diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md
index 72bca49dd6..603cb7b582 100644
--- a/.github/ISSUE_TEMPLATE/bug.md
+++ b/.github/ISSUE_TEMPLATE/bug.md
@@ -6,7 +6,7 @@ labels: 'type:bug'
assignees: ''
---
-Our support team has aggregated some common issues and their solutions from past which are faced while running or interacting with a bor client. In order to prevent redundant efforts, we would encourage you to have a look at the [FAQ's section](https://wiki.polygon.technology/docs/faq/technical-faqs/) of our documentation mentioning the same, before filing an issue here. In case of additional support, you can also join our [discord](https://discord.com/invite/0xPolygonDevs) server
+Our support team has aggregated some common issues and their solutions from past which are faced while running or interacting with a bor client. In order to prevent redundant efforts, we would encourage you to have a look at the [FAQ's section](https://wiki.polygon.technology/docs/faq/technical-faqs/) of our documentation mentioning the same, before filing an issue here. In case of additional support, you can also join our [discord](https://discord.com/invite/0xPolygonCommunity) server
z -= q
- // note: this is NOT constant time
- if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) {
- var b uint64
- z[0], b = bits.Sub64(z[0], 13402431016077863595, 0)
- z[1], b = bits.Sub64(z[1], 2210141511517208575, b)
- z[2], b = bits.Sub64(z[2], 7435674573564081700, b)
- z[3], b = bits.Sub64(z[3], 7239337960414712511, b)
- z[4], b = bits.Sub64(z[4], 5412103778470702295, b)
- z[5], _ = bits.Sub64(z[5], 1873798617647539866, b)
- }
-}
-
-func addAssign(x, y *fe) {
- var carry uint64
-
- x[0], carry = bits.Add64(x[0], y[0], 0)
- x[1], carry = bits.Add64(x[1], y[1], carry)
- x[2], carry = bits.Add64(x[2], y[2], carry)
- x[3], carry = bits.Add64(x[3], y[3], carry)
- x[4], carry = bits.Add64(x[4], y[4], carry)
- x[5], _ = bits.Add64(x[5], y[5], carry)
-
- // if z > q --> z -= q
- // note: this is NOT constant time
- if !(x[5] < 1873798617647539866 || (x[5] == 1873798617647539866 && (x[4] < 5412103778470702295 || (x[4] == 5412103778470702295 && (x[3] < 7239337960414712511 || (x[3] == 7239337960414712511 && (x[2] < 7435674573564081700 || (x[2] == 7435674573564081700 && (x[1] < 2210141511517208575 || (x[1] == 2210141511517208575 && (x[0] < 13402431016077863595))))))))))) {
- var b uint64
- x[0], b = bits.Sub64(x[0], 13402431016077863595, 0)
- x[1], b = bits.Sub64(x[1], 2210141511517208575, b)
- x[2], b = bits.Sub64(x[2], 7435674573564081700, b)
- x[3], b = bits.Sub64(x[3], 7239337960414712511, b)
- x[4], b = bits.Sub64(x[4], 5412103778470702295, b)
- x[5], _ = bits.Sub64(x[5], 1873798617647539866, b)
- }
-}
-
-func ladd(z, x, y *fe) {
- var carry uint64
- z[0], carry = bits.Add64(x[0], y[0], 0)
- z[1], carry = bits.Add64(x[1], y[1], carry)
- z[2], carry = bits.Add64(x[2], y[2], carry)
- z[3], carry = bits.Add64(x[3], y[3], carry)
- z[4], carry = bits.Add64(x[4], y[4], carry)
- z[5], _ = bits.Add64(x[5], y[5], carry)
-}
-
-func laddAssign(x, y *fe) {
- var carry uint64
- x[0], carry = bits.Add64(x[0], y[0], 0)
- x[1], carry = bits.Add64(x[1], y[1], carry)
- x[2], carry = bits.Add64(x[2], y[2], carry)
- x[3], carry = bits.Add64(x[3], y[3], carry)
- x[4], carry = bits.Add64(x[4], y[4], carry)
- x[5], _ = bits.Add64(x[5], y[5], carry)
-}
-
-func double(z, x *fe) {
- var carry uint64
-
- z[0], carry = bits.Add64(x[0], x[0], 0)
- z[1], carry = bits.Add64(x[1], x[1], carry)
- z[2], carry = bits.Add64(x[2], x[2], carry)
- z[3], carry = bits.Add64(x[3], x[3], carry)
- z[4], carry = bits.Add64(x[4], x[4], carry)
- z[5], _ = bits.Add64(x[5], x[5], carry)
-
- // if z > q --> z -= q
- // note: this is NOT constant time
- if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) {
- var b uint64
- z[0], b = bits.Sub64(z[0], 13402431016077863595, 0)
- z[1], b = bits.Sub64(z[1], 2210141511517208575, b)
- z[2], b = bits.Sub64(z[2], 7435674573564081700, b)
- z[3], b = bits.Sub64(z[3], 7239337960414712511, b)
- z[4], b = bits.Sub64(z[4], 5412103778470702295, b)
- z[5], _ = bits.Sub64(z[5], 1873798617647539866, b)
- }
-}
-
-func doubleAssign(z *fe) {
- var carry uint64
-
- z[0], carry = bits.Add64(z[0], z[0], 0)
- z[1], carry = bits.Add64(z[1], z[1], carry)
- z[2], carry = bits.Add64(z[2], z[2], carry)
- z[3], carry = bits.Add64(z[3], z[3], carry)
- z[4], carry = bits.Add64(z[4], z[4], carry)
- z[5], _ = bits.Add64(z[5], z[5], carry)
-
- // if z > q --> z -= q
- // note: this is NOT constant time
- if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) {
- var b uint64
- z[0], b = bits.Sub64(z[0], 13402431016077863595, 0)
- z[1], b = bits.Sub64(z[1], 2210141511517208575, b)
- z[2], b = bits.Sub64(z[2], 7435674573564081700, b)
- z[3], b = bits.Sub64(z[3], 7239337960414712511, b)
- z[4], b = bits.Sub64(z[4], 5412103778470702295, b)
- z[5], _ = bits.Sub64(z[5], 1873798617647539866, b)
- }
-}
-
-func ldouble(z, x *fe) {
- var carry uint64
-
- z[0], carry = bits.Add64(x[0], x[0], 0)
- z[1], carry = bits.Add64(x[1], x[1], carry)
- z[2], carry = bits.Add64(x[2], x[2], carry)
- z[3], carry = bits.Add64(x[3], x[3], carry)
- z[4], carry = bits.Add64(x[4], x[4], carry)
- z[5], _ = bits.Add64(x[5], x[5], carry)
-}
-
-func sub(z, x, y *fe) {
- var b uint64
- z[0], b = bits.Sub64(x[0], y[0], 0)
- z[1], b = bits.Sub64(x[1], y[1], b)
- z[2], b = bits.Sub64(x[2], y[2], b)
- z[3], b = bits.Sub64(x[3], y[3], b)
- z[4], b = bits.Sub64(x[4], y[4], b)
- z[5], b = bits.Sub64(x[5], y[5], b)
-
- if b != 0 {
- var c uint64
- z[0], c = bits.Add64(z[0], 13402431016077863595, 0)
- z[1], c = bits.Add64(z[1], 2210141511517208575, c)
- z[2], c = bits.Add64(z[2], 7435674573564081700, c)
- z[3], c = bits.Add64(z[3], 7239337960414712511, c)
- z[4], c = bits.Add64(z[4], 5412103778470702295, c)
- z[5], _ = bits.Add64(z[5], 1873798617647539866, c)
- }
-}
-
-func subAssign(z, x *fe) {
- var b uint64
- z[0], b = bits.Sub64(z[0], x[0], 0)
- z[1], b = bits.Sub64(z[1], x[1], b)
- z[2], b = bits.Sub64(z[2], x[2], b)
- z[3], b = bits.Sub64(z[3], x[3], b)
- z[4], b = bits.Sub64(z[4], x[4], b)
- z[5], b = bits.Sub64(z[5], x[5], b)
-
- if b != 0 {
- var c uint64
- z[0], c = bits.Add64(z[0], 13402431016077863595, 0)
- z[1], c = bits.Add64(z[1], 2210141511517208575, c)
- z[2], c = bits.Add64(z[2], 7435674573564081700, c)
- z[3], c = bits.Add64(z[3], 7239337960414712511, c)
- z[4], c = bits.Add64(z[4], 5412103778470702295, c)
- z[5], _ = bits.Add64(z[5], 1873798617647539866, c)
- }
-}
-
-func lsubAssign(z, x *fe) {
- var b uint64
- z[0], b = bits.Sub64(z[0], x[0], 0)
- z[1], b = bits.Sub64(z[1], x[1], b)
- z[2], b = bits.Sub64(z[2], x[2], b)
- z[3], b = bits.Sub64(z[3], x[3], b)
- z[4], b = bits.Sub64(z[4], x[4], b)
- z[5], _ = bits.Sub64(z[5], x[5], b)
-}
-
-func neg(z *fe, x *fe) {
- if x.isZero() {
- z.zero()
- return
- }
-
- var borrow uint64
- z[0], borrow = bits.Sub64(13402431016077863595, x[0], 0)
- z[1], borrow = bits.Sub64(2210141511517208575, x[1], borrow)
- z[2], borrow = bits.Sub64(7435674573564081700, x[2], borrow)
- z[3], borrow = bits.Sub64(7239337960414712511, x[3], borrow)
- z[4], borrow = bits.Sub64(5412103778470702295, x[4], borrow)
- z[5], _ = bits.Sub64(1873798617647539866, x[5], borrow)
-}
-
-func mul(z, x, y *fe) {
- var t [6]uint64
-
- var c [3]uint64
- {
- // round 0
- v := x[0]
- c[1], c[0] = bits.Mul64(v, y[0])
- m := c[0] * 9940570264628428797
- c[2] = madd0(m, 13402431016077863595, c[0])
- c[1], c[0] = madd1(v, y[1], c[1])
- c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
- c[1], c[0] = madd1(v, y[2], c[1])
- c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
- c[1], c[0] = madd1(v, y[3], c[1])
- c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
- c[1], c[0] = madd1(v, y[4], c[1])
- c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
- c[1], c[0] = madd1(v, y[5], c[1])
- t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
- }
- {
- // round 1
- v := x[1]
- c[1], c[0] = madd1(v, y[0], t[0])
- m := c[0] * 9940570264628428797
- c[2] = madd0(m, 13402431016077863595, c[0])
- c[1], c[0] = madd2(v, y[1], c[1], t[1])
- c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
- c[1], c[0] = madd2(v, y[2], c[1], t[2])
- c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
- c[1], c[0] = madd2(v, y[3], c[1], t[3])
- c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
- c[1], c[0] = madd2(v, y[4], c[1], t[4])
- c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
- c[1], c[0] = madd2(v, y[5], c[1], t[5])
- t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
- }
- {
- // round 2
- v := x[2]
- c[1], c[0] = madd1(v, y[0], t[0])
- m := c[0] * 9940570264628428797
- c[2] = madd0(m, 13402431016077863595, c[0])
- c[1], c[0] = madd2(v, y[1], c[1], t[1])
- c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
- c[1], c[0] = madd2(v, y[2], c[1], t[2])
- c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
- c[1], c[0] = madd2(v, y[3], c[1], t[3])
- c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
- c[1], c[0] = madd2(v, y[4], c[1], t[4])
- c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
- c[1], c[0] = madd2(v, y[5], c[1], t[5])
- t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
- }
- {
- // round 3
- v := x[3]
- c[1], c[0] = madd1(v, y[0], t[0])
- m := c[0] * 9940570264628428797
- c[2] = madd0(m, 13402431016077863595, c[0])
- c[1], c[0] = madd2(v, y[1], c[1], t[1])
- c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
- c[1], c[0] = madd2(v, y[2], c[1], t[2])
- c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
- c[1], c[0] = madd2(v, y[3], c[1], t[3])
- c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
- c[1], c[0] = madd2(v, y[4], c[1], t[4])
- c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
- c[1], c[0] = madd2(v, y[5], c[1], t[5])
- t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
- }
- {
- // round 4
- v := x[4]
- c[1], c[0] = madd1(v, y[0], t[0])
- m := c[0] * 9940570264628428797
- c[2] = madd0(m, 13402431016077863595, c[0])
- c[1], c[0] = madd2(v, y[1], c[1], t[1])
- c[2], t[0] = madd2(m, 2210141511517208575, c[2], c[0])
- c[1], c[0] = madd2(v, y[2], c[1], t[2])
- c[2], t[1] = madd2(m, 7435674573564081700, c[2], c[0])
- c[1], c[0] = madd2(v, y[3], c[1], t[3])
- c[2], t[2] = madd2(m, 7239337960414712511, c[2], c[0])
- c[1], c[0] = madd2(v, y[4], c[1], t[4])
- c[2], t[3] = madd2(m, 5412103778470702295, c[2], c[0])
- c[1], c[0] = madd2(v, y[5], c[1], t[5])
- t[5], t[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
- }
- {
- // round 5
- v := x[5]
- c[1], c[0] = madd1(v, y[0], t[0])
- m := c[0] * 9940570264628428797
- c[2] = madd0(m, 13402431016077863595, c[0])
- c[1], c[0] = madd2(v, y[1], c[1], t[1])
- c[2], z[0] = madd2(m, 2210141511517208575, c[2], c[0])
- c[1], c[0] = madd2(v, y[2], c[1], t[2])
- c[2], z[1] = madd2(m, 7435674573564081700, c[2], c[0])
- c[1], c[0] = madd2(v, y[3], c[1], t[3])
- c[2], z[2] = madd2(m, 7239337960414712511, c[2], c[0])
- c[1], c[0] = madd2(v, y[4], c[1], t[4])
- c[2], z[3] = madd2(m, 5412103778470702295, c[2], c[0])
- c[1], c[0] = madd2(v, y[5], c[1], t[5])
- z[5], z[4] = madd3(m, 1873798617647539866, c[0], c[2], c[1])
- }
-
- // if z > q --> z -= q
- // note: this is NOT constant time
- if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) {
- var b uint64
- z[0], b = bits.Sub64(z[0], 13402431016077863595, 0)
- z[1], b = bits.Sub64(z[1], 2210141511517208575, b)
- z[2], b = bits.Sub64(z[2], 7435674573564081700, b)
- z[3], b = bits.Sub64(z[3], 7239337960414712511, b)
- z[4], b = bits.Sub64(z[4], 5412103778470702295, b)
- z[5], _ = bits.Sub64(z[5], 1873798617647539866, b)
- }
-}
-
-func square(z, x *fe) {
- var p [6]uint64
-
- var u, v uint64
- {
- // round 0
- u, p[0] = bits.Mul64(x[0], x[0])
- m := p[0] * 9940570264628428797
- C := madd0(m, 13402431016077863595, p[0])
-
- var t uint64
- t, u, v = madd1sb(x[0], x[1], u)
- C, p[0] = madd2(m, 2210141511517208575, v, C)
- t, u, v = madd1s(x[0], x[2], t, u)
- C, p[1] = madd2(m, 7435674573564081700, v, C)
- t, u, v = madd1s(x[0], x[3], t, u)
- C, p[2] = madd2(m, 7239337960414712511, v, C)
- t, u, v = madd1s(x[0], x[4], t, u)
- C, p[3] = madd2(m, 5412103778470702295, v, C)
- _, u, v = madd1s(x[0], x[5], t, u)
- p[5], p[4] = madd3(m, 1873798617647539866, v, C, u)
- }
- {
- // round 1
- m := p[0] * 9940570264628428797
- C := madd0(m, 13402431016077863595, p[0])
- u, v = madd1(x[1], x[1], p[1])
- C, p[0] = madd2(m, 2210141511517208575, v, C)
-
- var t uint64
- t, u, v = madd2sb(x[1], x[2], p[2], u)
- C, p[1] = madd2(m, 7435674573564081700, v, C)
- t, u, v = madd2s(x[1], x[3], p[3], t, u)
- C, p[2] = madd2(m, 7239337960414712511, v, C)
- t, u, v = madd2s(x[1], x[4], p[4], t, u)
- C, p[3] = madd2(m, 5412103778470702295, v, C)
- _, u, v = madd2s(x[1], x[5], p[5], t, u)
- p[5], p[4] = madd3(m, 1873798617647539866, v, C, u)
- }
- {
- // round 2
- m := p[0] * 9940570264628428797
- C := madd0(m, 13402431016077863595, p[0])
- C, p[0] = madd2(m, 2210141511517208575, p[1], C)
- u, v = madd1(x[2], x[2], p[2])
- C, p[1] = madd2(m, 7435674573564081700, v, C)
-
- var t uint64
- t, u, v = madd2sb(x[2], x[3], p[3], u)
- C, p[2] = madd2(m, 7239337960414712511, v, C)
- t, u, v = madd2s(x[2], x[4], p[4], t, u)
- C, p[3] = madd2(m, 5412103778470702295, v, C)
- _, u, v = madd2s(x[2], x[5], p[5], t, u)
- p[5], p[4] = madd3(m, 1873798617647539866, v, C, u)
- }
- {
- // round 3
- m := p[0] * 9940570264628428797
- C := madd0(m, 13402431016077863595, p[0])
- C, p[0] = madd2(m, 2210141511517208575, p[1], C)
- C, p[1] = madd2(m, 7435674573564081700, p[2], C)
- u, v = madd1(x[3], x[3], p[3])
- C, p[2] = madd2(m, 7239337960414712511, v, C)
-
- var t uint64
- t, u, v = madd2sb(x[3], x[4], p[4], u)
- C, p[3] = madd2(m, 5412103778470702295, v, C)
- _, u, v = madd2s(x[3], x[5], p[5], t, u)
- p[5], p[4] = madd3(m, 1873798617647539866, v, C, u)
- }
- {
- // round 4
- m := p[0] * 9940570264628428797
- C := madd0(m, 13402431016077863595, p[0])
- C, p[0] = madd2(m, 2210141511517208575, p[1], C)
- C, p[1] = madd2(m, 7435674573564081700, p[2], C)
- C, p[2] = madd2(m, 7239337960414712511, p[3], C)
- u, v = madd1(x[4], x[4], p[4])
- C, p[3] = madd2(m, 5412103778470702295, v, C)
- _, u, v = madd2sb(x[4], x[5], p[5], u)
- p[5], p[4] = madd3(m, 1873798617647539866, v, C, u)
- }
- {
- // round 5
- m := p[0] * 9940570264628428797
- C := madd0(m, 13402431016077863595, p[0])
- C, z[0] = madd2(m, 2210141511517208575, p[1], C)
- C, z[1] = madd2(m, 7435674573564081700, p[2], C)
- C, z[2] = madd2(m, 7239337960414712511, p[3], C)
- C, z[3] = madd2(m, 5412103778470702295, p[4], C)
- u, v = madd1(x[5], x[5], p[5])
- z[5], z[4] = madd3(m, 1873798617647539866, v, C, u)
- }
-
- // if z > q --> z -= q
- // note: this is NOT constant time
- if !(z[5] < 1873798617647539866 || (z[5] == 1873798617647539866 && (z[4] < 5412103778470702295 || (z[4] == 5412103778470702295 && (z[3] < 7239337960414712511 || (z[3] == 7239337960414712511 && (z[2] < 7435674573564081700 || (z[2] == 7435674573564081700 && (z[1] < 2210141511517208575 || (z[1] == 2210141511517208575 && (z[0] < 13402431016077863595))))))))))) {
- var b uint64
- z[0], b = bits.Sub64(z[0], 13402431016077863595, 0)
- z[1], b = bits.Sub64(z[1], 2210141511517208575, b)
- z[2], b = bits.Sub64(z[2], 7435674573564081700, b)
- z[3], b = bits.Sub64(z[3], 7239337960414712511, b)
- z[4], b = bits.Sub64(z[4], 5412103778470702295, b)
- z[5], _ = bits.Sub64(z[5], 1873798617647539866, b)
- }
-}
-
-// arith.go
-// Copyright 2020 ConsenSys AG
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Code generated by goff DO NOT EDIT
-
-func madd(a, b, t, u, v uint64) (uint64, uint64, uint64) {
- var carry uint64
-
- hi, lo := bits.Mul64(a, b)
- v, carry = bits.Add64(lo, v, 0)
- u, carry = bits.Add64(hi, u, carry)
- t, _ = bits.Add64(t, 0, carry)
-
- return t, u, v
-}
-
-// madd0 hi = a*b + c (discards lo bits)
-func madd0(a, b, c uint64) (hi uint64) {
- var carry, lo uint64
- hi, lo = bits.Mul64(a, b)
- _, carry = bits.Add64(lo, c, 0)
- hi, _ = bits.Add64(hi, 0, carry)
-
- return
-}
-
-// madd1 hi, lo = a*b + c
-func madd1(a, b, c uint64) (hi uint64, lo uint64) {
- var carry uint64
-
- hi, lo = bits.Mul64(a, b)
- lo, carry = bits.Add64(lo, c, 0)
- hi, _ = bits.Add64(hi, 0, carry)
-
- return
-}
-
-// madd2 hi, lo = a*b + c + d
-func madd2(a, b, c, d uint64) (hi uint64, lo uint64) {
- var carry uint64
-
- hi, lo = bits.Mul64(a, b)
- c, carry = bits.Add64(c, d, 0)
- hi, _ = bits.Add64(hi, 0, carry)
- lo, carry = bits.Add64(lo, c, 0)
- hi, _ = bits.Add64(hi, 0, carry)
-
- return
-}
-
-// madd2s superhi, hi, lo = 2*a*b + c + d + e
-func madd2s(a, b, c, d, e uint64) (superhi, hi, lo uint64) {
- var carry, sum uint64
-
- hi, lo = bits.Mul64(a, b)
- lo, carry = bits.Add64(lo, lo, 0)
- hi, superhi = bits.Add64(hi, hi, carry)
-
- sum, carry = bits.Add64(c, e, 0)
- hi, _ = bits.Add64(hi, 0, carry)
- lo, carry = bits.Add64(lo, sum, 0)
- hi, _ = bits.Add64(hi, 0, carry)
- hi, _ = bits.Add64(hi, 0, d)
-
- return
-}
-
-func madd1s(a, b, d, e uint64) (superhi, hi, lo uint64) {
- var carry uint64
-
- hi, lo = bits.Mul64(a, b)
- lo, carry = bits.Add64(lo, lo, 0)
- hi, superhi = bits.Add64(hi, hi, carry)
- lo, carry = bits.Add64(lo, e, 0)
- hi, _ = bits.Add64(hi, 0, carry)
- hi, _ = bits.Add64(hi, 0, d)
-
- return
-}
-
-func madd2sb(a, b, c, e uint64) (superhi, hi, lo uint64) {
- var carry, sum uint64
-
- hi, lo = bits.Mul64(a, b)
- lo, carry = bits.Add64(lo, lo, 0)
- hi, superhi = bits.Add64(hi, hi, carry)
-
- sum, carry = bits.Add64(c, e, 0)
- hi, _ = bits.Add64(hi, 0, carry)
- lo, carry = bits.Add64(lo, sum, 0)
- hi, _ = bits.Add64(hi, 0, carry)
-
- return
-}
-
-func madd1sb(a, b, e uint64) (superhi, hi, lo uint64) {
- var carry uint64
-
- hi, lo = bits.Mul64(a, b)
- lo, carry = bits.Add64(lo, lo, 0)
- hi, superhi = bits.Add64(hi, hi, carry)
- lo, carry = bits.Add64(lo, e, 0)
- hi, _ = bits.Add64(hi, 0, carry)
-
- return
-}
-
-func madd3(a, b, c, d, e uint64) (hi uint64, lo uint64) {
- var carry uint64
-
- hi, lo = bits.Mul64(a, b)
- c, carry = bits.Add64(c, d, 0)
- hi, _ = bits.Add64(hi, 0, carry)
- lo, carry = bits.Add64(lo, c, 0)
- hi, _ = bits.Add64(hi, e, carry)
-
- return
-}
diff --git a/crypto/bls12381/arithmetic_x86.s b/crypto/bls12381/arithmetic_x86.s
deleted file mode 100644
index 2cebbc46f7..0000000000
--- a/crypto/bls12381/arithmetic_x86.s
+++ /dev/null
@@ -1,2150 +0,0 @@
-// +build amd64,blsasm amd64,blsadx
-
-#include "textflag.h"
-
-// addition w/ modular reduction
-// a = (a + b) % p
-TEXT ·addAssign(SB), NOSPLIT, $0-16
- // |
- MOVQ a+0(FP), DI
- MOVQ b+8(FP), SI
-
- // |
- MOVQ (DI), R8
- MOVQ 8(DI), R9
- MOVQ 16(DI), R10
- MOVQ 24(DI), R11
- MOVQ 32(DI), R12
- MOVQ 40(DI), R13
-
- // |
- ADDQ (SI), R8
- ADCQ 8(SI), R9
- ADCQ 16(SI), R10
- ADCQ 24(SI), R11
- ADCQ 32(SI), R12
- ADCQ 40(SI), R13
-
- // |
- MOVQ R8, R14
- MOVQ R9, R15
- MOVQ R10, CX
- MOVQ R11, DX
- MOVQ R12, SI
- MOVQ R13, BX
- MOVQ $0xb9feffffffffaaab, AX
- SUBQ AX, R14
- MOVQ $0x1eabfffeb153ffff, AX
- SBBQ AX, R15
- MOVQ $0x6730d2a0f6b0f624, AX
- SBBQ AX, CX
- MOVQ $0x64774b84f38512bf, AX
- SBBQ AX, DX
- MOVQ $0x4b1ba7b6434bacd7, AX
- SBBQ AX, SI
- MOVQ $0x1a0111ea397fe69a, AX
- SBBQ AX, BX
- CMOVQCC R14, R8
- CMOVQCC R15, R9
- CMOVQCC CX, R10
- CMOVQCC DX, R11
- CMOVQCC SI, R12
- CMOVQCC BX, R13
-
- // |
- MOVQ R8, (DI)
- MOVQ R9, 8(DI)
- MOVQ R10, 16(DI)
- MOVQ R11, 24(DI)
- MOVQ R12, 32(DI)
- MOVQ R13, 40(DI)
- RET
-
-/* | end */
-
-
-// addition w/ modular reduction
-// c = (a + b) % p
-TEXT ·add(SB), NOSPLIT, $0-24
- // |
- MOVQ a+8(FP), DI
- MOVQ b+16(FP), SI
-
- // |
- MOVQ (DI), R8
- MOVQ 8(DI), R9
- MOVQ 16(DI), R10
- MOVQ 24(DI), R11
- MOVQ 32(DI), R12
- MOVQ 40(DI), R13
-
- // |
- ADDQ (SI), R8
- ADCQ 8(SI), R9
- ADCQ 16(SI), R10
- ADCQ 24(SI), R11
- ADCQ 32(SI), R12
- ADCQ 40(SI), R13
-
- // |
- MOVQ R8, R14
- MOVQ R9, R15
- MOVQ R10, CX
- MOVQ R11, DX
- MOVQ R12, SI
- MOVQ R13, BX
- MOVQ $0xb9feffffffffaaab, DI
- SUBQ DI, R14
- MOVQ $0x1eabfffeb153ffff, DI
- SBBQ DI, R15
- MOVQ $0x6730d2a0f6b0f624, DI
- SBBQ DI, CX
- MOVQ $0x64774b84f38512bf, DI
- SBBQ DI, DX
- MOVQ $0x4b1ba7b6434bacd7, DI
- SBBQ DI, SI
- MOVQ $0x1a0111ea397fe69a, DI
- SBBQ DI, BX
- CMOVQCC R14, R8
- CMOVQCC R15, R9
- CMOVQCC CX, R10
- CMOVQCC DX, R11
- CMOVQCC SI, R12
- CMOVQCC BX, R13
-
- // |
- MOVQ c+0(FP), DI
- MOVQ R8, (DI)
- MOVQ R9, 8(DI)
- MOVQ R10, 16(DI)
- MOVQ R11, 24(DI)
- MOVQ R12, 32(DI)
- MOVQ R13, 40(DI)
- RET
-/* | end */
-
-
-// addition w/o reduction check
-// c = (a + b)
-TEXT ·ladd(SB), NOSPLIT, $0-24
- // |
- MOVQ a+8(FP), DI
- MOVQ b+16(FP), SI
-
- // |
- MOVQ (DI), R8
- MOVQ 8(DI), R9
- MOVQ 16(DI), R10
- MOVQ 24(DI), R11
- MOVQ 32(DI), R12
- MOVQ 40(DI), R13
-
- // |
- ADDQ (SI), R8
- ADCQ 8(SI), R9
- ADCQ 16(SI), R10
- ADCQ 24(SI), R11
- ADCQ 32(SI), R12
- ADCQ 40(SI), R13
-
- // |
- MOVQ c+0(FP), DI
- MOVQ R8, (DI)
- MOVQ R9, 8(DI)
- MOVQ R10, 16(DI)
- MOVQ R11, 24(DI)
- MOVQ R12, 32(DI)
- MOVQ R13, 40(DI)
- RET
-/* | end */
-
-
-// addition w/o reduction check
-// a = a + b
-TEXT ·laddAssign(SB), NOSPLIT, $0-16
- // |
- MOVQ a+0(FP), DI
- MOVQ b+8(FP), SI
-
- // |
- MOVQ (DI), R8
- MOVQ 8(DI), R9
- MOVQ 16(DI), R10
- MOVQ 24(DI), R11
- MOVQ 32(DI), R12
- MOVQ 40(DI), R13
-
- // |
- ADDQ (SI), R8
- ADCQ 8(SI), R9
- ADCQ 16(SI), R10
- ADCQ 24(SI), R11
- ADCQ 32(SI), R12
- ADCQ 40(SI), R13
-
- // |
- MOVQ a+0(FP), DI
- MOVQ R8, (DI)
- MOVQ R9, 8(DI)
- MOVQ R10, 16(DI)
- MOVQ R11, 24(DI)
- MOVQ R12, 32(DI)
- MOVQ R13, 40(DI)
- RET
-/* | end */
-
-
-// subtraction w/ modular reduction
-// c = (a - b) % p
-TEXT ·sub(SB), NOSPLIT, $0-24
- // |
- MOVQ a+8(FP), DI
- MOVQ b+16(FP), SI
- XORQ AX, AX
-
- // |
- MOVQ (DI), R8
- MOVQ 8(DI), R9
- MOVQ 16(DI), R10
- MOVQ 24(DI), R11
- MOVQ 32(DI), R12
- MOVQ 40(DI), R13
- SUBQ (SI), R8
- SBBQ 8(SI), R9
- SBBQ 16(SI), R10
- SBBQ 24(SI), R11
- SBBQ 32(SI), R12
- SBBQ 40(SI), R13
-
- // |
- MOVQ $0xb9feffffffffaaab, R14
- MOVQ $0x1eabfffeb153ffff, R15
- MOVQ $0x6730d2a0f6b0f624, CX
- MOVQ $0x64774b84f38512bf, DX
- MOVQ $0x4b1ba7b6434bacd7, SI
- MOVQ $0x1a0111ea397fe69a, BX
- CMOVQCC AX, R14
- CMOVQCC AX, R15
- CMOVQCC AX, CX
- CMOVQCC AX, DX
- CMOVQCC AX, SI
- CMOVQCC AX, BX
- ADDQ R14, R8
- ADCQ R15, R9
- ADCQ CX, R10
- ADCQ DX, R11
- ADCQ SI, R12
- ADCQ BX, R13
-
- // |
- MOVQ c+0(FP), DI
- MOVQ R8, (DI)
- MOVQ R9, 8(DI)
- MOVQ R10, 16(DI)
- MOVQ R11, 24(DI)
- MOVQ R12, 32(DI)
- MOVQ R13, 40(DI)
- RET
-/* | end */
-
-
-// subtraction w/ modular reduction
-// a = (a - b) % p
-TEXT ·subAssign(SB), NOSPLIT, $0-16
- // |
- MOVQ a+0(FP), DI
- MOVQ b+8(FP), SI
- XORQ AX, AX
-
- // |
- MOVQ (DI), R8
- MOVQ 8(DI), R9
- MOVQ 16(DI), R10
- MOVQ 24(DI), R11
- MOVQ 32(DI), R12
- MOVQ 40(DI), R13
- SUBQ (SI), R8
- SBBQ 8(SI), R9
- SBBQ 16(SI), R10
- SBBQ 24(SI), R11
- SBBQ 32(SI), R12
- SBBQ 40(SI), R13
-
- // |
- MOVQ $0xb9feffffffffaaab, R14
- MOVQ $0x1eabfffeb153ffff, R15
- MOVQ $0x6730d2a0f6b0f624, CX
- MOVQ $0x64774b84f38512bf, DX
- MOVQ $0x4b1ba7b6434bacd7, SI
- MOVQ $0x1a0111ea397fe69a, BX
- CMOVQCC AX, R14
- CMOVQCC AX, R15
- CMOVQCC AX, CX
- CMOVQCC AX, DX
- CMOVQCC AX, SI
- CMOVQCC AX, BX
- ADDQ R14, R8
- ADCQ R15, R9
- ADCQ CX, R10
- ADCQ DX, R11
- ADCQ SI, R12
- ADCQ BX, R13
-
- // |
- MOVQ a+0(FP), DI
- MOVQ R8, (DI)
- MOVQ R9, 8(DI)
- MOVQ R10, 16(DI)
- MOVQ R11, 24(DI)
- MOVQ R12, 32(DI)
- MOVQ R13, 40(DI)
- RET
-/* | end */
-
-
-// subtraction w/o reduction check
-// a = (a - b)
-TEXT ·lsubAssign(SB), NOSPLIT, $0-16
- // |
- MOVQ a+0(FP), DI
- MOVQ b+8(FP), SI
-
- // |
- MOVQ (DI), R8
- MOVQ 8(DI), R9
- MOVQ 16(DI), R10
- MOVQ 24(DI), R11
- MOVQ 32(DI), R12
- MOVQ 40(DI), R13
- SUBQ (SI), R8
- SBBQ 8(SI), R9
- SBBQ 16(SI), R10
- SBBQ 24(SI), R11
- SBBQ 32(SI), R12
- SBBQ 40(SI), R13
-
- // |
- MOVQ a+0(FP), DI
- MOVQ R8, (DI)
- MOVQ R9, 8(DI)
- MOVQ R10, 16(DI)
- MOVQ R11, 24(DI)
- MOVQ R12, 32(DI)
- MOVQ R13, 40(DI)
- RET
-/* | end */
-
-// doubling w/ reduction
-// c = (2 * a) % p
-TEXT ·double(SB), NOSPLIT, $0-16
- // |
- MOVQ a+8(FP), DI
-
- MOVQ (DI), R8
- MOVQ 8(DI), R9
- MOVQ 16(DI), R10
- MOVQ 24(DI), R11
- MOVQ 32(DI), R12
- MOVQ 40(DI), R13
- ADDQ R8, R8
- ADCQ R9, R9
- ADCQ R10, R10
- ADCQ R11, R11
- ADCQ R12, R12
- ADCQ R13, R13
-
- // |
- MOVQ R8, R14
- MOVQ R9, R15
- MOVQ R10, CX
- MOVQ R11, DX
- MOVQ R12, SI
- MOVQ R13, BX
- MOVQ $0xb9feffffffffaaab, DI
- SUBQ DI, R14
- MOVQ $0x1eabfffeb153ffff, DI
- SBBQ DI, R15
- MOVQ $0x6730d2a0f6b0f624, DI
- SBBQ DI, CX
- MOVQ $0x64774b84f38512bf, DI
- SBBQ DI, DX
- MOVQ $0x4b1ba7b6434bacd7, DI
- SBBQ DI, SI
- MOVQ $0x1a0111ea397fe69a, DI
- SBBQ DI, BX
- CMOVQCC R14, R8
- CMOVQCC R15, R9
- CMOVQCC CX, R10
- CMOVQCC DX, R11
- CMOVQCC SI, R12
- CMOVQCC BX, R13
-
- // |
- MOVQ c+0(FP), DI
- MOVQ R8, (DI)
- MOVQ R9, 8(DI)
- MOVQ R10, 16(DI)
- MOVQ R11, 24(DI)
- MOVQ R12, 32(DI)
- MOVQ R13, 40(DI)
- RET
-/* | end */
-
-
-// doubling w/ reduction
-// a = (2 * a) % p
-TEXT ·doubleAssign(SB), NOSPLIT, $0-8
- // |
- MOVQ a+0(FP), DI
-
- MOVQ (DI), R8
- MOVQ 8(DI), R9
- MOVQ 16(DI), R10
- MOVQ 24(DI), R11
- MOVQ 32(DI), R12
- MOVQ 40(DI), R13
- ADDQ R8, R8
- ADCQ R9, R9
- ADCQ R10, R10
- ADCQ R11, R11
- ADCQ R12, R12
- ADCQ R13, R13
-
- // |
- MOVQ R8, R14
- MOVQ R9, R15
- MOVQ R10, CX
- MOVQ R11, DX
- MOVQ R12, SI
- MOVQ R13, BX
- MOVQ $0xb9feffffffffaaab, AX
- SUBQ AX, R14
- MOVQ $0x1eabfffeb153ffff, AX
- SBBQ AX, R15
- MOVQ $0x6730d2a0f6b0f624, AX
- SBBQ AX, CX
- MOVQ $0x64774b84f38512bf, AX
- SBBQ AX, DX
- MOVQ $0x4b1ba7b6434bacd7, AX
- SBBQ AX, SI
- MOVQ $0x1a0111ea397fe69a, AX
- SBBQ AX, BX
- CMOVQCC R14, R8
- CMOVQCC R15, R9
- CMOVQCC CX, R10
- CMOVQCC DX, R11
- CMOVQCC SI, R12
- CMOVQCC BX, R13
-
- MOVQ R8, (DI)
- MOVQ R9, 8(DI)
- MOVQ R10, 16(DI)
- MOVQ R11, 24(DI)
- MOVQ R12, 32(DI)
- MOVQ R13, 40(DI)
- RET
-/* | end */
-
-
-// doubling w/o reduction
-// c = 2 * a
-TEXT ·ldouble(SB), NOSPLIT, $0-16
- // |
- MOVQ a+8(FP), DI
-
- MOVQ (DI), R8
- MOVQ 8(DI), R9
- MOVQ 16(DI), R10
- MOVQ 24(DI), R11
- MOVQ 32(DI), R12
- MOVQ 40(DI), R13
-
- // |
- ADDQ R8, R8
- ADCQ R9, R9
- ADCQ R10, R10
- ADCQ R11, R11
- ADCQ R12, R12
- ADCQ R13, R13
-
- // |
- MOVQ c+0(FP), DI
- MOVQ R8, (DI)
- MOVQ R9, 8(DI)
- MOVQ R10, 16(DI)
- MOVQ R11, 24(DI)
- MOVQ R12, 32(DI)
- MOVQ R13, 40(DI)
-
- RET
-/* | end */
-
-
-TEXT ·_neg(SB), NOSPLIT, $0-16
- // |
- MOVQ a+8(FP), DI
-
- // |
- MOVQ $0xb9feffffffffaaab, R8
- MOVQ $0x1eabfffeb153ffff, R9
- MOVQ $0x6730d2a0f6b0f624, R10
- MOVQ $0x64774b84f38512bf, R11
- MOVQ $0x4b1ba7b6434bacd7, R12
- MOVQ $0x1a0111ea397fe69a, R13
- SUBQ (DI), R8
- SBBQ 8(DI), R9
- SBBQ 16(DI), R10
- SBBQ 24(DI), R11
- SBBQ 32(DI), R12
- SBBQ 40(DI), R13
-
- // |
- MOVQ c+0(FP), DI
- MOVQ R8, (DI)
- MOVQ R9, 8(DI)
- MOVQ R10, 16(DI)
- MOVQ R11, 24(DI)
- MOVQ R12, 32(DI)
- MOVQ R13, 40(DI)
- RET
-/* | end */
-
-
-// multiplication without using MULX/ADX
-// c = a * b % p
-TEXT ·mulNoADX(SB), NOSPLIT, $24-24
- // |
-
-/* inputs */
-
- MOVQ a+8(FP), DI
- MOVQ b+16(FP), SI
- MOVQ $0x00, R9
- MOVQ $0x00, R10
- MOVQ $0x00, R11
- MOVQ $0x00, R12
- MOVQ $0x00, R13
- MOVQ $0x00, R14
- MOVQ $0x00, R15
-
- // |
-
-/* i0 */
-
- // | a0 @ CX
- MOVQ (DI), CX
-
- // | a0 * b0
- MOVQ (SI), AX
- MULQ CX
- MOVQ AX, (SP)
- MOVQ DX, R8
-
- // | a0 * b1
- MOVQ 8(SI), AX
- MULQ CX
- ADDQ AX, R8
- ADCQ DX, R9
-
- // | a0 * b2
- MOVQ 16(SI), AX
- MULQ CX
- ADDQ AX, R9
- ADCQ DX, R10
-
- // | a0 * b3
- MOVQ 24(SI), AX
- MULQ CX
- ADDQ AX, R10
- ADCQ DX, R11
-
- // | a0 * b4
- MOVQ 32(SI), AX
- MULQ CX
- ADDQ AX, R11
- ADCQ DX, R12
-
- // | a0 * b5
- MOVQ 40(SI), AX
- MULQ CX
- ADDQ AX, R12
- ADCQ DX, R13
-
- // |
-
-/* i1 */
-
- // | a1 @ CX
- MOVQ 8(DI), CX
- MOVQ $0x00, BX
-
- // | a1 * b0
- MOVQ (SI), AX
- MULQ CX
- ADDQ AX, R8
- ADCQ DX, R9
- ADCQ $0x00, R10
- ADCQ $0x00, BX
- MOVQ R8, 8(SP)
- MOVQ $0x00, R8
-
- // | a1 * b1
- MOVQ 8(SI), AX
- MULQ CX
- ADDQ AX, R9
- ADCQ DX, R10
- ADCQ BX, R11
- MOVQ $0x00, BX
- ADCQ $0x00, BX
-
- // | a1 * b2
- MOVQ 16(SI), AX
- MULQ CX
- ADDQ AX, R10
- ADCQ DX, R11
- ADCQ BX, R12
- MOVQ $0x00, BX
- ADCQ $0x00, BX
-
- // | a1 * b3
- MOVQ 24(SI), AX
- MULQ CX
- ADDQ AX, R11
- ADCQ DX, R12
- ADCQ BX, R13
- MOVQ $0x00, BX
- ADCQ $0x00, BX
-
- // | a1 * b4
- MOVQ 32(SI), AX
- MULQ CX
- ADDQ AX, R12
- ADCQ DX, R13
- ADCQ BX, R14
-
- // | a1 * b5
- MOVQ 40(SI), AX
- MULQ CX
- ADDQ AX, R13
- ADCQ DX, R14
-
- // |
-
-/* i2 */
-
- // | a2 @ CX
- MOVQ 16(DI), CX
- MOVQ $0x00, BX
-
- // | a2 * b0
- MOVQ (SI), AX
- MULQ CX
- ADDQ AX, R9
- ADCQ DX, R10
- ADCQ $0x00, R11
- ADCQ $0x00, BX
- MOVQ R9, 16(SP)
- MOVQ $0x00, R9
-
- // | a2 * b1
- MOVQ 8(SI), AX
- MULQ CX
- ADDQ AX, R10
- ADCQ DX, R11
- ADCQ BX, R12
- MOVQ $0x00, BX
- ADCQ $0x00, BX
-
- // | a2 * b2
- MOVQ 16(SI), AX
- MULQ CX
- ADDQ AX, R11
- ADCQ DX, R12
- ADCQ BX, R13
- MOVQ $0x00, BX
- ADCQ $0x00, BX
-
- // | a2 * b3
- MOVQ 24(SI), AX
- MULQ CX
- ADDQ AX, R12
- ADCQ DX, R13
- ADCQ BX, R14
- MOVQ $0x00, BX
- ADCQ $0x00, BX
-
- // | a2 * b4
- MOVQ 32(SI), AX
- MULQ CX
- ADDQ AX, R13
- ADCQ DX, R14
- ADCQ BX, R15
-
- // | a2 * b5
- MOVQ 40(SI), AX
- MULQ CX
- ADDQ AX, R14
- ADCQ DX, R15
-
- // |
-
-/* i3 */
-
- // | a3 @ CX
- MOVQ 24(DI), CX
- MOVQ $0x00, BX
-
- // | a3 * b0
- MOVQ (SI), AX
- MULQ CX
- ADDQ AX, R10
- ADCQ DX, R11
- ADCQ $0x00, R12
- ADCQ $0x00, BX
-
- // | a3 * b1
- MOVQ 8(SI), AX
- MULQ CX
- ADDQ AX, R11
- ADCQ DX, R12
- ADCQ BX, R13
- MOVQ $0x00, BX
- ADCQ $0x00, BX
-
- // | a3 * b2
- MOVQ 16(SI), AX
- MULQ CX
- ADDQ AX, R12
- ADCQ DX, R13
- ADCQ BX, R14
- MOVQ $0x00, BX
- ADCQ $0x00, BX
-
- // | a3 * b3
- MOVQ 24(SI), AX
- MULQ CX
- ADDQ AX, R13
- ADCQ DX, R14
- ADCQ BX, R15
- MOVQ $0x00, BX
- ADCQ $0x00, BX
-
- // | a3 * b4
- MOVQ 32(SI), AX
- MULQ CX
- ADDQ AX, R14
- ADCQ DX, R15
- ADCQ BX, R8
-
- // | a3 * b5
- MOVQ 40(SI), AX
- MULQ CX
- ADDQ AX, R15
- ADCQ DX, R8
-
- // |
-
-/* i4 */
-
- // | a4 @ CX
- MOVQ 32(DI), CX
- MOVQ $0x00, BX
-
- // | a4 * b0
- MOVQ (SI), AX
- MULQ CX
- ADDQ AX, R11
- ADCQ DX, R12
- ADCQ $0x00, R13
- ADCQ $0x00, BX
-
- // | a4 * b1
- MOVQ 8(SI), AX
- MULQ CX
- ADDQ AX, R12
- ADCQ DX, R13
- ADCQ BX, R14
- MOVQ $0x00, BX
- ADCQ $0x00, BX
-
- // | a4 * b2
- MOVQ 16(SI), AX
- MULQ CX
- ADDQ AX, R13
- ADCQ DX, R14
- ADCQ BX, R15
- MOVQ $0x00, BX
- ADCQ $0x00, BX
-
- // | a4 * b3
- MOVQ 24(SI), AX
- MULQ CX
- ADDQ AX, R14
- ADCQ DX, R15
- ADCQ BX, R8
- MOVQ $0x00, BX
- ADCQ $0x00, BX
-
- // | a4 * b4
- MOVQ 32(SI), AX
- MULQ CX
- ADDQ AX, R15
- ADCQ DX, R8
- ADCQ BX, R9
-
- // | a4 * b5
- MOVQ 40(SI), AX
- MULQ CX
- ADDQ AX, R8
- ADCQ DX, R9
-
- // |
-
-/* i5 */
-
- // | a5 @ CX
- MOVQ 40(DI), CX
- MOVQ $0x00, BX
-
- // | a5 * b0
- MOVQ (SI), AX
- MULQ CX
- ADDQ AX, R12
- ADCQ DX, R13
- ADCQ $0x00, R14
- ADCQ $0x00, BX
-
- // | a5 * b1
- MOVQ 8(SI), AX
- MULQ CX
- ADDQ AX, R13
- ADCQ DX, R14
- ADCQ BX, R15
- MOVQ $0x00, BX
- ADCQ $0x00, BX
-
- // | a5 * b2
- MOVQ 16(SI), AX
- MULQ CX
- ADDQ AX, R14
- ADCQ DX, R15
- ADCQ BX, R8
- MOVQ $0x00, BX
- ADCQ $0x00, BX
-
- // | a5 * b3
- MOVQ 24(SI), AX
- MULQ CX
- ADDQ AX, R15
- ADCQ DX, R8
- ADCQ BX, R9
- MOVQ $0x00, BX
- ADCQ $0x00, BX
-
- // | a5 * b4
- MOVQ 32(SI), AX
- MULQ CX
- ADDQ AX, R8
- ADCQ DX, R9
- ADCQ $0x00, BX
-
- // | a5 * b5
- MOVQ 40(SI), AX
- MULQ CX
- ADDQ AX, R9
- ADCQ DX, BX
-
- // |
-
-/* */
-
- // |
- // | W
- // | 0 (SP) | 1 8(SP) | 2 16(SP) | 3 R10 | 4 R11 | 5 R12
- // | 6 R13 | 7 R14 | 8 R15 | 9 R8 | 10 R9 | 11 BX
-
-
- MOVQ (SP), CX
- MOVQ 8(SP), DI
- MOVQ 16(SP), SI
- MOVQ BX, (SP)
- MOVQ R9, 8(SP)
-
- // |
-
-/* montgomery reduction */
-
- // |
-
-/* i0 */
-
- // |
- // | W
- // | 0 CX | 1 DI | 2 SI | 3 R10 | 4 R11 | 5 R12
- // | 6 R13 | 7 R14 | 8 R15 | 9 R8 | 10 8(SP) | 11 (SP)
-
-
- // | | u0 = w0 * inp
- MOVQ CX, AX
- MULQ ·inp+0(SB)
- MOVQ AX, R9
- MOVQ $0x00, BX
-
- // |
-
-/* */
-
- // | j0
-
- // | w0 @ CX
- MOVQ ·modulus+0(SB), AX
- MULQ R9
- ADDQ AX, CX
- ADCQ DX, BX
-
- // | j1
-
- // | w1 @ DI
- MOVQ ·modulus+8(SB), AX
- MULQ R9
- ADDQ AX, DI
- ADCQ $0x00, DX
- ADDQ BX, DI
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j2
-
- // | w2 @ SI
- MOVQ ·modulus+16(SB), AX
- MULQ R9
- ADDQ AX, SI
- ADCQ $0x00, DX
- ADDQ BX, SI
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j3
-
- // | w3 @ R10
- MOVQ ·modulus+24(SB), AX
- MULQ R9
- ADDQ AX, R10
- ADCQ $0x00, DX
- ADDQ BX, R10
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j4
-
- // | w4 @ R11
- MOVQ ·modulus+32(SB), AX
- MULQ R9
- ADDQ AX, R11
- ADCQ $0x00, DX
- ADDQ BX, R11
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j5
-
- // | w5 @ R12
- MOVQ ·modulus+40(SB), AX
- MULQ R9
- ADDQ AX, R12
- ADCQ $0x00, DX
- ADDQ BX, R12
-
- // | w6 @ R13
- ADCQ DX, R13
- ADCQ $0x00, CX
-
- // |
-
-/* i1 */
-
- // |
- // | W
- // | 0 - | 1 DI | 2 SI | 3 R10 | 4 R11 | 5 R12
- // | 6 R13 | 7 R14 | 8 R15 | 9 R8 | 10 8(SP) | 11 (SP)
-
-
- // | | u1 = w1 * inp
- MOVQ DI, AX
- MULQ ·inp+0(SB)
- MOVQ AX, R9
- MOVQ $0x00, BX
-
- // |
-
-/* */
-
- // | j0
-
- // | w1 @ DI
- MOVQ ·modulus+0(SB), AX
- MULQ R9
- ADDQ AX, DI
- ADCQ DX, BX
-
- // | j1
-
- // | w2 @ SI
- MOVQ ·modulus+8(SB), AX
- MULQ R9
- ADDQ AX, SI
- ADCQ $0x00, DX
- ADDQ BX, SI
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j2
-
- // | w3 @ R10
- MOVQ ·modulus+16(SB), AX
- MULQ R9
- ADDQ AX, R10
- ADCQ $0x00, DX
- ADDQ BX, R10
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j3
-
- // | w4 @ R11
- MOVQ ·modulus+24(SB), AX
- MULQ R9
- ADDQ AX, R11
- ADCQ $0x00, DX
- ADDQ BX, R11
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j4
-
- // | w5 @ R12
- MOVQ ·modulus+32(SB), AX
- MULQ R9
- ADDQ AX, R12
- ADCQ $0x00, DX
- ADDQ BX, R12
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j5
-
- // | w6 @ R13
- MOVQ ·modulus+40(SB), AX
- MULQ R9
- ADDQ AX, R13
- ADCQ DX, CX
- ADDQ BX, R13
-
- // | w7 @ R14
- ADCQ CX, R14
- MOVQ $0x00, CX
- ADCQ $0x00, CX
-
- // |
-
-/* i2 */
-
- // |
- // | W
- // | 0 - | 1 - | 2 SI | 3 R10 | 4 R11 | 5 R12
- // | 6 R13 | 7 R14 | 8 R15 | 9 R8 | 10 8(SP) | 11 (SP)
-
-
- // | | u2 = w2 * inp
- MOVQ SI, AX
- MULQ ·inp+0(SB)
- MOVQ AX, R9
- MOVQ $0x00, BX
-
- // |
-
-/* */
-
- // | j0
-
- // | w2 @ SI
- MOVQ ·modulus+0(SB), AX
- MULQ R9
- ADDQ AX, SI
- ADCQ DX, BX
-
- // | j1
-
- // | w3 @ R10
- MOVQ ·modulus+8(SB), AX
- MULQ R9
- ADDQ AX, R10
- ADCQ $0x00, DX
- ADDQ BX, R10
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j2
-
- // | w4 @ R11
- MOVQ ·modulus+16(SB), AX
- MULQ R9
- ADDQ AX, R11
- ADCQ $0x00, DX
- ADDQ BX, R11
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j3
-
- // | w5 @ R12
- MOVQ ·modulus+24(SB), AX
- MULQ R9
- ADDQ AX, R12
- ADCQ $0x00, DX
- ADDQ BX, R12
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j4
-
- // | w6 @ R13
- MOVQ ·modulus+32(SB), AX
- MULQ R9
- ADDQ AX, R13
- ADCQ $0x00, DX
- ADDQ BX, R13
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j5
-
- // | w7 @ R14
- MOVQ ·modulus+40(SB), AX
- MULQ R9
- ADDQ AX, R14
- ADCQ DX, CX
- ADDQ BX, R14
-
- // | w8 @ R15
- ADCQ CX, R15
- MOVQ $0x00, CX
- ADCQ $0x00, CX
-
- // |
-
-/* i3 */
-
- // |
- // | W
- // | 0 - | 1 - | 2 - | 3 R10 | 4 R11 | 5 R12
- // | 6 R13 | 7 R14 | 8 R15 | 9 R8 | 10 8(SP) | 11 (SP)
-
-
- // | | u3 = w3 * inp
- MOVQ R10, AX
- MULQ ·inp+0(SB)
- MOVQ AX, R9
- MOVQ $0x00, BX
-
- // |
-
-/* */
-
- // | j0
-
- // | w3 @ R10
- MOVQ ·modulus+0(SB), AX
- MULQ R9
- ADDQ AX, R10
- ADCQ DX, BX
-
- // | j1
-
- // | w4 @ R11
- MOVQ ·modulus+8(SB), AX
- MULQ R9
- ADDQ AX, R11
- ADCQ $0x00, DX
- ADDQ BX, R11
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j2
-
- // | w5 @ R12
- MOVQ ·modulus+16(SB), AX
- MULQ R9
- ADDQ AX, R12
- ADCQ $0x00, DX
- ADDQ BX, R12
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j3
-
- // | w6 @ R13
- MOVQ ·modulus+24(SB), AX
- MULQ R9
- ADDQ AX, R13
- ADCQ $0x00, DX
- ADDQ BX, R13
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j4
-
- // | w7 @ R14
- MOVQ ·modulus+32(SB), AX
- MULQ R9
- ADDQ AX, R14
- ADCQ $0x00, DX
- ADDQ BX, R14
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j5
-
- // | w8 @ R15
- MOVQ ·modulus+40(SB), AX
- MULQ R9
- ADDQ AX, R15
- ADCQ DX, CX
- ADDQ BX, R15
-
- // | w9 @ R8
- ADCQ CX, R8
- MOVQ $0x00, CX
- ADCQ $0x00, CX
-
- // |
-
-/* i4 */
-
- // |
- // | W
- // | 0 - | 1 - | 2 - | 3 - | 4 R11 | 5 R12
- // | 6 R13 | 7 R14 | 8 R15 | 9 R8 | 10 8(SP) | 11 (SP)
-
-
- // | | u4 = w4 * inp
- MOVQ R11, AX
- MULQ ·inp+0(SB)
- MOVQ AX, R9
- MOVQ $0x00, BX
-
- // |
-
-/* */
-
- // | j0
-
- // | w4 @ R11
- MOVQ ·modulus+0(SB), AX
- MULQ R9
- ADDQ AX, R11
- ADCQ DX, BX
-
- // | j1
-
- // | w5 @ R12
- MOVQ ·modulus+8(SB), AX
- MULQ R9
- ADDQ AX, R12
- ADCQ $0x00, DX
- ADDQ BX, R12
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j2
-
- // | w6 @ R13
- MOVQ ·modulus+16(SB), AX
- MULQ R9
- ADDQ AX, R13
- ADCQ $0x00, DX
- ADDQ BX, R13
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j3
-
- // | w7 @ R14
- MOVQ ·modulus+24(SB), AX
- MULQ R9
- ADDQ AX, R14
- ADCQ $0x00, DX
- ADDQ BX, R14
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j4
-
- // | w8 @ R15
- MOVQ ·modulus+32(SB), AX
- MULQ R9
- ADDQ AX, R15
- ADCQ $0x00, DX
- ADDQ BX, R15
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j5
-
- // | w9 @ R8
- MOVQ ·modulus+40(SB), AX
- MULQ R9
- ADDQ AX, R8
- ADCQ DX, CX
- ADDQ BX, R8
-
- // | move to idle register
- MOVQ 8(SP), DI
-
- // | w10 @ DI
- ADCQ CX, DI
- MOVQ $0x00, CX
- ADCQ $0x00, CX
-
- // |
-
-/* i5 */
-
- // |
- // | W
- // | 0 - | 1 - | 2 - | 3 - | 4 - | 5 R12
- // | 6 R13 | 7 R14 | 8 R15 | 9 R8 | 10 DI | 11 (SP)
-
-
- // | | u5 = w5 * inp
- MOVQ R12, AX
- MULQ ·inp+0(SB)
- MOVQ AX, R9
- MOVQ $0x00, BX
-
- // |
-
-/* */
-
- // | j0
-
- // | w5 @ R12
- MOVQ ·modulus+0(SB), AX
- MULQ R9
- ADDQ AX, R12
- ADCQ DX, BX
-
- // | j1
-
- // | w6 @ R13
- MOVQ ·modulus+8(SB), AX
- MULQ R9
- ADDQ AX, R13
- ADCQ $0x00, DX
- ADDQ BX, R13
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j2
-
- // | w7 @ R14
- MOVQ ·modulus+16(SB), AX
- MULQ R9
- ADDQ AX, R14
- ADCQ $0x00, DX
- ADDQ BX, R14
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j3
-
- // | w8 @ R15
- MOVQ ·modulus+24(SB), AX
- MULQ R9
- ADDQ AX, R15
- ADCQ $0x00, DX
- ADDQ BX, R15
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j4
-
- // | w9 @ R8
- MOVQ ·modulus+32(SB), AX
- MULQ R9
- ADDQ AX, R8
- ADCQ $0x00, DX
- ADDQ BX, R8
- MOVQ $0x00, BX
- ADCQ DX, BX
-
- // | j5
-
- // | w10 @ DI
- MOVQ ·modulus+40(SB), AX
- MULQ R9
- ADDQ AX, DI
- ADCQ DX, CX
- ADDQ BX, DI
-
- // | w11 @ CX
- ADCQ (SP), CX
-
- // |
- // | W montgomerry reduction ends
- // | 0 - | 1 - | 2 - | 3 - | 4 - | 5 -
- // | 6 R13 | 7 R14 | 8 R15 | 9 R8 | 10 DI | 11 CX
-
-
- // |
-
-
-/* modular reduction */
-
- MOVQ R13, R10
- SUBQ ·modulus+0(SB), R10
- MOVQ R14, R11
- SBBQ ·modulus+8(SB), R11
- MOVQ R15, R12
- SBBQ ·modulus+16(SB), R12
- MOVQ R8, AX
- SBBQ ·modulus+24(SB), AX
- MOVQ DI, BX
- SBBQ ·modulus+32(SB), BX
- MOVQ CX, R9
- SBBQ ·modulus+40(SB), R9
- // |
-
-/* out */
-
- MOVQ c+0(FP), SI
- CMOVQCC R10, R13
- MOVQ R13, (SI)
- CMOVQCC R11, R14
- MOVQ R14, 8(SI)
- CMOVQCC R12, R15
- MOVQ R15, 16(SI)
- CMOVQCC AX, R8
- MOVQ R8, 24(SI)
- CMOVQCC BX, DI
- MOVQ DI, 32(SI)
- CMOVQCC R9, CX
- MOVQ CX, 40(SI)
- RET
-
- // |
-
-/* end */
-
-
-// multiplication
-// c = a * b % p
-TEXT ·mulADX(SB), NOSPLIT, $16-24
- // |
-
-/* inputs */
-
- MOVQ a+8(FP), DI
- MOVQ b+16(FP), SI
- XORQ AX, AX
-
- // |
-
-/* i0 */
-
- // | a0 @ DX
- MOVQ (DI), DX
-
- // | a0 * b0
- MULXQ (SI), AX, CX
- MOVQ AX, (SP)
-
- // | a0 * b1
- MULXQ 8(SI), AX, R8
- ADCXQ AX, CX
-
- // | a0 * b2
- MULXQ 16(SI), AX, R9
- ADCXQ AX, R8
-
- // | a0 * b3
- MULXQ 24(SI), AX, R10
- ADCXQ AX, R9
-
- // | a0 * b4
- MULXQ 32(SI), AX, R11
- ADCXQ AX, R10
-
- // | a0 * b5
- MULXQ 40(SI), AX, R12
- ADCXQ AX, R11
- ADCQ $0x00, R12
-
- // |
-
-/* i1 */
-
- // | a1 @ DX
- MOVQ 8(DI), DX
- XORQ R13, R13
-
- // | a1 * b0
- MULXQ (SI), AX, BX
- ADOXQ AX, CX
- ADCXQ BX, R8
- MOVQ CX, 8(SP)
-
- // | a1 * b1
- MULXQ 8(SI), AX, BX
- ADOXQ AX, R8
- ADCXQ BX, R9
-
- // | a1 * b2
- MULXQ 16(SI), AX, BX
- ADOXQ AX, R9
- ADCXQ BX, R10
-
- // | a1 * b3
- MULXQ 24(SI), AX, BX
- ADOXQ AX, R10
- ADCXQ BX, R11
-
- // | a1 * b4
- MULXQ 32(SI), AX, BX
- ADOXQ AX, R11
- ADCXQ BX, R12
-
- // | a1 * b5
- MULXQ 40(SI), AX, BX
- ADOXQ AX, R12
- ADOXQ R13, R13
- ADCXQ BX, R13
-
- // |
-
-/* i2 */
-
- // | a2 @ DX
- MOVQ 16(DI), DX
- XORQ R14, R14
-
- // | a2 * b0
- MULXQ (SI), AX, BX
- ADOXQ AX, R8
- ADCXQ BX, R9
-
- // | a2 * b1
- MULXQ 8(SI), AX, BX
- ADOXQ AX, R9
- ADCXQ BX, R10
-
- // | a2 * b2
- MULXQ 16(SI), AX, BX
- ADOXQ AX, R10
- ADCXQ BX, R11
-
- // | a2 * b3
- MULXQ 24(SI), AX, BX
- ADOXQ AX, R11
- ADCXQ BX, R12
-
- // | a2 * b4
- MULXQ 32(SI), AX, BX
- ADOXQ AX, R12
- ADCXQ BX, R13
-
- // | a2 * b5
- MULXQ 40(SI), AX, BX
- ADOXQ AX, R13
- ADOXQ R14, R14
- ADCXQ BX, R14
-
- // |
-
-/* i3 */
-
- // | a3 @ DX
- MOVQ 24(DI), DX
- XORQ R15, R15
-
- // | a3 * b0
- MULXQ (SI), AX, BX
- ADOXQ AX, R9
- ADCXQ BX, R10
-
- // | a3 * b1
- MULXQ 8(SI), AX, BX
- ADOXQ AX, R10
- ADCXQ BX, R11
-
- // | a3 * b2
- MULXQ 16(SI), AX, BX
- ADOXQ AX, R11
- ADCXQ BX, R12
-
- // | a3 * b3
- MULXQ 24(SI), AX, BX
- ADOXQ AX, R12
- ADCXQ BX, R13
-
- // | a3 * b4
- MULXQ 32(SI), AX, BX
- ADOXQ AX, R13
- ADCXQ BX, R14
-
- // | a3 * b5
- MULXQ 40(SI), AX, BX
- ADOXQ AX, R14
- ADOXQ R15, R15
- ADCXQ BX, R15
-
- // |
-
-/* i4 */
-
- // | a4 @ DX
- MOVQ 32(DI), DX
- XORQ CX, CX
-
- // | a4 * b0
- MULXQ (SI), AX, BX
- ADOXQ AX, R10
- ADCXQ BX, R11
-
- // | a4 * b1
- MULXQ 8(SI), AX, BX
- ADOXQ AX, R11
- ADCXQ BX, R12
-
- // | a4 * b2
- MULXQ 16(SI), AX, BX
- ADOXQ AX, R12
- ADCXQ BX, R13
-
- // | a4 * b3
- MULXQ 24(SI), AX, BX
- ADOXQ AX, R13
- ADCXQ BX, R14
-
- // | a4 * b4
- MULXQ 32(SI), AX, BX
- ADOXQ AX, R14
- ADCXQ BX, R15
-
- // | a4 * b5
- MULXQ 40(SI), AX, BX
- ADOXQ AX, R15
- ADOXQ CX, CX
- ADCXQ BX, CX
-
- // |
-
-/* i5 */
-
- // | a5 @ DX
- MOVQ 40(DI), DX
- XORQ DI, DI
-
- // | a5 * b0
- MULXQ (SI), AX, BX
- ADOXQ AX, R11
- ADCXQ BX, R12
-
- // | a5 * b1
- MULXQ 8(SI), AX, BX
- ADOXQ AX, R12
- ADCXQ BX, R13
-
- // | a5 * b2
- MULXQ 16(SI), AX, BX
- ADOXQ AX, R13
- ADCXQ BX, R14
-
- // | a5 * b3
- MULXQ 24(SI), AX, BX
- ADOXQ AX, R14
- ADCXQ BX, R15
-
- // | a5 * b4
- MULXQ 32(SI), AX, BX
- ADOXQ AX, R15
- ADCXQ BX, CX
-
- // | a5 * b5
- MULXQ 40(SI), AX, BX
- ADOXQ AX, CX
- ADOXQ BX, DI
- ADCQ $0x00, DI
-
- // |
-
-/* */
-
- // |
- // | W
- // | 0 (SP) | 1 8(SP) | 2 R8 | 3 R9 | 4 R10 | 5 R11
- // | 6 R12 | 7 R13 | 8 R14 | 9 R15 | 10 CX | 11 DI
-
-
- MOVQ (SP), BX
- MOVQ 8(SP), SI
- MOVQ DI, (SP)
-
- // |
- // | W ready to mont
- // | 0 BX | 1 SI | 2 R8 | 3 R9 | 4 R10 | 5 R11
- // | 6 R12 | 7 R13 | 8 R14 | 9 R15 | 10 CX | 11 (SP)
-
-
- // |
-
-/* montgomery reduction */
-
- // | clear flags
- XORQ AX, AX
-
- // |
-
-/* i0 */
-
- // |
- // | W
- // | 0 BX | 1 SI | 2 R8 | 3 R9 | 4 R10 | 5 R11
- // | 6 R12 | 7 R13 | 8 R14 | 9 R15 | 10 CX | 11 (SP)
-
-
- // | | u0 = w0 * inp
- MOVQ BX, DX
- MULXQ ·inp+0(SB), DX, DI
-
- // |
-
-/* */
-
- // | j0
-
- // | w0 @ BX
- MULXQ ·modulus+0(SB), AX, DI
- ADOXQ AX, BX
- ADCXQ DI, SI
-
- // | j1
-
- // | w1 @ SI
- MULXQ ·modulus+8(SB), AX, DI
- ADOXQ AX, SI
- ADCXQ DI, R8
-
- // | j2
-
- // | w2 @ R8
- MULXQ ·modulus+16(SB), AX, DI
- ADOXQ AX, R8
- ADCXQ DI, R9
-
- // | j3
-
- // | w3 @ R9
- MULXQ ·modulus+24(SB), AX, DI
- ADOXQ AX, R9
- ADCXQ DI, R10
-
- // | j4
-
- // | w4 @ R10
- MULXQ ·modulus+32(SB), AX, DI
- ADOXQ AX, R10
- ADCXQ DI, R11
-
- // | j5
-
- // | w5 @ R11
- MULXQ ·modulus+40(SB), AX, DI
- ADOXQ AX, R11
- ADCXQ DI, R12
- ADOXQ BX, R12
- ADCXQ BX, BX
- MOVQ $0x00, AX
- ADOXQ AX, BX
-
- // | clear flags
- XORQ AX, AX
-
- // |
-
-/* i1 */
-
- // |
- // | W
- // | 0 - | 1 SI | 2 R8 | 3 R9 | 4 R10 | 5 R11
- // | 6 R12 | 7 R13 | 8 R14 | 9 R15 | 10 CX | 11 (SP)
-
-
- // | | u1 = w1 * inp
- MOVQ SI, DX
- MULXQ ·inp+0(SB), DX, DI
-
- // |
-
-/* */
-
- // | j0
-
- // | w1 @ SI
- MULXQ ·modulus+0(SB), AX, DI
- ADOXQ AX, SI
- ADCXQ DI, R8
-
- // | j1
-
- // | w2 @ R8
- MULXQ ·modulus+8(SB), AX, DI
- ADOXQ AX, R8
- ADCXQ DI, R9
-
- // | j2
-
- // | w3 @ R9
- MULXQ ·modulus+16(SB), AX, DI
- ADOXQ AX, R9
- ADCXQ DI, R10
-
- // | j3
-
- // | w4 @ R10
- MULXQ ·modulus+24(SB), AX, DI
- ADOXQ AX, R10
- ADCXQ DI, R11
-
- // | j4
-
- // | w5 @ R11
- MULXQ ·modulus+32(SB), AX, DI
- ADOXQ AX, R11
- ADCXQ DI, R12
-
- // | j5
-
- // | w6 @ R12
- MULXQ ·modulus+40(SB), AX, DI
- ADOXQ AX, R12
- ADCXQ DI, R13
- ADOXQ BX, R13
- ADCXQ SI, SI
- MOVQ $0x00, AX
- ADOXQ AX, SI
-
- // | clear flags
- XORQ AX, AX
-
- // |
-
-/* i2 */
-
- // |
- // | W
- // | 0 - | 1 - | 2 R8 | 3 R9 | 4 R10 | 5 R11
- // | 6 R12 | 7 R13 | 8 R14 | 9 R15 | 10 CX | 11 (SP)
-
-
- // | | u2 = w2 * inp
- MOVQ R8, DX
- MULXQ ·inp+0(SB), DX, DI
-
- // |
-
-/* */
-
- // | j0
-
- // | w2 @ R8
- MULXQ ·modulus+0(SB), AX, DI
- ADOXQ AX, R8
- ADCXQ DI, R9
-
- // | j1
-
- // | w3 @ R9
- MULXQ ·modulus+8(SB), AX, DI
- ADOXQ AX, R9
- ADCXQ DI, R10
-
- // | j2
-
- // | w4 @ R10
- MULXQ ·modulus+16(SB), AX, DI
- ADOXQ AX, R10
- ADCXQ DI, R11
-
- // | j3
-
- // | w5 @ R11
- MULXQ ·modulus+24(SB), AX, DI
- ADOXQ AX, R11
- ADCXQ DI, R12
-
- // | j4
-
- // | w6 @ R12
- MULXQ ·modulus+32(SB), AX, DI
- ADOXQ AX, R12
- ADCXQ DI, R13
-
- // | j5
-
- // | w7 @ R13
- MULXQ ·modulus+40(SB), AX, DI
- ADOXQ AX, R13
- ADCXQ DI, R14
- ADOXQ SI, R14
- ADCXQ R8, R8
- MOVQ $0x00, AX
- ADOXQ AX, R8
-
- // | clear flags
- XORQ AX, AX
-
- // |
-
-/* i3 */
-
- // |
- // | W
- // | 0 - | 1 - | 2 - | 3 R9 | 4 R10 | 5 R11
- // | 6 R12 | 7 R13 | 8 R14 | 9 R15 | 10 CX | 11 (SP)
-
-
- // | | u3 = w3 * inp
- MOVQ R9, DX
- MULXQ ·inp+0(SB), DX, DI
-
- // |
-
-/* */
-
- // | j0
-
- // | w3 @ R9
- MULXQ ·modulus+0(SB), AX, DI
- ADOXQ AX, R9
- ADCXQ DI, R10
-
- // | j1
-
- // | w4 @ R10
- MULXQ ·modulus+8(SB), AX, DI
- ADOXQ AX, R10
- ADCXQ DI, R11
-
- // | j2
-
- // | w5 @ R11
- MULXQ ·modulus+16(SB), AX, DI
- ADOXQ AX, R11
- ADCXQ DI, R12
-
- // | j3
-
- // | w6 @ R12
- MULXQ ·modulus+24(SB), AX, DI
- ADOXQ AX, R12
- ADCXQ DI, R13
-
- // | j4
-
- // | w7 @ R13
- MULXQ ·modulus+32(SB), AX, DI
- ADOXQ AX, R13
- ADCXQ DI, R14
-
- // | j5
-
- // | w8 @ R14
- MULXQ ·modulus+40(SB), AX, DI
- ADOXQ AX, R14
- ADCXQ DI, R15
- ADOXQ R8, R15
- ADCXQ R9, R9
- MOVQ $0x00, AX
- ADOXQ AX, R9
-
- // | clear flags
- XORQ AX, AX
-
- // |
-
-/* i4 */
-
- // |
- // | W
- // | 0 - | 1 - | 2 - | 3 - | 4 R10 | 5 R11
- // | 6 R12 | 7 R13 | 8 R14 | 9 R15 | 10 CX | 11 (SP)
-
-
- // | | u4 = w4 * inp
- MOVQ R10, DX
- MULXQ ·inp+0(SB), DX, DI
-
- // |
-
-/* */
-
- // | j0
-
- // | w4 @ R10
- MULXQ ·modulus+0(SB), AX, DI
- ADOXQ AX, R10
- ADCXQ DI, R11
-
- // | j1
-
- // | w5 @ R11
- MULXQ ·modulus+8(SB), AX, DI
- ADOXQ AX, R11
- ADCXQ DI, R12
-
- // | j2
-
- // | w6 @ R12
- MULXQ ·modulus+16(SB), AX, DI
- ADOXQ AX, R12
- ADCXQ DI, R13
-
- // | j3
-
- // | w7 @ R13
- MULXQ ·modulus+24(SB), AX, DI
- ADOXQ AX, R13
- ADCXQ DI, R14
-
- // | j4
-
- // | w8 @ R14
- MULXQ ·modulus+32(SB), AX, DI
- ADOXQ AX, R14
- ADCXQ DI, R15
-
- // | j5
-
- // | w9 @ R15
- MULXQ ·modulus+40(SB), AX, DI
- ADOXQ AX, R15
- ADCXQ DI, CX
- ADOXQ R9, CX
- ADCXQ R10, R10
- MOVQ $0x00, AX
- ADOXQ AX, R10
-
- // | clear flags
- XORQ AX, AX
-
- // |
-
-/* i5 */
-
- // |
- // | W
- // | 0 - | 1 - | 2 - | 3 - | 4 - | 5 R11
- // | 6 R12 | 7 R13 | 8 R14 | 9 R15 | 10 CX | 11 (SP)
-
-
- // | | u5 = w5 * inp
- MOVQ R11, DX
- MULXQ ·inp+0(SB), DX, DI
-
- // |
-
-/* */
-
- // | j0
-
- // | w5 @ R11
- MULXQ ·modulus+0(SB), AX, DI
- ADOXQ AX, R11
- ADCXQ DI, R12
-
- // | j1
-
- // | w6 @ R12
- MULXQ ·modulus+8(SB), AX, DI
- ADOXQ AX, R12
- ADCXQ DI, R13
-
- // | j2
-
- // | w7 @ R13
- MULXQ ·modulus+16(SB), AX, DI
- ADOXQ AX, R13
- ADCXQ DI, R14
-
- // | j3
-
- // | w8 @ R14
- MULXQ ·modulus+24(SB), AX, DI
- ADOXQ AX, R14
- ADCXQ DI, R15
-
- // | j4
-
- // | w9 @ R15
- MULXQ ·modulus+32(SB), AX, DI
- ADOXQ AX, R15
- ADCXQ DI, CX
-
- // | j5
-
- // | w10 @ CX
- MULXQ ·modulus+40(SB), AX, DI
- ADOXQ AX, CX
-
- // | w11 @ (SP)
- // | move to an idle register
- MOVQ (SP), BX
- ADCXQ DI, BX
- ADOXQ R10, BX
-
- // |
- // | W montgomery reduction ends
- // | 0 - | 1 - | 2 - | 3 - | 4 - | 5 -
- // | 6 R12 | 7 R13 | 8 R14 | 9 R15 | 10 CX | 11 BX
-
-
- // |
-
-/* modular reduction */
-
- MOVQ R12, AX
- SUBQ ·modulus+0(SB), AX
- MOVQ R13, DI
- SBBQ ·modulus+8(SB), DI
- MOVQ R14, SI
- SBBQ ·modulus+16(SB), SI
- MOVQ R15, R8
- SBBQ ·modulus+24(SB), R8
- MOVQ CX, R9
- SBBQ ·modulus+32(SB), R9
- MOVQ BX, R10
- SBBQ ·modulus+40(SB), R10
-
- // |
-
-/* out */
-
- MOVQ c+0(FP), R11
- CMOVQCC AX, R12
- MOVQ R12, (R11)
- CMOVQCC DI, R13
- MOVQ R13, 8(R11)
- CMOVQCC SI, R14
- MOVQ R14, 16(R11)
- CMOVQCC R8, R15
- MOVQ R15, 24(R11)
- CMOVQCC R9, CX
- MOVQ CX, 32(R11)
- CMOVQCC R10, BX
- MOVQ BX, 40(R11)
- RET
-
- // |
-
-/* end */
diff --git a/crypto/bls12381/bls12_381.go b/crypto/bls12381/bls12_381.go
deleted file mode 100644
index 1c1c97765f..0000000000
--- a/crypto/bls12381/bls12_381.go
+++ /dev/null
@@ -1,230 +0,0 @@
-// Copyright 2020 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 bls12381
-
-/*
- Field Constants
-*/
-
-// Base field modulus
-// p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
-
-// Size of six words
-// r = 2 ^ 384
-
-// modulus = p
-var modulus = fe{0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a}
-
-var (
- // -p^(-1) mod 2^64
- inp uint64 = 0x89f3fffcfffcfffd
- // This value is used in assembly code
- _ = inp
-)
-
-// r mod p
-var r1 = &fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493}
-
-// r^2 mod p
-var r2 = &fe{
- 0xf4df1f341c341746, 0x0a76e6a609d104f1, 0x8de5476c4c95b6d5, 0x67eb88a9939d83c0, 0x9a793e85b519952d, 0x11988fe592cae3aa,
-}
-
-// -1 + 0 * u
-var negativeOne2 = &fe2{
- fe{0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x07e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x040ab3263eff0206},
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
-}
-
-// 2 ^ (-1)
-var twoInv = &fe{0x1804000000015554, 0x855000053ab00001, 0x633cb57c253c276f, 0x6e22d1ec31ebb502, 0xd3916126f2d14ca2, 0x17fbb8571a006596}
-
-// (p - 3) / 4
-var pMinus3Over4 = bigFromHex("0x680447a8e5ff9a692c6e9ed90d2eb35d91dd2e13ce144afd9cc34a83dac3d8907aaffffac54ffffee7fbfffffffeaaa")
-
-// (p + 1) / 4
-var pPlus1Over4 = bigFromHex("0x680447a8e5ff9a692c6e9ed90d2eb35d91dd2e13ce144afd9cc34a83dac3d8907aaffffac54ffffee7fbfffffffeaab")
-
-// (p - 1) / 2
-var pMinus1Over2 = bigFromHex("0xd0088f51cbff34d258dd3db21a5d66bb23ba5c279c2895fb39869507b587b120f55ffff58a9ffffdcff7fffffffd555")
-
-// -1
-var nonResidue1 = &fe{0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x07e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x040ab3263eff0206}
-
-// (1 + 1 * u)
-var nonResidue2 = &fe2{
- fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
- fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
-}
-
-/*
- Curve Constants
-*/
-
-// b coefficient for G1
-var b = &fe{0xaa270000000cfff3, 0x53cc0032fc34000a, 0x478fe97a6b0a807f, 0xb1d37ebee6ba24d7, 0x8ec9733bbf78ab2f, 0x09d645513d83de7e}
-
-// b coefficient for G2
-var b2 = &fe2{
- fe{0xaa270000000cfff3, 0x53cc0032fc34000a, 0x478fe97a6b0a807f, 0xb1d37ebee6ba24d7, 0x8ec9733bbf78ab2f, 0x09d645513d83de7e},
- fe{0xaa270000000cfff3, 0x53cc0032fc34000a, 0x478fe97a6b0a807f, 0xb1d37ebee6ba24d7, 0x8ec9733bbf78ab2f, 0x09d645513d83de7e},
-}
-
-// Curve order
-var q = bigFromHex("0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001")
-
-// Efficient cofactor of G1
-var cofactorEFFG1 = bigFromHex("0xd201000000010001")
-
-// Efficient cofactor of G2
-var cofactorEFFG2 = bigFromHex("0x0bc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551")
-
-var g1One = PointG1{
- fe{0x5cb38790fd530c16, 0x7817fc679976fff5, 0x154f95c7143ba1c1, 0xf0ae6acdf3d0e747, 0xedce6ecc21dbf440, 0x120177419e0bfb75},
- fe{0xbaac93d50ce72271, 0x8c22631a7918fd8e, 0xdd595f13570725ce, 0x51ac582950405194, 0x0e1c8c3fad0059c0, 0x0bbc3efc5008a26a},
- fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
-}
-
-var g2One = PointG2{
- fe2{
- fe{0xf5f28fa202940a10, 0xb3f5fb2687b4961a, 0xa1a893b53e2ae580, 0x9894999d1a3caee9, 0x6f67b7631863366b, 0x058191924350bcd7},
- fe{0xa5a9c0759e23f606, 0xaaa0c59dbccd60c3, 0x3bb17e18e2867806, 0x1b1ab6cc8541b367, 0xc2b6ed0ef2158547, 0x11922a097360edf3},
- },
- fe2{
- fe{0x4c730af860494c4a, 0x597cfa1f5e369c5a, 0xe7e6856caa0a635a, 0xbbefb5e96e0d495f, 0x07d3a975f0ef25a2, 0x083fd8e7e80dae5},
- fe{0xadc0fc92df64b05d, 0x18aa270a2b1461dc, 0x86adac6a3be4eba0, 0x79495c4ec93da33a, 0xe7175850a43ccaed, 0xb2bc2a163de1bf2},
- },
- fe2{
- fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
- },
-}
-
-/*
- Frobenious Coeffs
-*/
-
-var frobeniusCoeffs61 = [6]fe2{
- {
- fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
- },
- {
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
- fe{0xcd03c9e48671f071, 0x5dab22461fcda5d2, 0x587042afd3851b95, 0x8eb60ebe01bacb9e, 0x03f97d6e83d050d2, 0x18f0206554638741},
- },
- {
- fe{0x30f1361b798a64e8, 0xf3b8ddab7ece5a2a, 0x16a8ca3ac61577f7, 0xc26a2ff874fd029b, 0x3636b76660701c6e, 0x051ba4ab241b6160},
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
- },
- {
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
- fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
- },
- {
- fe{0xcd03c9e48671f071, 0x5dab22461fcda5d2, 0x587042afd3851b95, 0x8eb60ebe01bacb9e, 0x03f97d6e83d050d2, 0x18f0206554638741},
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
- },
- {
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
- fe{0x30f1361b798a64e8, 0xf3b8ddab7ece5a2a, 0x16a8ca3ac61577f7, 0xc26a2ff874fd029b, 0x3636b76660701c6e, 0x051ba4ab241b6160},
- },
-}
-
-var frobeniusCoeffs62 = [6]fe2{
- {
- fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
- },
- {
- fe{0x890dc9e4867545c3, 0x2af322533285a5d5, 0x50880866309b7e2c, 0xa20d1b8c7e881024, 0x14e4f04fe2db9068, 0x14e56d3f1564853a},
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
- },
- {
- fe{0xcd03c9e48671f071, 0x5dab22461fcda5d2, 0x587042afd3851b95, 0x8eb60ebe01bacb9e, 0x03f97d6e83d050d2, 0x18f0206554638741},
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
- },
- {
- fe{0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x07e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x040ab3263eff0206},
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
- },
- {
- fe{0x30f1361b798a64e8, 0xf3b8ddab7ece5a2a, 0x16a8ca3ac61577f7, 0xc26a2ff874fd029b, 0x3636b76660701c6e, 0x051ba4ab241b6160},
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
- },
- {
- fe{0xecfb361b798dba3a, 0xc100ddb891865a2c, 0x0ec08ff1232bda8e, 0xd5c13cc6f1ca4721, 0x47222a47bf7b5c04, 0x0110f184e51c5f59},
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
- },
-}
-
-var frobeniusCoeffs12 = [12]fe2{
- {
- fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
- },
- {
- fe{0x07089552b319d465, 0xc6695f92b50a8313, 0x97e83cccd117228f, 0xa35baecab2dc29ee, 0x1ce393ea5daace4d, 0x08f2220fb0fb66eb},
- fe{0xb2f66aad4ce5d646, 0x5842a06bfc497cec, 0xcf4895d42599d394, 0xc11b9cba40a8e8d0, 0x2e3813cbe5a0de89, 0x110eefda88847faf},
- },
- {
- fe{0xecfb361b798dba3a, 0xc100ddb891865a2c, 0x0ec08ff1232bda8e, 0xd5c13cc6f1ca4721, 0x47222a47bf7b5c04, 0x0110f184e51c5f59},
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
- },
- {
- fe{0x3e2f585da55c9ad1, 0x4294213d86c18183, 0x382844c88b623732, 0x92ad2afd19103e18, 0x1d794e4fac7cf0b9, 0x0bd592fc7d825ec8},
- fe{0x7bcfa7a25aa30fda, 0xdc17dec12a927e7c, 0x2f088dd86b4ebef1, 0xd1ca2087da74d4a7, 0x2da2596696cebc1d, 0x0e2b7eedbbfd87d2},
- },
- {
- fe{0x30f1361b798a64e8, 0xf3b8ddab7ece5a2a, 0x16a8ca3ac61577f7, 0xc26a2ff874fd029b, 0x3636b76660701c6e, 0x051ba4ab241b6160},
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
- },
- {
- fe{0x3726c30af242c66c, 0x7c2ac1aad1b6fe70, 0xa04007fbba4b14a2, 0xef517c3266341429, 0x0095ba654ed2226b, 0x02e370eccc86f7dd},
- fe{0x82d83cf50dbce43f, 0xa2813e53df9d018f, 0xc6f0caa53c65e181, 0x7525cf528d50fe95, 0x4a85ed50f4798a6b, 0x171da0fd6cf8eebd},
- },
- {
- fe{0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x07e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x040ab3263eff0206},
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
- },
- {
- fe{0xb2f66aad4ce5d646, 0x5842a06bfc497cec, 0xcf4895d42599d394, 0xc11b9cba40a8e8d0, 0x2e3813cbe5a0de89, 0x110eefda88847faf},
- fe{0x07089552b319d465, 0xc6695f92b50a8313, 0x97e83cccd117228f, 0xa35baecab2dc29ee, 0x1ce393ea5daace4d, 0x08f2220fb0fb66eb},
- },
- {
- fe{0xcd03c9e48671f071, 0x5dab22461fcda5d2, 0x587042afd3851b95, 0x8eb60ebe01bacb9e, 0x03f97d6e83d050d2, 0x18f0206554638741},
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
- },
- {
- fe{0x7bcfa7a25aa30fda, 0xdc17dec12a927e7c, 0x2f088dd86b4ebef1, 0xd1ca2087da74d4a7, 0x2da2596696cebc1d, 0x0e2b7eedbbfd87d2},
- fe{0x3e2f585da55c9ad1, 0x4294213d86c18183, 0x382844c88b623732, 0x92ad2afd19103e18, 0x1d794e4fac7cf0b9, 0x0bd592fc7d825ec8},
- },
- {
- fe{0x890dc9e4867545c3, 0x2af322533285a5d5, 0x50880866309b7e2c, 0xa20d1b8c7e881024, 0x14e4f04fe2db9068, 0x14e56d3f1564853a},
- fe{0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000},
- },
- {
- fe{0x82d83cf50dbce43f, 0xa2813e53df9d018f, 0xc6f0caa53c65e181, 0x7525cf528d50fe95, 0x4a85ed50f4798a6b, 0x171da0fd6cf8eebd},
- fe{0x3726c30af242c66c, 0x7c2ac1aad1b6fe70, 0xa04007fbba4b14a2, 0xef517c3266341429, 0x0095ba654ed2226b, 0x02e370eccc86f7dd},
- },
-}
-
-/*
- x
-*/
-
-var x = bigFromHex("0xd201000000010000")
diff --git a/crypto/bls12381/bls12_381_test.go b/crypto/bls12381/bls12_381_test.go
deleted file mode 100644
index 6bf5834105..0000000000
--- a/crypto/bls12381/bls12_381_test.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package bls12381
-
-import (
- "crypto/rand"
- "math/big"
-)
-
-var fuz = 10
-
-func randScalar(max *big.Int) *big.Int {
- a, _ := rand.Int(rand.Reader, max)
- return a
-}
diff --git a/crypto/bls12381/field_element.go b/crypto/bls12381/field_element.go
deleted file mode 100644
index ee57ade3b4..0000000000
--- a/crypto/bls12381/field_element.go
+++ /dev/null
@@ -1,373 +0,0 @@
-// Copyright 2020 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 bls12381
-
-import (
- "crypto/rand"
- "encoding/hex"
- "fmt"
- "io"
- "math/big"
-)
-
-// fe is base field element representation
-type fe [6]uint64
-
-// fe2 is element representation of 'fp2' which is quadratic extension of base field 'fp'
-// Representation follows c[0] + c[1] * u encoding order.
-type fe2 [2]fe
-
-// fe6 is element representation of 'fp6' field which is cubic extension of 'fp2'
-// Representation follows c[0] + c[1] * v + c[2] * v^2 encoding order.
-type fe6 [3]fe2
-
-// fe12 is element representation of 'fp12' field which is quadratic extension of 'fp6'
-// Representation follows c[0] + c[1] * w encoding order.
-type fe12 [2]fe6
-
-func (fe *fe) setBytes(in []byte) *fe {
- size := 48
- l := len(in)
-
- if l >= size {
- l = size
- }
-
- padded := make([]byte, size)
- copy(padded[size-l:], in[:])
-
- var a int
- for i := 0; i < 6; i++ {
- a = size - i*8
- fe[i] = uint64(padded[a-1]) | uint64(padded[a-2])<<8 |
- uint64(padded[a-3])<<16 | uint64(padded[a-4])<<24 |
- uint64(padded[a-5])<<32 | uint64(padded[a-6])<<40 |
- uint64(padded[a-7])<<48 | uint64(padded[a-8])<<56
- }
-
- return fe
-}
-
-func (fe *fe) setBig(a *big.Int) *fe {
- return fe.setBytes(a.Bytes())
-}
-
-func (fe *fe) setString(s string) (*fe, error) {
- if s[:2] == "0x" {
- s = s[2:]
- }
-
- bytes, err := hex.DecodeString(s)
- if err != nil {
- return nil, err
- }
-
- return fe.setBytes(bytes), nil
-}
-
-func (fe *fe) set(fe2 *fe) *fe {
- fe[0] = fe2[0]
- fe[1] = fe2[1]
- fe[2] = fe2[2]
- fe[3] = fe2[3]
- fe[4] = fe2[4]
- fe[5] = fe2[5]
-
- return fe
-}
-
-func (fe *fe) bytes() []byte {
- out := make([]byte, 48)
-
- var a int
- for i := 0; i < 6; i++ {
- a = 48 - i*8
- out[a-1] = byte(fe[i])
- out[a-2] = byte(fe[i] >> 8)
- out[a-3] = byte(fe[i] >> 16)
- out[a-4] = byte(fe[i] >> 24)
- out[a-5] = byte(fe[i] >> 32)
- out[a-6] = byte(fe[i] >> 40)
- out[a-7] = byte(fe[i] >> 48)
- out[a-8] = byte(fe[i] >> 56)
- }
-
- return out
-}
-
-func (fe *fe) big() *big.Int {
- return new(big.Int).SetBytes(fe.bytes())
-}
-
-func (fe *fe) string() (s string) {
- for i := 5; i >= 0; i-- {
- s = fmt.Sprintf("%s%16.16x", s, fe[i])
- }
-
- return "0x" + s
-}
-
-func (fe *fe) zero() *fe {
- fe[0] = 0
- fe[1] = 0
- fe[2] = 0
- fe[3] = 0
- fe[4] = 0
- fe[5] = 0
-
- return fe
-}
-
-func (fe *fe) one() *fe {
- return fe.set(r1)
-}
-
-func (fe *fe) rand(r io.Reader) (*fe, error) {
- bi, err := rand.Int(r, modulus.big())
- if err != nil {
- return nil, err
- }
-
- return fe.setBig(bi), nil
-}
-
-func (fe *fe) isValid() bool {
- return fe.cmp(&modulus) < 0
-}
-
-func (fe *fe) isOdd() bool {
- var mask uint64 = 1
- return fe[0]&mask != 0
-}
-
-func (fe *fe) isEven() bool {
- var mask uint64 = 1
- return fe[0]&mask == 0
-}
-
-func (fe *fe) isZero() bool {
- return (fe[5] | fe[4] | fe[3] | fe[2] | fe[1] | fe[0]) == 0
-}
-
-func (fe *fe) isOne() bool {
- return fe.equal(r1)
-}
-
-func (fe *fe) cmp(fe2 *fe) int {
- for i := 5; i >= 0; i-- {
- if fe[i] > fe2[i] {
- return 1
- } else if fe[i] < fe2[i] {
- return -1
- }
- }
-
- return 0
-}
-
-func (fe *fe) equal(fe2 *fe) bool {
- return fe2[0] == fe[0] && fe2[1] == fe[1] && fe2[2] == fe[2] && fe2[3] == fe[3] && fe2[4] == fe[4] && fe2[5] == fe[5]
-}
-
-func (e *fe) sign() bool {
- r := new(fe)
- fromMont(r, e)
-
- return r[0]&1 == 0
-}
-
-func (fe *fe) div2(e uint64) {
- fe[0] = fe[0]>>1 | fe[1]<<63
- fe[1] = fe[1]>>1 | fe[2]<<63
- fe[2] = fe[2]>>1 | fe[3]<<63
- fe[3] = fe[3]>>1 | fe[4]<<63
- fe[4] = fe[4]>>1 | fe[5]<<63
- fe[5] = fe[5]>>1 | e<<63
-}
-
-func (fe *fe) mul2() uint64 {
- e := fe[5] >> 63
- fe[5] = fe[5]<<1 | fe[4]>>63
- fe[4] = fe[4]<<1 | fe[3]>>63
- fe[3] = fe[3]<<1 | fe[2]>>63
- fe[2] = fe[2]<<1 | fe[1]>>63
- fe[1] = fe[1]<<1 | fe[0]>>63
- fe[0] = fe[0] << 1
-
- return e
-}
-
-func (e *fe2) zero() *fe2 {
- e[0].zero()
- e[1].zero()
-
- return e
-}
-
-func (e *fe2) one() *fe2 {
- e[0].one()
- e[1].zero()
-
- return e
-}
-
-func (e *fe2) set(e2 *fe2) *fe2 {
- e[0].set(&e2[0])
- e[1].set(&e2[1])
-
- return e
-}
-
-func (e *fe2) rand(r io.Reader) (*fe2, error) {
- a0, err := new(fe).rand(r)
- if err != nil {
- return nil, err
- }
-
- a1, err := new(fe).rand(r)
- if err != nil {
- return nil, err
- }
-
- return &fe2{*a0, *a1}, nil
-}
-
-func (e *fe2) isOne() bool {
- return e[0].isOne() && e[1].isZero()
-}
-
-func (e *fe2) isZero() bool {
- return e[0].isZero() && e[1].isZero()
-}
-
-func (e *fe2) equal(e2 *fe2) bool {
- return e[0].equal(&e2[0]) && e[1].equal(&e2[1])
-}
-
-func (e *fe2) sign() bool {
- r := new(fe)
- if !e[0].isZero() {
- fromMont(r, &e[0])
- return r[0]&1 == 0
- }
-
- fromMont(r, &e[1])
-
- return r[0]&1 == 0
-}
-
-func (e *fe6) zero() *fe6 {
- e[0].zero()
- e[1].zero()
- e[2].zero()
-
- return e
-}
-
-func (e *fe6) one() *fe6 {
- e[0].one()
- e[1].zero()
- e[2].zero()
-
- return e
-}
-
-func (e *fe6) set(e2 *fe6) *fe6 {
- e[0].set(&e2[0])
- e[1].set(&e2[1])
- e[2].set(&e2[2])
-
- return e
-}
-
-func (e *fe6) rand(r io.Reader) (*fe6, error) {
- a0, err := new(fe2).rand(r)
- if err != nil {
- return nil, err
- }
-
- a1, err := new(fe2).rand(r)
- if err != nil {
- return nil, err
- }
-
- a2, err := new(fe2).rand(r)
- if err != nil {
- return nil, err
- }
-
- return &fe6{*a0, *a1, *a2}, nil
-}
-
-func (e *fe6) isOne() bool {
- return e[0].isOne() && e[1].isZero() && e[2].isZero()
-}
-
-func (e *fe6) isZero() bool {
- return e[0].isZero() && e[1].isZero() && e[2].isZero()
-}
-
-func (e *fe6) equal(e2 *fe6) bool {
- return e[0].equal(&e2[0]) && e[1].equal(&e2[1]) && e[2].equal(&e2[2])
-}
-
-func (e *fe12) zero() *fe12 {
- e[0].zero()
- e[1].zero()
-
- return e
-}
-
-func (e *fe12) one() *fe12 {
- e[0].one()
- e[1].zero()
-
- return e
-}
-
-func (e *fe12) set(e2 *fe12) *fe12 {
- e[0].set(&e2[0])
- e[1].set(&e2[1])
-
- return e
-}
-
-func (e *fe12) rand(r io.Reader) (*fe12, error) {
- a0, err := new(fe6).rand(r)
- if err != nil {
- return nil, err
- }
-
- a1, err := new(fe6).rand(r)
- if err != nil {
- return nil, err
- }
-
- return &fe12{*a0, *a1}, nil
-}
-
-func (e *fe12) isOne() bool {
- return e[0].isOne() && e[1].isZero()
-}
-
-func (e *fe12) isZero() bool {
- return e[0].isZero() && e[1].isZero()
-}
-
-func (e *fe12) equal(e2 *fe12) bool {
- return e[0].equal(&e2[0]) && e[1].equal(&e2[1])
-}
diff --git a/crypto/bls12381/field_element_test.go b/crypto/bls12381/field_element_test.go
deleted file mode 100644
index f5b376f32f..0000000000
--- a/crypto/bls12381/field_element_test.go
+++ /dev/null
@@ -1,298 +0,0 @@
-package bls12381
-
-import (
- "bytes"
- "crypto/rand"
- "math/big"
- "testing"
-)
-
-func TestFieldElementValidation(t *testing.T) {
- zero := new(fe).zero()
- if !zero.isValid() {
- t.Fatal("zero must be valid")
- }
-
- one := new(fe).one()
- if !one.isValid() {
- t.Fatal("one must be valid")
- }
-
- if modulus.isValid() {
- t.Fatal("modulus must be invalid")
- }
-
- n := modulus.big()
- n.Add(n, big.NewInt(1))
-
- if new(fe).setBig(n).isValid() {
- t.Fatal("number greater than modulus must be invalid")
- }
-}
-
-func TestFieldElementEquality(t *testing.T) {
- // fe
- zero := new(fe).zero()
- if !zero.equal(zero) {
- t.Fatal("0 == 0")
- }
-
- one := new(fe).one()
- if !one.equal(one) {
- t.Fatal("1 == 1")
- }
-
- a, _ := new(fe).rand(rand.Reader)
- if !a.equal(a) {
- t.Fatal("a == a")
- }
-
- b := new(fe)
- add(b, a, one)
-
- if a.equal(b) {
- t.Fatal("a != a + 1")
- }
- // fe2
- zero2 := new(fe2).zero()
- if !zero2.equal(zero2) {
- t.Fatal("0 == 0")
- }
-
- one2 := new(fe2).one()
- if !one2.equal(one2) {
- t.Fatal("1 == 1")
- }
-
- a2, _ := new(fe2).rand(rand.Reader)
- if !a2.equal(a2) {
- t.Fatal("a == a")
- }
-
- b2 := new(fe2)
- fp2 := newFp2()
- fp2.add(b2, a2, one2)
-
- if a2.equal(b2) {
- t.Fatal("a != a + 1")
- }
- // fe6
- zero6 := new(fe6).zero()
- if !zero6.equal(zero6) {
- t.Fatal("0 == 0")
- }
-
- one6 := new(fe6).one()
- if !one6.equal(one6) {
- t.Fatal("1 == 1")
- }
-
- a6, _ := new(fe6).rand(rand.Reader)
- if !a6.equal(a6) {
- t.Fatal("a == a")
- }
-
- b6 := new(fe6)
- fp6 := newFp6(fp2)
- fp6.add(b6, a6, one6)
-
- if a6.equal(b6) {
- t.Fatal("a != a + 1")
- }
- // fe12
- zero12 := new(fe12).zero()
- if !zero12.equal(zero12) {
- t.Fatal("0 == 0")
- }
-
- one12 := new(fe12).one()
- if !one12.equal(one12) {
- t.Fatal("1 == 1")
- }
-
- a12, _ := new(fe12).rand(rand.Reader)
- if !a12.equal(a12) {
- t.Fatal("a == a")
- }
-
- b12 := new(fe12)
- fp12 := newFp12(fp6)
- fp12.add(b12, a12, one12)
-
- if a12.equal(b12) {
- t.Fatal("a != a + 1")
- }
-}
-
-func TestFieldElementHelpers(t *testing.T) {
- // fe
- zero := new(fe).zero()
- if !zero.isZero() {
- t.Fatal("'zero' is not zero")
- }
-
- one := new(fe).one()
- if !one.isOne() {
- t.Fatal("'one' is not one")
- }
-
- odd := new(fe).setBig(big.NewInt(1))
- if !odd.isOdd() {
- t.Fatal("1 must be odd")
- }
-
- if odd.isEven() {
- t.Fatal("1 must not be even")
- }
-
- even := new(fe).setBig(big.NewInt(2))
- if !even.isEven() {
- t.Fatal("2 must be even")
- }
-
- if even.isOdd() {
- t.Fatal("2 must not be odd")
- }
- // fe2
- zero2 := new(fe2).zero()
- if !zero2.isZero() {
- t.Fatal("'zero' is not zero, 2")
- }
-
- one2 := new(fe2).one()
- if !one2.isOne() {
- t.Fatal("'one' is not one, 2")
- }
- // fe6
- zero6 := new(fe6).zero()
- if !zero6.isZero() {
- t.Fatal("'zero' is not zero, 6")
- }
-
- one6 := new(fe6).one()
- if !one6.isOne() {
- t.Fatal("'one' is not one, 6")
- }
- // fe12
- zero12 := new(fe12).zero()
- if !zero12.isZero() {
- t.Fatal("'zero' is not zero, 12")
- }
-
- one12 := new(fe12).one()
- if !one12.isOne() {
- t.Fatal("'one' is not one, 12")
- }
-}
-
-func TestFieldElementSerialization(t *testing.T) {
- t.Run("zero", func(t *testing.T) {
- in := make([]byte, 48)
-
- fe := new(fe).setBytes(in)
- if !fe.isZero() {
- t.Fatal("bad serialization")
- }
-
- if !bytes.Equal(in, fe.bytes()) {
- t.Fatal("bad serialization")
- }
- })
- t.Run("bytes", func(t *testing.T) {
- for i := 0; i < fuz; i++ {
- a, _ := new(fe).rand(rand.Reader)
- b := new(fe).setBytes(a.bytes())
-
- if !a.equal(b) {
- t.Fatal("bad serialization")
- }
- }
- })
- t.Run("big", func(t *testing.T) {
- for i := 0; i < fuz; i++ {
- a, _ := new(fe).rand(rand.Reader)
- b := new(fe).setBig(a.big())
-
- if !a.equal(b) {
- t.Fatal("bad encoding or decoding")
- }
- }
- })
- t.Run("string", func(t *testing.T) {
- for i := 0; i < fuz; i++ {
- a, _ := new(fe).rand(rand.Reader)
-
- b, err := new(fe).setString(a.string())
- if err != nil {
- t.Fatal(err)
- }
-
- if !a.equal(b) {
- t.Fatal("bad encoding or decoding")
- }
- }
- })
-}
-
-func TestFieldElementByteInputs(t *testing.T) {
- zero := new(fe).zero()
- in := make([]byte, 0)
-
- a := new(fe).setBytes(in)
- if !a.equal(zero) {
- t.Fatal("bad serialization")
- }
-
- in = make([]byte, 48)
-
- a = new(fe).setBytes(in)
- if !a.equal(zero) {
- t.Fatal("bad serialization")
- }
-
- in = make([]byte, 64)
-
- a = new(fe).setBytes(in)
- if !a.equal(zero) {
- t.Fatal("bad serialization")
- }
-
- in = make([]byte, 49)
- in[47] = 1
- normalOne := &fe{1, 0, 0, 0, 0, 0}
- a = new(fe).setBytes(in)
-
- if !a.equal(normalOne) {
- t.Fatal("bad serialization")
- }
-}
-
-func TestFieldElementCopy(t *testing.T) {
- a, _ := new(fe).rand(rand.Reader)
- b := new(fe).set(a)
-
- if !a.equal(b) {
- t.Fatal("bad copy, 1")
- }
-
- a2, _ := new(fe2).rand(rand.Reader)
- b2 := new(fe2).set(a2)
-
- if !a2.equal(b2) {
- t.Fatal("bad copy, 2")
- }
-
- a6, _ := new(fe6).rand(rand.Reader)
- b6 := new(fe6).set(a6)
-
- if !a6.equal(b6) {
- t.Fatal("bad copy, 6")
- }
-
- a12, _ := new(fe12).rand(rand.Reader)
- b12 := new(fe12).set(a12)
-
- if !a12.equal(b12) {
- t.Fatal("bad copy, 12")
- }
-}
diff --git a/crypto/bls12381/fp.go b/crypto/bls12381/fp.go
deleted file mode 100644
index 0e9f24181e..0000000000
--- a/crypto/bls12381/fp.go
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright 2020 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 bls12381
-
-import (
- "errors"
- "math/big"
-)
-
-func fromBytes(in []byte) (*fe, error) {
- fe := &fe{}
-
- if len(in) != 48 {
- return nil, errors.New("input string should be equal 48 bytes")
- }
-
- fe.setBytes(in)
-
- if !fe.isValid() {
- return nil, errors.New("must be less than modulus")
- }
-
- toMont(fe, fe)
-
- return fe, nil
-}
-
-func fromBig(in *big.Int) (*fe, error) {
- fe := new(fe).setBig(in)
- if !fe.isValid() {
- return nil, errors.New("invalid input string")
- }
-
- toMont(fe, fe)
-
- return fe, nil
-}
-
-func fromString(in string) (*fe, error) {
- fe, err := new(fe).setString(in)
- if err != nil {
- return nil, err
- }
-
- if !fe.isValid() {
- return nil, errors.New("invalid input string")
- }
-
- toMont(fe, fe)
-
- return fe, nil
-}
-
-func toBytes(e *fe) []byte {
- e2 := new(fe)
- fromMont(e2, e)
-
- return e2.bytes()
-}
-
-func toBig(e *fe) *big.Int {
- e2 := new(fe)
- fromMont(e2, e)
-
- return e2.big()
-}
-
-func toString(e *fe) (s string) {
- e2 := new(fe)
- fromMont(e2, e)
-
- return e2.string()
-}
-
-func toMont(c, a *fe) {
- mul(c, a, r2)
-}
-
-func fromMont(c, a *fe) {
- mul(c, a, &fe{1})
-}
-
-func exp(c, a *fe, e *big.Int) {
- z := new(fe).set(r1)
- for i := e.BitLen(); i >= 0; i-- {
- mul(z, z, z)
-
- if e.Bit(i) == 1 {
- mul(z, z, a)
- }
- }
- c.set(z)
-}
-
-func inverse(inv, e *fe) {
- if e.isZero() {
- inv.zero()
- return
- }
-
- u := new(fe).set(&modulus)
- v := new(fe).set(e)
- s := &fe{1}
- r := &fe{0}
-
- var k int
-
- var z uint64
-
- var found = false
- // Phase 1
- for i := 0; i < 768; i++ {
- if v.isZero() {
- found = true
- break
- }
-
- if u.isEven() {
- u.div2(0)
- s.mul2()
- } else if v.isEven() {
- v.div2(0)
-
- z += r.mul2()
- } else if u.cmp(v) == 1 {
- lsubAssign(u, v)
- u.div2(0)
- laddAssign(r, s)
- s.mul2()
- } else {
- lsubAssign(v, u)
- v.div2(0)
- laddAssign(s, r)
- z += r.mul2()
- }
-
- k += 1
- }
-
- if !found {
- inv.zero()
- return
- }
-
- if k < 381 || k > 381+384 {
- inv.zero()
- return
- }
-
- if r.cmp(&modulus) != -1 || z > 0 {
- lsubAssign(r, &modulus)
- }
-
- u.set(&modulus)
- lsubAssign(u, r)
-
- // Phase 2
- for i := k; i < 384*2; i++ {
- double(u, u)
- }
- inv.set(u)
-}
-
-func sqrt(c, a *fe) bool {
- u, v := new(fe).set(a), new(fe)
- exp(c, a, pPlus1Over4)
- square(v, c)
-
- return u.equal(v)
-}
-
-func isQuadraticNonResidue(elem *fe) bool {
- result := new(fe)
- exp(result, elem, pMinus1Over2)
-
- return !result.isOne()
-}
diff --git a/crypto/bls12381/fp12.go b/crypto/bls12381/fp12.go
deleted file mode 100644
index 9645d067c6..0000000000
--- a/crypto/bls12381/fp12.go
+++ /dev/null
@@ -1,291 +0,0 @@
-// Copyright 2020 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 bls12381
-
-import (
- "errors"
- "math/big"
-)
-
-type fp12 struct {
- fp12temp
- fp6 *fp6
-}
-
-type fp12temp struct {
- t2 [9]*fe2
- t6 [5]*fe6
- t12 *fe12
-}
-
-func newFp12Temp() fp12temp {
- t2 := [9]*fe2{}
- t6 := [5]*fe6{}
-
- for i := 0; i < len(t2); i++ {
- t2[i] = &fe2{}
- }
-
- for i := 0; i < len(t6); i++ {
- t6[i] = &fe6{}
- }
-
- return fp12temp{t2, t6, &fe12{}}
-}
-
-func newFp12(fp6 *fp6) *fp12 {
- t := newFp12Temp()
- if fp6 == nil {
- return &fp12{t, newFp6(nil)}
- }
-
- return &fp12{t, fp6}
-}
-
-func (e *fp12) fp2() *fp2 {
- return e.fp6.fp2
-}
-
-func (e *fp12) fromBytes(in []byte) (*fe12, error) {
- if len(in) != 576 {
- return nil, errors.New("input string should be larger than 96 bytes")
- }
-
- fp6 := e.fp6
-
- c1, err := fp6.fromBytes(in[:288])
- if err != nil {
- return nil, err
- }
-
- c0, err := fp6.fromBytes(in[288:])
- if err != nil {
- return nil, err
- }
-
- return &fe12{*c0, *c1}, nil
-}
-
-func (e *fp12) toBytes(a *fe12) []byte {
- fp6 := e.fp6
- out := make([]byte, 576)
- copy(out[:288], fp6.toBytes(&a[1]))
- copy(out[288:], fp6.toBytes(&a[0]))
-
- return out
-}
-
-func (e *fp12) new() *fe12 {
- return new(fe12)
-}
-
-func (e *fp12) zero() *fe12 {
- return new(fe12)
-}
-
-func (e *fp12) one() *fe12 {
- return new(fe12).one()
-}
-
-func (e *fp12) add(c, a, b *fe12) {
- fp6 := e.fp6
- fp6.add(&c[0], &a[0], &b[0])
- fp6.add(&c[1], &a[1], &b[1])
-}
-
-func (e *fp12) double(c, a *fe12) {
- fp6 := e.fp6
- fp6.double(&c[0], &a[0])
- fp6.double(&c[1], &a[1])
-}
-
-func (e *fp12) sub(c, a, b *fe12) {
- fp6 := e.fp6
- fp6.sub(&c[0], &a[0], &b[0])
- fp6.sub(&c[1], &a[1], &b[1])
-}
-
-func (e *fp12) neg(c, a *fe12) {
- fp6 := e.fp6
- fp6.neg(&c[0], &a[0])
- fp6.neg(&c[1], &a[1])
-}
-
-func (e *fp12) conjugate(c, a *fe12) {
- fp6 := e.fp6
-
- c[0].set(&a[0])
- fp6.neg(&c[1], &a[1])
-}
-
-func (e *fp12) square(c, a *fe12) {
- fp6, t := e.fp6, e.t6
- fp6.add(t[0], &a[0], &a[1])
- fp6.mul(t[2], &a[0], &a[1])
- fp6.mulByNonResidue(t[1], &a[1])
- fp6.addAssign(t[1], &a[0])
- fp6.mulByNonResidue(t[3], t[2])
- fp6.mulAssign(t[0], t[1])
- fp6.subAssign(t[0], t[2])
- fp6.sub(&c[0], t[0], t[3])
- fp6.double(&c[1], t[2])
-}
-
-func (e *fp12) cyclotomicSquare(c, a *fe12) {
- t, fp2 := e.t2, e.fp2()
- e.fp4Square(t[3], t[4], &a[0][0], &a[1][1])
- fp2.sub(t[2], t[3], &a[0][0])
- fp2.doubleAssign(t[2])
- fp2.add(&c[0][0], t[2], t[3])
- fp2.add(t[2], t[4], &a[1][1])
- fp2.doubleAssign(t[2])
- fp2.add(&c[1][1], t[2], t[4])
- e.fp4Square(t[3], t[4], &a[1][0], &a[0][2])
- e.fp4Square(t[5], t[6], &a[0][1], &a[1][2])
- fp2.sub(t[2], t[3], &a[0][1])
- fp2.doubleAssign(t[2])
- fp2.add(&c[0][1], t[2], t[3])
- fp2.add(t[2], t[4], &a[1][2])
- fp2.doubleAssign(t[2])
- fp2.add(&c[1][2], t[2], t[4])
- fp2.mulByNonResidue(t[3], t[6])
- fp2.add(t[2], t[3], &a[1][0])
- fp2.doubleAssign(t[2])
- fp2.add(&c[1][0], t[2], t[3])
- fp2.sub(t[2], t[5], &a[0][2])
- fp2.doubleAssign(t[2])
- fp2.add(&c[0][2], t[2], t[5])
-}
-
-func (e *fp12) mul(c, a, b *fe12) {
- t, fp6 := e.t6, e.fp6
- fp6.mul(t[1], &a[0], &b[0])
- fp6.mul(t[2], &a[1], &b[1])
- fp6.add(t[0], t[1], t[2])
- fp6.mulByNonResidue(t[2], t[2])
- fp6.add(t[3], t[1], t[2])
- fp6.add(t[1], &a[0], &a[1])
- fp6.add(t[2], &b[0], &b[1])
- fp6.mulAssign(t[1], t[2])
- c[0].set(t[3])
- fp6.sub(&c[1], t[1], t[0])
-}
-
-func (e *fp12) mulAssign(a, b *fe12) {
- t, fp6 := e.t6, e.fp6
- fp6.mul(t[1], &a[0], &b[0])
- fp6.mul(t[2], &a[1], &b[1])
- fp6.add(t[0], t[1], t[2])
- fp6.mulByNonResidue(t[2], t[2])
- fp6.add(t[3], t[1], t[2])
- fp6.add(t[1], &a[0], &a[1])
- fp6.add(t[2], &b[0], &b[1])
- fp6.mulAssign(t[1], t[2])
- a[0].set(t[3])
- fp6.sub(&a[1], t[1], t[0])
-}
-
-func (e *fp12) fp4Square(c0, c1, a0, a1 *fe2) {
- t, fp2 := e.t2, e.fp2()
- fp2.square(t[0], a0)
- fp2.square(t[1], a1)
- fp2.mulByNonResidue(t[2], t[1])
- fp2.add(c0, t[2], t[0])
- fp2.add(t[2], a0, a1)
- fp2.squareAssign(t[2])
- fp2.subAssign(t[2], t[0])
- fp2.sub(c1, t[2], t[1])
-}
-
-func (e *fp12) inverse(c, a *fe12) {
- fp6, t := e.fp6, e.t6
- fp6.square(t[0], &a[0])
- fp6.square(t[1], &a[1])
- fp6.mulByNonResidue(t[1], t[1])
- fp6.sub(t[1], t[0], t[1])
- fp6.inverse(t[0], t[1])
- fp6.mul(&c[0], &a[0], t[0])
- fp6.mulAssign(t[0], &a[1])
- fp6.neg(&c[1], t[0])
-}
-
-func (e *fp12) mulBy014Assign(a *fe12, c0, c1, c4 *fe2) {
- fp2, fp6, t, t2 := e.fp2(), e.fp6, e.t6, e.t2[0]
- fp6.mulBy01(t[0], &a[0], c0, c1)
- fp6.mulBy1(t[1], &a[1], c4)
- fp2.add(t2, c1, c4)
- fp6.add(t[2], &a[1], &a[0])
- fp6.mulBy01Assign(t[2], c0, t2)
- fp6.subAssign(t[2], t[0])
- fp6.sub(&a[1], t[2], t[1])
- fp6.mulByNonResidue(t[1], t[1])
- fp6.add(&a[0], t[1], t[0])
-}
-
-func (e *fp12) exp(c, a *fe12, s *big.Int) {
- z := e.one()
- for i := s.BitLen() - 1; i >= 0; i-- {
- e.square(z, z)
-
- if s.Bit(i) == 1 {
- e.mul(z, z, a)
- }
- }
- c.set(z)
-}
-
-func (e *fp12) cyclotomicExp(c, a *fe12, s *big.Int) {
- z := e.one()
- for i := s.BitLen() - 1; i >= 0; i-- {
- e.cyclotomicSquare(z, z)
-
- if s.Bit(i) == 1 {
- e.mul(z, z, a)
- }
- }
- c.set(z)
-}
-
-func (e *fp12) frobeniusMap(c, a *fe12, power uint) {
- fp6 := e.fp6
- fp6.frobeniusMap(&c[0], &a[0], power)
- fp6.frobeniusMap(&c[1], &a[1], power)
-
- switch power {
- case 0:
- return
- case 6:
- fp6.neg(&c[1], &c[1])
- default:
- fp6.mulByBaseField(&c[1], &c[1], &frobeniusCoeffs12[power])
- }
-}
-
-func (e *fp12) frobeniusMapAssign(a *fe12, power uint) {
- fp6 := e.fp6
- fp6.frobeniusMapAssign(&a[0], power)
- fp6.frobeniusMapAssign(&a[1], power)
-
- switch power {
- case 0:
- return
- case 6:
- fp6.neg(&a[1], &a[1])
- default:
- fp6.mulByBaseField(&a[1], &a[1], &frobeniusCoeffs12[power])
- }
-}
diff --git a/crypto/bls12381/fp2.go b/crypto/bls12381/fp2.go
deleted file mode 100644
index 412567964a..0000000000
--- a/crypto/bls12381/fp2.go
+++ /dev/null
@@ -1,265 +0,0 @@
-// Copyright 2020 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 bls12381
-
-import (
- "errors"
- "math/big"
-)
-
-type fp2Temp struct {
- t [4]*fe
-}
-
-type fp2 struct {
- fp2Temp
-}
-
-func newFp2Temp() fp2Temp {
- t := [4]*fe{}
- for i := 0; i < len(t); i++ {
- t[i] = &fe{}
- }
-
- return fp2Temp{t}
-}
-
-func newFp2() *fp2 {
- t := newFp2Temp()
- return &fp2{t}
-}
-
-func (e *fp2) fromBytes(in []byte) (*fe2, error) {
- if len(in) != 96 {
- return nil, errors.New("length of input string should be 96 bytes")
- }
-
- c1, err := fromBytes(in[:48])
- if err != nil {
- return nil, err
- }
-
- c0, err := fromBytes(in[48:])
- if err != nil {
- return nil, err
- }
-
- return &fe2{*c0, *c1}, nil
-}
-
-func (e *fp2) toBytes(a *fe2) []byte {
- out := make([]byte, 96)
- copy(out[:48], toBytes(&a[1]))
- copy(out[48:], toBytes(&a[0]))
-
- return out
-}
-
-func (e *fp2) new() *fe2 {
- return new(fe2).zero()
-}
-
-func (e *fp2) zero() *fe2 {
- return new(fe2).zero()
-}
-
-func (e *fp2) one() *fe2 {
- return new(fe2).one()
-}
-
-func (e *fp2) add(c, a, b *fe2) {
- add(&c[0], &a[0], &b[0])
- add(&c[1], &a[1], &b[1])
-}
-
-func (e *fp2) addAssign(a, b *fe2) {
- addAssign(&a[0], &b[0])
- addAssign(&a[1], &b[1])
-}
-
-func (e *fp2) ladd(c, a, b *fe2) {
- ladd(&c[0], &a[0], &b[0])
- ladd(&c[1], &a[1], &b[1])
-}
-
-func (e *fp2) double(c, a *fe2) {
- double(&c[0], &a[0])
- double(&c[1], &a[1])
-}
-
-func (e *fp2) doubleAssign(a *fe2) {
- doubleAssign(&a[0])
- doubleAssign(&a[1])
-}
-
-func (e *fp2) ldouble(c, a *fe2) {
- ldouble(&c[0], &a[0])
- ldouble(&c[1], &a[1])
-}
-
-func (e *fp2) sub(c, a, b *fe2) {
- sub(&c[0], &a[0], &b[0])
- sub(&c[1], &a[1], &b[1])
-}
-
-func (e *fp2) subAssign(c, a *fe2) {
- subAssign(&c[0], &a[0])
- subAssign(&c[1], &a[1])
-}
-
-func (e *fp2) neg(c, a *fe2) {
- neg(&c[0], &a[0])
- neg(&c[1], &a[1])
-}
-
-func (e *fp2) mul(c, a, b *fe2) {
- t := e.t
- mul(t[1], &a[0], &b[0])
- mul(t[2], &a[1], &b[1])
- add(t[0], &a[0], &a[1])
- add(t[3], &b[0], &b[1])
- sub(&c[0], t[1], t[2])
- addAssign(t[1], t[2])
- mul(t[0], t[0], t[3])
- sub(&c[1], t[0], t[1])
-}
-
-func (e *fp2) mulAssign(a, b *fe2) {
- t := e.t
- mul(t[1], &a[0], &b[0])
- mul(t[2], &a[1], &b[1])
- add(t[0], &a[0], &a[1])
- add(t[3], &b[0], &b[1])
- sub(&a[0], t[1], t[2])
- addAssign(t[1], t[2])
- mul(t[0], t[0], t[3])
- sub(&a[1], t[0], t[1])
-}
-
-func (e *fp2) square(c, a *fe2) {
- t := e.t
- ladd(t[0], &a[0], &a[1])
- sub(t[1], &a[0], &a[1])
- ldouble(t[2], &a[0])
- mul(&c[0], t[0], t[1])
- mul(&c[1], t[2], &a[1])
-}
-
-func (e *fp2) squareAssign(a *fe2) {
- t := e.t
- ladd(t[0], &a[0], &a[1])
- sub(t[1], &a[0], &a[1])
- ldouble(t[2], &a[0])
- mul(&a[0], t[0], t[1])
- mul(&a[1], t[2], &a[1])
-}
-
-func (e *fp2) mulByNonResidue(c, a *fe2) {
- t := e.t
- sub(t[0], &a[0], &a[1])
- add(&c[1], &a[0], &a[1])
- c[0].set(t[0])
-}
-
-func (e *fp2) mulByB(c, a *fe2) {
- t := e.t
- double(t[0], &a[0])
- double(t[1], &a[1])
- doubleAssign(t[0])
- doubleAssign(t[1])
- sub(&c[0], t[0], t[1])
- add(&c[1], t[0], t[1])
-}
-
-func (e *fp2) inverse(c, a *fe2) {
- t := e.t
- square(t[0], &a[0])
- square(t[1], &a[1])
- addAssign(t[0], t[1])
- inverse(t[0], t[0])
- mul(&c[0], &a[0], t[0])
- mul(t[0], t[0], &a[1])
- neg(&c[1], t[0])
-}
-
-func (e *fp2) mulByFq(c, a *fe2, b *fe) {
- mul(&c[0], &a[0], b)
- mul(&c[1], &a[1], b)
-}
-
-func (e *fp2) exp(c, a *fe2, s *big.Int) {
- z := e.one()
- for i := s.BitLen() - 1; i >= 0; i-- {
- e.square(z, z)
-
- if s.Bit(i) == 1 {
- e.mul(z, z, a)
- }
- }
- c.set(z)
-}
-
-func (e *fp2) frobeniusMap(c, a *fe2, power uint) {
- c[0].set(&a[0])
-
- if power%2 == 1 {
- neg(&c[1], &a[1])
- return
- }
-
- c[1].set(&a[1])
-}
-
-func (e *fp2) frobeniusMapAssign(a *fe2, power uint) {
- if power%2 == 1 {
- neg(&a[1], &a[1])
- return
- }
-}
-
-func (e *fp2) sqrt(c, a *fe2) bool {
- u, x0, a1, alpha := &fe2{}, &fe2{}, &fe2{}, &fe2{}
- u.set(a)
- e.exp(a1, a, pMinus3Over4)
- e.square(alpha, a1)
- e.mul(alpha, alpha, a)
- e.mul(x0, a1, a)
-
- if alpha.equal(negativeOne2) {
- neg(&c[0], &x0[1])
- c[1].set(&x0[0])
-
- return true
- }
-
- e.add(alpha, alpha, e.one())
- e.exp(alpha, alpha, pMinus1Over2)
- e.mul(c, alpha, x0)
- e.square(alpha, c)
-
- return alpha.equal(u)
-}
-
-func (e *fp2) isQuadraticNonResidue(a *fe2) bool {
- // https://github.com/leovt/constructible/wiki/Taking-Square-Roots-in-quadratic-extension-Fields
- c0, c1 := new(fe), new(fe)
- square(c0, &a[0])
- square(c1, &a[1])
- add(c1, c1, c0)
-
- return isQuadraticNonResidue(c1)
-}
diff --git a/crypto/bls12381/fp6.go b/crypto/bls12381/fp6.go
deleted file mode 100644
index bd916c3542..0000000000
--- a/crypto/bls12381/fp6.go
+++ /dev/null
@@ -1,363 +0,0 @@
-// Copyright 2020 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 bls12381
-
-import (
- "errors"
- "math/big"
-)
-
-type fp6Temp struct {
- t [6]*fe2
-}
-
-type fp6 struct {
- fp2 *fp2
- fp6Temp
-}
-
-func newFp6Temp() fp6Temp {
- t := [6]*fe2{}
- for i := 0; i < len(t); i++ {
- t[i] = &fe2{}
- }
-
- return fp6Temp{t}
-}
-
-func newFp6(f *fp2) *fp6 {
- t := newFp6Temp()
- if f == nil {
- return &fp6{newFp2(), t}
- }
-
- return &fp6{f, t}
-}
-
-func (e *fp6) fromBytes(b []byte) (*fe6, error) {
- if len(b) < 288 {
- return nil, errors.New("input string should be larger than 288 bytes")
- }
-
- fp2 := e.fp2
-
- u2, err := fp2.fromBytes(b[:96])
- if err != nil {
- return nil, err
- }
-
- u1, err := fp2.fromBytes(b[96:192])
- if err != nil {
- return nil, err
- }
-
- u0, err := fp2.fromBytes(b[192:])
- if err != nil {
- return nil, err
- }
-
- return &fe6{*u0, *u1, *u2}, nil
-}
-
-func (e *fp6) toBytes(a *fe6) []byte {
- fp2 := e.fp2
- out := make([]byte, 288)
- copy(out[:96], fp2.toBytes(&a[2]))
- copy(out[96:192], fp2.toBytes(&a[1]))
- copy(out[192:], fp2.toBytes(&a[0]))
-
- return out
-}
-
-func (e *fp6) new() *fe6 {
- return new(fe6)
-}
-
-func (e *fp6) zero() *fe6 {
- return new(fe6)
-}
-
-func (e *fp6) one() *fe6 {
- return new(fe6).one()
-}
-
-func (e *fp6) add(c, a, b *fe6) {
- fp2 := e.fp2
- fp2.add(&c[0], &a[0], &b[0])
- fp2.add(&c[1], &a[1], &b[1])
- fp2.add(&c[2], &a[2], &b[2])
-}
-
-func (e *fp6) addAssign(a, b *fe6) {
- fp2 := e.fp2
- fp2.addAssign(&a[0], &b[0])
- fp2.addAssign(&a[1], &b[1])
- fp2.addAssign(&a[2], &b[2])
-}
-
-func (e *fp6) double(c, a *fe6) {
- fp2 := e.fp2
- fp2.double(&c[0], &a[0])
- fp2.double(&c[1], &a[1])
- fp2.double(&c[2], &a[2])
-}
-
-func (e *fp6) doubleAssign(a *fe6) {
- fp2 := e.fp2
- fp2.doubleAssign(&a[0])
- fp2.doubleAssign(&a[1])
- fp2.doubleAssign(&a[2])
-}
-
-func (e *fp6) sub(c, a, b *fe6) {
- fp2 := e.fp2
- fp2.sub(&c[0], &a[0], &b[0])
- fp2.sub(&c[1], &a[1], &b[1])
- fp2.sub(&c[2], &a[2], &b[2])
-}
-
-func (e *fp6) subAssign(a, b *fe6) {
- fp2 := e.fp2
- fp2.subAssign(&a[0], &b[0])
- fp2.subAssign(&a[1], &b[1])
- fp2.subAssign(&a[2], &b[2])
-}
-
-func (e *fp6) neg(c, a *fe6) {
- fp2 := e.fp2
- fp2.neg(&c[0], &a[0])
- fp2.neg(&c[1], &a[1])
- fp2.neg(&c[2], &a[2])
-}
-
-func (e *fp6) mul(c, a, b *fe6) {
- fp2, t := e.fp2, e.t
- fp2.mul(t[0], &a[0], &b[0])
- fp2.mul(t[1], &a[1], &b[1])
- fp2.mul(t[2], &a[2], &b[2])
- fp2.add(t[3], &a[1], &a[2])
- fp2.add(t[4], &b[1], &b[2])
- fp2.mulAssign(t[3], t[4])
- fp2.add(t[4], t[1], t[2])
- fp2.subAssign(t[3], t[4])
- fp2.mulByNonResidue(t[3], t[3])
- fp2.add(t[5], t[0], t[3])
- fp2.add(t[3], &a[0], &a[1])
- fp2.add(t[4], &b[0], &b[1])
- fp2.mulAssign(t[3], t[4])
- fp2.add(t[4], t[0], t[1])
- fp2.subAssign(t[3], t[4])
- fp2.mulByNonResidue(t[4], t[2])
- fp2.add(&c[1], t[3], t[4])
- fp2.add(t[3], &a[0], &a[2])
- fp2.add(t[4], &b[0], &b[2])
- fp2.mulAssign(t[3], t[4])
- fp2.add(t[4], t[0], t[2])
- fp2.subAssign(t[3], t[4])
- fp2.add(&c[2], t[1], t[3])
- c[0].set(t[5])
-}
-
-func (e *fp6) mulAssign(a, b *fe6) {
- fp2, t := e.fp2, e.t
- fp2.mul(t[0], &a[0], &b[0])
- fp2.mul(t[1], &a[1], &b[1])
- fp2.mul(t[2], &a[2], &b[2])
- fp2.add(t[3], &a[1], &a[2])
- fp2.add(t[4], &b[1], &b[2])
- fp2.mulAssign(t[3], t[4])
- fp2.add(t[4], t[1], t[2])
- fp2.subAssign(t[3], t[4])
- fp2.mulByNonResidue(t[3], t[3])
- fp2.add(t[5], t[0], t[3])
- fp2.add(t[3], &a[0], &a[1])
- fp2.add(t[4], &b[0], &b[1])
- fp2.mulAssign(t[3], t[4])
- fp2.add(t[4], t[0], t[1])
- fp2.subAssign(t[3], t[4])
- fp2.mulByNonResidue(t[4], t[2])
- fp2.add(&a[1], t[3], t[4])
- fp2.add(t[3], &a[0], &a[2])
- fp2.add(t[4], &b[0], &b[2])
- fp2.mulAssign(t[3], t[4])
- fp2.add(t[4], t[0], t[2])
- fp2.subAssign(t[3], t[4])
- fp2.add(&a[2], t[1], t[3])
- a[0].set(t[5])
-}
-
-func (e *fp6) square(c, a *fe6) {
- fp2, t := e.fp2, e.t
- fp2.square(t[0], &a[0])
- fp2.mul(t[1], &a[0], &a[1])
- fp2.doubleAssign(t[1])
- fp2.sub(t[2], &a[0], &a[1])
- fp2.addAssign(t[2], &a[2])
- fp2.squareAssign(t[2])
- fp2.mul(t[3], &a[1], &a[2])
- fp2.doubleAssign(t[3])
- fp2.square(t[4], &a[2])
- fp2.mulByNonResidue(t[5], t[3])
- fp2.add(&c[0], t[0], t[5])
- fp2.mulByNonResidue(t[5], t[4])
- fp2.add(&c[1], t[1], t[5])
- fp2.addAssign(t[1], t[2])
- fp2.addAssign(t[1], t[3])
- fp2.addAssign(t[0], t[4])
- fp2.sub(&c[2], t[1], t[0])
-}
-
-func (e *fp6) mulBy01Assign(a *fe6, b0, b1 *fe2) {
- fp2, t := e.fp2, e.t
- fp2.mul(t[0], &a[0], b0)
- fp2.mul(t[1], &a[1], b1)
- fp2.add(t[5], &a[1], &a[2])
- fp2.mul(t[2], b1, t[5])
- fp2.subAssign(t[2], t[1])
- fp2.mulByNonResidue(t[2], t[2])
- fp2.add(t[5], &a[0], &a[2])
- fp2.mul(t[3], b0, t[5])
- fp2.subAssign(t[3], t[0])
- fp2.add(&a[2], t[3], t[1])
- fp2.add(t[4], b0, b1)
- fp2.add(t[5], &a[0], &a[1])
- fp2.mulAssign(t[4], t[5])
- fp2.subAssign(t[4], t[0])
- fp2.sub(&a[1], t[4], t[1])
- fp2.add(&a[0], t[2], t[0])
-}
-
-func (e *fp6) mulBy01(c, a *fe6, b0, b1 *fe2) {
- fp2, t := e.fp2, e.t
- fp2.mul(t[0], &a[0], b0)
- fp2.mul(t[1], &a[1], b1)
- fp2.add(t[2], &a[1], &a[2])
- fp2.mulAssign(t[2], b1)
- fp2.subAssign(t[2], t[1])
- fp2.mulByNonResidue(t[2], t[2])
- fp2.add(t[3], &a[0], &a[2])
- fp2.mulAssign(t[3], b0)
- fp2.subAssign(t[3], t[0])
- fp2.add(&c[2], t[3], t[1])
- fp2.add(t[4], b0, b1)
- fp2.add(t[3], &a[0], &a[1])
- fp2.mulAssign(t[4], t[3])
- fp2.subAssign(t[4], t[0])
- fp2.sub(&c[1], t[4], t[1])
- fp2.add(&c[0], t[2], t[0])
-}
-
-func (e *fp6) mulBy1(c, a *fe6, b1 *fe2) {
- fp2, t := e.fp2, e.t
- fp2.mul(t[0], &a[2], b1)
- fp2.mul(&c[2], &a[1], b1)
- fp2.mul(&c[1], &a[0], b1)
- fp2.mulByNonResidue(&c[0], t[0])
-}
-
-func (e *fp6) mulByNonResidue(c, a *fe6) {
- fp2, t := e.fp2, e.t
- t[0].set(&a[0])
- fp2.mulByNonResidue(&c[0], &a[2])
- c[2].set(&a[1])
- c[1].set(t[0])
-}
-
-func (e *fp6) mulByBaseField(c, a *fe6, b *fe2) {
- fp2 := e.fp2
- fp2.mul(&c[0], &a[0], b)
- fp2.mul(&c[1], &a[1], b)
- fp2.mul(&c[2], &a[2], b)
-}
-
-func (e *fp6) exp(c, a *fe6, s *big.Int) {
- z := e.one()
- for i := s.BitLen() - 1; i >= 0; i-- {
- e.square(z, z)
-
- if s.Bit(i) == 1 {
- e.mul(z, z, a)
- }
- }
- c.set(z)
-}
-
-func (e *fp6) inverse(c, a *fe6) {
- fp2, t := e.fp2, e.t
- fp2.square(t[0], &a[0])
- fp2.mul(t[1], &a[1], &a[2])
- fp2.mulByNonResidue(t[1], t[1])
- fp2.subAssign(t[0], t[1])
- fp2.square(t[1], &a[1])
- fp2.mul(t[2], &a[0], &a[2])
- fp2.subAssign(t[1], t[2])
- fp2.square(t[2], &a[2])
- fp2.mulByNonResidue(t[2], t[2])
- fp2.mul(t[3], &a[0], &a[1])
- fp2.subAssign(t[2], t[3])
- fp2.mul(t[3], &a[2], t[2])
- fp2.mul(t[4], &a[1], t[1])
- fp2.addAssign(t[3], t[4])
- fp2.mulByNonResidue(t[3], t[3])
- fp2.mul(t[4], &a[0], t[0])
- fp2.addAssign(t[3], t[4])
- fp2.inverse(t[3], t[3])
- fp2.mul(&c[0], t[0], t[3])
- fp2.mul(&c[1], t[2], t[3])
- fp2.mul(&c[2], t[1], t[3])
-}
-
-func (e *fp6) frobeniusMap(c, a *fe6, power uint) {
- fp2 := e.fp2
- fp2.frobeniusMap(&c[0], &a[0], power)
- fp2.frobeniusMap(&c[1], &a[1], power)
- fp2.frobeniusMap(&c[2], &a[2], power)
-
- switch power % 6 {
- case 0:
- return
- case 3:
- neg(&c[0][0], &a[1][1])
- c[1][1].set(&a[1][0])
- fp2.neg(&a[2], &a[2])
- default:
- fp2.mul(&c[1], &c[1], &frobeniusCoeffs61[power%6])
- fp2.mul(&c[2], &c[2], &frobeniusCoeffs62[power%6])
- }
-}
-
-func (e *fp6) frobeniusMapAssign(a *fe6, power uint) {
- fp2 := e.fp2
- fp2.frobeniusMapAssign(&a[0], power)
- fp2.frobeniusMapAssign(&a[1], power)
- fp2.frobeniusMapAssign(&a[2], power)
-
- t := e.t
-
- switch power % 6 {
- case 0:
- return
- case 3:
- neg(&t[0][0], &a[1][1])
- a[1][1].set(&a[1][0])
- a[1][0].set(&t[0][0])
- fp2.neg(&a[2], &a[2])
- default:
- fp2.mulAssign(&a[1], &frobeniusCoeffs61[power%6])
- fp2.mulAssign(&a[2], &frobeniusCoeffs62[power%6])
- }
-}
diff --git a/crypto/bls12381/fp_test.go b/crypto/bls12381/fp_test.go
deleted file mode 100644
index dcd90bb6f7..0000000000
--- a/crypto/bls12381/fp_test.go
+++ /dev/null
@@ -1,1774 +0,0 @@
-package bls12381
-
-import (
- "bytes"
- "crypto/rand"
- "math/big"
- "testing"
-)
-
-func TestFpSerialization(t *testing.T) {
- t.Run("zero", func(t *testing.T) {
- in := make([]byte, 48)
-
- fe, err := fromBytes(in)
- if err != nil {
- t.Fatal(err)
- }
-
- if !fe.isZero() {
- t.Fatal("bad serialization")
- }
-
- if !bytes.Equal(in, toBytes(fe)) {
- t.Fatal("bad serialization")
- }
- })
- t.Run("bytes", func(t *testing.T) {
- for i := 0; i < fuz; i++ {
- a, _ := new(fe).rand(rand.Reader)
-
- b, err := fromBytes(toBytes(a))
- if err != nil {
- t.Fatal(err)
- }
-
- if !a.equal(b) {
- t.Fatal("bad serialization")
- }
- }
- })
- t.Run("string", func(t *testing.T) {
- for i := 0; i < fuz; i++ {
- a, _ := new(fe).rand(rand.Reader)
-
- b, err := fromString(toString(a))
- if err != nil {
- t.Fatal(err)
- }
-
- if !a.equal(b) {
- t.Fatal("bad encoding or decoding")
- }
- }
- })
- t.Run("big", func(t *testing.T) {
- for i := 0; i < fuz; i++ {
- a, _ := new(fe).rand(rand.Reader)
-
- b, err := fromBig(toBig(a))
- if err != nil {
- t.Fatal(err)
- }
-
- if !a.equal(b) {
- t.Fatal("bad encoding or decoding")
- }
- }
- })
-}
-
-func TestFpAdditionCrossAgainstBigInt(t *testing.T) {
- for i := 0; i < fuz; i++ {
- a, _ := new(fe).rand(rand.Reader)
- b, _ := new(fe).rand(rand.Reader)
- c := new(fe)
- big_a := toBig(a)
- big_b := toBig(b)
- big_c := new(big.Int)
-
- add(c, a, b)
- out_1 := toBytes(c)
- out_2 := padBytes(big_c.Add(big_a, big_b).Mod(big_c, modulus.big()).Bytes(), 48)
-
- if !bytes.Equal(out_1, out_2) {
- t.Fatal("cross test against big.Int is not satisfied A")
- }
-
- double(c, a)
- out_1 = toBytes(c)
- out_2 = padBytes(big_c.Add(big_a, big_a).Mod(big_c, modulus.big()).Bytes(), 48)
-
- if !bytes.Equal(out_1, out_2) {
- t.Fatal("cross test against big.Int is not satisfied B")
- }
-
- sub(c, a, b)
- out_1 = toBytes(c)
- out_2 = padBytes(big_c.Sub(big_a, big_b).Mod(big_c, modulus.big()).Bytes(), 48)
-
- if !bytes.Equal(out_1, out_2) {
- t.Fatal("cross test against big.Int is not satisfied C")
- }
-
- neg(c, a)
- out_1 = toBytes(c)
- out_2 = padBytes(big_c.Neg(big_a).Mod(big_c, modulus.big()).Bytes(), 48)
-
- if !bytes.Equal(out_1, out_2) {
- t.Fatal("cross test against big.Int is not satisfied D")
- }
- }
-}
-
-func TestFpAdditionCrossAgainstBigIntAssigned(t *testing.T) {
- for i := 0; i < fuz; i++ {
- a, _ := new(fe).rand(rand.Reader)
- b, _ := new(fe).rand(rand.Reader)
- big_a, big_b := toBig(a), toBig(b)
- addAssign(a, b)
- out_1 := toBytes(a)
- out_2 := padBytes(big_a.Add(big_a, big_b).Mod(big_a, modulus.big()).Bytes(), 48)
-
- if !bytes.Equal(out_1, out_2) {
- t.Fatal("cross test against big.Int is not satisfied A")
- }
-
- a, _ = new(fe).rand(rand.Reader)
- big_a = toBig(a)
- doubleAssign(a)
- out_1 = toBytes(a)
- out_2 = padBytes(big_a.Add(big_a, big_a).Mod(big_a, modulus.big()).Bytes(), 48)
-
- if !bytes.Equal(out_1, out_2) {
- t.Fatal("cross test against big.Int is not satisfied B")
- }
-
- a, _ = new(fe).rand(rand.Reader)
- b, _ = new(fe).rand(rand.Reader)
- big_a, big_b = toBig(a), toBig(b)
- subAssign(a, b)
- out_1 = toBytes(a)
- out_2 = padBytes(big_a.Sub(big_a, big_b).Mod(big_a, modulus.big()).Bytes(), 48)
-
- if !bytes.Equal(out_1, out_2) {
- t.Fatal("cross test against big.Int is not satisfied A")
- }
- }
-}
-
-func TestFpAdditionProperties(t *testing.T) {
- for i := 0; i < fuz; i++ {
- zero := new(fe).zero()
- a, _ := new(fe).rand(rand.Reader)
- b, _ := new(fe).rand(rand.Reader)
- c_1, c_2 := new(fe), new(fe)
- add(c_1, a, zero)
-
- if !c_1.equal(a) {
- t.Fatal("a + 0 == a")
- }
-
- sub(c_1, a, zero)
-
- if !c_1.equal(a) {
- t.Fatal("a - 0 == a")
- }
-
- double(c_1, zero)
-
- if !c_1.equal(zero) {
- t.Fatal("2 * 0 == 0")
- }
-
- neg(c_1, zero)
-
- if !c_1.equal(zero) {
- t.Fatal("-0 == 0")
- }
-
- sub(c_1, zero, a)
- neg(c_2, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("0-a == -a")
- }
-
- double(c_1, a)
- add(c_2, a, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("2 * a == a + a")
- }
-
- add(c_1, a, b)
- add(c_2, b, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("a + b = b + a")
- }
-
- sub(c_1, a, b)
- sub(c_2, b, a)
- neg(c_2, c_2)
-
- if !c_1.equal(c_2) {
- t.Fatal("a - b = - ( b - a )")
- }
-
- c_x, _ := new(fe).rand(rand.Reader)
-
- add(c_1, a, b)
- add(c_1, c_1, c_x)
- add(c_2, a, c_x)
- add(c_2, c_2, b)
-
- if !c_1.equal(c_2) {
- t.Fatal("(a + b) + c == (a + c ) + b")
- }
-
- sub(c_1, a, b)
- sub(c_1, c_1, c_x)
- sub(c_2, a, c_x)
- sub(c_2, c_2, b)
-
- if !c_1.equal(c_2) {
- t.Fatal("(a - b) - c == (a - c ) -b")
- }
- }
-}
-
-func TestFpAdditionPropertiesAssigned(t *testing.T) {
- for i := 0; i < fuz; i++ {
- zero := new(fe).zero()
- a, b := new(fe), new(fe)
- _, _ = a.rand(rand.Reader)
- b.set(a)
- addAssign(a, zero)
-
- if !a.equal(b) {
- t.Fatal("a + 0 == a")
- }
-
- subAssign(a, zero)
-
- if !a.equal(b) {
- t.Fatal("a - 0 == a")
- }
-
- a.set(zero)
- doubleAssign(a)
-
- if !a.equal(zero) {
- t.Fatal("2 * 0 == 0")
- }
-
- a.set(zero)
- subAssign(a, b)
- neg(b, b)
-
- if !a.equal(b) {
- t.Fatal("0-a == -a")
- }
-
- _, _ = a.rand(rand.Reader)
- b.set(a)
- doubleAssign(a)
- addAssign(b, b)
-
- if !a.equal(b) {
- t.Fatal("2 * a == a + a")
- }
-
- _, _ = a.rand(rand.Reader)
- _, _ = b.rand(rand.Reader)
- c_1, c_2 := new(fe).set(a), new(fe).set(b)
- addAssign(c_1, b)
- addAssign(c_2, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("a + b = b + a")
- }
-
- _, _ = a.rand(rand.Reader)
- _, _ = b.rand(rand.Reader)
-
- c_1.set(a)
- c_2.set(b)
- subAssign(c_1, b)
- subAssign(c_2, a)
- neg(c_2, c_2)
-
- if !c_1.equal(c_2) {
- t.Fatal("a - b = - ( b - a )")
- }
-
- _, _ = a.rand(rand.Reader)
- _, _ = b.rand(rand.Reader)
- c, _ := new(fe).rand(rand.Reader)
- a0 := new(fe).set(a)
- addAssign(a, b)
- addAssign(a, c)
- addAssign(b, c)
- addAssign(b, a0)
-
- if !a.equal(b) {
- t.Fatal("(a + b) + c == (b + c) + a")
- }
-
- _, _ = a.rand(rand.Reader)
- _, _ = b.rand(rand.Reader)
- _, _ = c.rand(rand.Reader)
-
- a0.set(a)
- subAssign(a, b)
- subAssign(a, c)
- subAssign(a0, c)
- subAssign(a0, b)
-
- if !a.equal(a0) {
- t.Fatal("(a - b) - c == (a - c) -b")
- }
- }
-}
-
-func TestFpLazyOperations(t *testing.T) {
- for i := 0; i < fuz; i++ {
- a, _ := new(fe).rand(rand.Reader)
- b, _ := new(fe).rand(rand.Reader)
- c, _ := new(fe).rand(rand.Reader)
- c0 := new(fe)
- c1 := new(fe)
-
- ladd(c0, a, b)
- add(c1, a, b)
- mul(c0, c0, c)
- mul(c1, c1, c)
-
- if !c0.equal(c1) {
- // l+ operator stands for lazy addition
- t.Fatal("(a + b) * c == (a l+ b) * c")
- }
-
- _, _ = a.rand(rand.Reader)
- b.set(a)
- ldouble(a, a)
- ladd(b, b, b)
-
- if !a.equal(b) {
- t.Fatal("2 l* a = a l+ a")
- }
-
- _, _ = a.rand(rand.Reader)
- _, _ = b.rand(rand.Reader)
- _, _ = c.rand(rand.Reader)
- a0 := new(fe).set(a)
- lsubAssign(a, b)
- laddAssign(a, &modulus)
- mul(a, a, c)
- subAssign(a0, b)
- mul(a0, a0, c)
-
- if !a.equal(a0) {
- t.Fatal("((a l- b) + p) * c = (a-b) * c")
- }
- }
-}
-
-func TestFpMultiplicationCrossAgainstBigInt(t *testing.T) {
- for i := 0; i < fuz; i++ {
- a, _ := new(fe).rand(rand.Reader)
- b, _ := new(fe).rand(rand.Reader)
- c := new(fe)
- big_a := toBig(a)
- big_b := toBig(b)
- big_c := new(big.Int)
-
- mul(c, a, b)
- out_1 := toBytes(c)
- out_2 := padBytes(big_c.Mul(big_a, big_b).Mod(big_c, modulus.big()).Bytes(), 48)
-
- if !bytes.Equal(out_1, out_2) {
- t.Fatal("cross test against big.Int is not satisfied")
- }
- }
-}
-
-func TestFpMultiplicationProperties(t *testing.T) {
- for i := 0; i < fuz; i++ {
- a, _ := new(fe).rand(rand.Reader)
- b, _ := new(fe).rand(rand.Reader)
- zero, one := new(fe).zero(), new(fe).one()
- c_1, c_2 := new(fe), new(fe)
- mul(c_1, a, zero)
-
- if !c_1.equal(zero) {
- t.Fatal("a * 0 == 0")
- }
-
- mul(c_1, a, one)
-
- if !c_1.equal(a) {
- t.Fatal("a * 1 == a")
- }
-
- mul(c_1, a, b)
- mul(c_2, b, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("a * b == b * a")
- }
-
- c_x, _ := new(fe).rand(rand.Reader)
-
- mul(c_1, a, b)
- mul(c_1, c_1, c_x)
- mul(c_2, c_x, b)
- mul(c_2, c_2, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("(a * b) * c == (a * c) * b")
- }
-
- square(a, zero)
-
- if !a.equal(zero) {
- t.Fatal("0^2 == 0")
- }
-
- square(a, one)
-
- if !a.equal(one) {
- t.Fatal("1^2 == 1")
- }
-
- _, _ = a.rand(rand.Reader)
- square(c_1, a)
- mul(c_2, a, a)
-
- if !c_1.equal(c_1) {
- t.Fatal("a^2 == a*a")
- }
- }
-}
-
-func TestFpExponentiation(t *testing.T) {
- for i := 0; i < fuz; i++ {
- a, _ := new(fe).rand(rand.Reader)
- u := new(fe)
- exp(u, a, big.NewInt(0))
-
- if !u.isOne() {
- t.Fatal("a^0 == 1")
- }
-
- exp(u, a, big.NewInt(1))
-
- if !u.equal(a) {
- t.Fatal("a^1 == a")
- }
-
- v := new(fe)
-
- mul(u, a, a)
- mul(u, u, u)
- mul(u, u, u)
- exp(v, a, big.NewInt(8))
-
- if !u.equal(v) {
- t.Fatal("((a^2)^2)^2 == a^8")
- }
-
- p := modulus.big()
- exp(u, a, p)
-
- if !u.equal(a) {
- t.Fatal("a^p == a")
- }
-
- exp(u, a, p.Sub(p, big.NewInt(1)))
-
- if !u.isOne() {
- t.Fatal("a^(p-1) == 1")
- }
- }
-}
-
-func TestFpInversion(t *testing.T) {
- for i := 0; i < fuz; i++ {
- u := new(fe)
- zero, one := new(fe).zero(), new(fe).one()
- inverse(u, zero)
-
- if !u.equal(zero) {
- t.Fatal("(0^-1) == 0)")
- }
-
- inverse(u, one)
-
- if !u.equal(one) {
- t.Fatal("(1^-1) == 1)")
- }
-
- a, _ := new(fe).rand(rand.Reader)
- inverse(u, a)
- mul(u, u, a)
-
- if !u.equal(one) {
- t.Fatal("(r*a) * r*(a^-1) == r)")
- }
-
- v := new(fe)
- p := modulus.big()
- exp(u, a, p.Sub(p, big.NewInt(2)))
- inverse(v, a)
-
- if !v.equal(u) {
- t.Fatal("a^(p-2) == a^-1")
- }
- }
-}
-
-func TestFpSquareRoot(t *testing.T) {
- r := new(fe)
- if sqrt(r, nonResidue1) {
- t.Fatal("non residue cannot have a sqrt")
- }
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe).rand(rand.Reader)
- aa, rr, r := &fe{}, &fe{}, &fe{}
- square(aa, a)
-
- if !sqrt(r, aa) {
- t.Fatal("bad sqrt 1")
- }
-
- square(rr, r)
-
- if !rr.equal(aa) {
- t.Fatal("bad sqrt 2")
- }
- }
-}
-
-func TestFpNonResidue(t *testing.T) {
- if !isQuadraticNonResidue(nonResidue1) {
- t.Fatal("element is quadratic non residue, 1")
- }
-
- if isQuadraticNonResidue(new(fe).one()) {
- t.Fatal("one is not quadratic non residue")
- }
-
- if !isQuadraticNonResidue(new(fe).zero()) {
- t.Fatal("should accept zero as quadratic non residue")
- }
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe).rand(rand.Reader)
- square(a, a)
-
- if isQuadraticNonResidue(new(fe).one()) {
- t.Fatal("element is not quadratic non residue")
- }
- }
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe).rand(rand.Reader)
- if !sqrt(new(fe), a) {
- if !isQuadraticNonResidue(a) {
- t.Fatal("element is quadratic non residue, 2", i)
- }
- } else {
- i -= 1
- }
- }
-}
-
-func TestFp2Serialization(t *testing.T) {
- field := newFp2()
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe2).rand(rand.Reader)
-
- b, err := field.fromBytes(field.toBytes(a))
- if err != nil {
- t.Fatal(err)
- }
-
- if !a.equal(b) {
- t.Fatal("bad serialization")
- }
- }
-}
-
-func TestFp2AdditionProperties(t *testing.T) {
- field := newFp2()
- for i := 0; i < fuz; i++ {
- zero := field.zero()
- a, _ := new(fe2).rand(rand.Reader)
- b, _ := new(fe2).rand(rand.Reader)
- c_1 := field.new()
- c_2 := field.new()
- field.add(c_1, a, zero)
-
- if !c_1.equal(a) {
- t.Fatal("a + 0 == a")
- }
-
- field.sub(c_1, a, zero)
-
- if !c_1.equal(a) {
- t.Fatal("a - 0 == a")
- }
-
- field.double(c_1, zero)
-
- if !c_1.equal(zero) {
- t.Fatal("2 * 0 == 0")
- }
-
- field.neg(c_1, zero)
-
- if !c_1.equal(zero) {
- t.Fatal("-0 == 0")
- }
-
- field.sub(c_1, zero, a)
- field.neg(c_2, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("0-a == -a")
- }
-
- field.double(c_1, a)
- field.add(c_2, a, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("2 * a == a + a")
- }
-
- field.add(c_1, a, b)
- field.add(c_2, b, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("a + b = b + a")
- }
-
- field.sub(c_1, a, b)
- field.sub(c_2, b, a)
- field.neg(c_2, c_2)
-
- if !c_1.equal(c_2) {
- t.Fatal("a - b = - ( b - a )")
- }
-
- c_x, _ := new(fe2).rand(rand.Reader)
-
- field.add(c_1, a, b)
- field.add(c_1, c_1, c_x)
- field.add(c_2, a, c_x)
- field.add(c_2, c_2, b)
-
- if !c_1.equal(c_2) {
- t.Fatal("(a + b) + c == (a + c ) + b")
- }
-
- field.sub(c_1, a, b)
- field.sub(c_1, c_1, c_x)
- field.sub(c_2, a, c_x)
- field.sub(c_2, c_2, b)
-
- if !c_1.equal(c_2) {
- t.Fatal("(a - b) - c == (a - c ) -b")
- }
- }
-}
-
-func TestFp2AdditionPropertiesAssigned(t *testing.T) {
- field := newFp2()
-
- for i := 0; i < fuz; i++ {
- zero := new(fe2).zero()
- a, b := new(fe2), new(fe2)
- _, _ = a.rand(rand.Reader)
- b.set(a)
- field.addAssign(a, zero)
-
- if !a.equal(b) {
- t.Fatal("a + 0 == a")
- }
-
- field.subAssign(a, zero)
-
- if !a.equal(b) {
- t.Fatal("a - 0 == a")
- }
-
- a.set(zero)
- field.doubleAssign(a)
-
- if !a.equal(zero) {
- t.Fatal("2 * 0 == 0")
- }
-
- a.set(zero)
- field.subAssign(a, b)
- field.neg(b, b)
-
- if !a.equal(b) {
- t.Fatal("0-a == -a")
- }
-
- _, _ = a.rand(rand.Reader)
- b.set(a)
- field.doubleAssign(a)
- field.addAssign(b, b)
-
- if !a.equal(b) {
- t.Fatal("2 * a == a + a")
- }
-
- _, _ = a.rand(rand.Reader)
- _, _ = b.rand(rand.Reader)
- c_1, c_2 := new(fe2).set(a), new(fe2).set(b)
- field.addAssign(c_1, b)
- field.addAssign(c_2, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("a + b = b + a")
- }
-
- _, _ = a.rand(rand.Reader)
- _, _ = b.rand(rand.Reader)
-
- c_1.set(a)
- c_2.set(b)
- field.subAssign(c_1, b)
- field.subAssign(c_2, a)
- field.neg(c_2, c_2)
-
- if !c_1.equal(c_2) {
- t.Fatal("a - b = - ( b - a )")
- }
-
- _, _ = a.rand(rand.Reader)
- _, _ = b.rand(rand.Reader)
- c, _ := new(fe2).rand(rand.Reader)
- a0 := new(fe2).set(a)
- field.addAssign(a, b)
- field.addAssign(a, c)
- field.addAssign(b, c)
- field.addAssign(b, a0)
-
- if !a.equal(b) {
- t.Fatal("(a + b) + c == (b + c) + a")
- }
-
- _, _ = a.rand(rand.Reader)
- _, _ = b.rand(rand.Reader)
- _, _ = c.rand(rand.Reader)
-
- a0.set(a)
- field.subAssign(a, b)
- field.subAssign(a, c)
- field.subAssign(a0, c)
- field.subAssign(a0, b)
-
- if !a.equal(a0) {
- t.Fatal("(a - b) - c == (a - c) -b")
- }
- }
-}
-
-func TestFp2LazyOperations(t *testing.T) {
- field := newFp2()
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe2).rand(rand.Reader)
- b, _ := new(fe2).rand(rand.Reader)
- c, _ := new(fe2).rand(rand.Reader)
- c0 := new(fe2)
- c1 := new(fe2)
-
- field.ladd(c0, a, b)
- field.add(c1, a, b)
- field.mulAssign(c0, c)
- field.mulAssign(c1, c)
-
- if !c0.equal(c1) {
- // l+ operator stands for lazy addition
- t.Fatal("(a + b) * c == (a l+ b) * c")
- }
-
- _, _ = a.rand(rand.Reader)
- b.set(a)
- field.ldouble(a, a)
- field.ladd(b, b, b)
-
- if !a.equal(b) {
- t.Fatal("2 l* a = a l+ a")
- }
- }
-}
-
-func TestFp2MultiplicationProperties(t *testing.T) {
- field := newFp2()
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe2).rand(rand.Reader)
- b, _ := new(fe2).rand(rand.Reader)
- zero := field.zero()
- one := field.one()
- c_1, c_2 := field.new(), field.new()
- field.mul(c_1, a, zero)
-
- if !c_1.equal(zero) {
- t.Fatal("a * 0 == 0")
- }
-
- field.mul(c_1, a, one)
-
- if !c_1.equal(a) {
- t.Fatal("a * 1 == a")
- }
-
- field.mul(c_1, a, b)
- field.mul(c_2, b, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("a * b == b * a")
- }
-
- c_x, _ := new(fe2).rand(rand.Reader)
-
- field.mul(c_1, a, b)
- field.mul(c_1, c_1, c_x)
- field.mul(c_2, c_x, b)
- field.mul(c_2, c_2, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("(a * b) * c == (a * c) * b")
- }
-
- field.square(a, zero)
-
- if !a.equal(zero) {
- t.Fatal("0^2 == 0")
- }
-
- field.square(a, one)
-
- if !a.equal(one) {
- t.Fatal("1^2 == 1")
- }
-
- _, _ = a.rand(rand.Reader)
- field.square(c_1, a)
- field.mul(c_2, a, a)
-
- if !c_2.equal(c_1) {
- t.Fatal("a^2 == a*a")
- }
- }
-}
-
-func TestFp2MultiplicationPropertiesAssigned(t *testing.T) {
- field := newFp2()
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe2).rand(rand.Reader)
- zero, one := new(fe2).zero(), new(fe2).one()
- field.mulAssign(a, zero)
-
- if !a.equal(zero) {
- t.Fatal("a * 0 == 0")
- }
-
- _, _ = a.rand(rand.Reader)
- a0 := new(fe2).set(a)
- field.mulAssign(a, one)
-
- if !a.equal(a0) {
- t.Fatal("a * 1 == a")
- }
-
- _, _ = a.rand(rand.Reader)
- b, _ := new(fe2).rand(rand.Reader)
-
- a0.set(a)
- field.mulAssign(a, b)
- field.mulAssign(b, a0)
-
- if !a.equal(b) {
- t.Fatal("a * b == b * a")
- }
-
- c, _ := new(fe2).rand(rand.Reader)
-
- a0.set(a)
- field.mulAssign(a, b)
- field.mulAssign(a, c)
- field.mulAssign(a0, c)
- field.mulAssign(a0, b)
-
- if !a.equal(a0) {
- t.Fatal("(a * b) * c == (a * c) * b")
- }
-
- a0.set(a)
- field.squareAssign(a)
- field.mulAssign(a0, a0)
-
- if !a.equal(a0) {
- t.Fatal("a^2 == a*a")
- }
- }
-}
-
-func TestFp2Exponentiation(t *testing.T) {
- field := newFp2()
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe2).rand(rand.Reader)
- u := field.new()
- field.exp(u, a, big.NewInt(0))
-
- if !u.equal(field.one()) {
- t.Fatal("a^0 == 1")
- }
-
- field.exp(u, a, big.NewInt(1))
-
- if !u.equal(a) {
- t.Fatal("a^1 == a")
- }
-
- v := field.new()
- field.mul(u, a, a)
- field.mul(u, u, u)
- field.mul(u, u, u)
- field.exp(v, a, big.NewInt(8))
-
- if !u.equal(v) {
- t.Fatal("((a^2)^2)^2 == a^8")
- }
- }
-}
-
-func TestFp2Inversion(t *testing.T) {
- field := newFp2()
- u := field.new()
- zero := field.zero()
- one := field.one()
- field.inverse(u, zero)
-
- if !u.equal(zero) {
- t.Fatal("(0 ^ -1) == 0)")
- }
-
- field.inverse(u, one)
-
- if !u.equal(one) {
- t.Fatal("(1 ^ -1) == 1)")
- }
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe2).rand(rand.Reader)
- field.inverse(u, a)
- field.mul(u, u, a)
-
- if !u.equal(one) {
- t.Fatal("(r * a) * r * (a ^ -1) == r)")
- }
- }
-}
-
-func TestFp2SquareRoot(t *testing.T) {
- field := newFp2()
-
- for z := 0; z < 1000; z++ {
- zi := new(fe)
- sub(zi, &modulus, &fe{uint64(z * z)})
- // r = (-z*z, 0)
- r := &fe2{*zi, fe{0}}
- toMont(&r[0], &r[0])
- toMont(&r[1], &r[1])
-
- c := field.new()
- // sqrt((-z*z, 0)) = (0, z)
- if !field.sqrt(c, r) {
- t.Fatal("z*z does have a square root")
- }
-
- e := &fe2{fe{uint64(0)}, fe{uint64(z)}}
- toMont(&e[0], &e[0])
- toMont(&e[1], &e[1])
- field.square(e, e)
- field.square(c, c)
-
- if !e.equal(c) {
- t.Fatal("square root failed")
- }
- }
-
- if field.sqrt(field.new(), nonResidue2) {
- t.Fatal("non residue cannot have a sqrt")
- }
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe2).rand(rand.Reader)
- aa, rr, r := field.new(), field.new(), field.new()
- field.square(aa, a)
-
- if !field.sqrt(r, aa) {
- t.Fatal("bad sqrt 1")
- }
-
- field.square(rr, r)
-
- if !rr.equal(aa) {
- t.Fatal("bad sqrt 2")
- }
- }
-}
-
-func TestFp2NonResidue(t *testing.T) {
- field := newFp2()
- if !field.isQuadraticNonResidue(nonResidue2) {
- t.Fatal("element is quadratic non residue, 1")
- }
-
- if field.isQuadraticNonResidue(new(fe2).one()) {
- t.Fatal("one is not quadratic non residue")
- }
-
- if !field.isQuadraticNonResidue(new(fe2).zero()) {
- t.Fatal("should accept zero as quadratic non residue")
- }
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe2).rand(rand.Reader)
- field.squareAssign(a)
-
- if field.isQuadraticNonResidue(new(fe2).one()) {
- t.Fatal("element is not quadratic non residue")
- }
- }
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe2).rand(rand.Reader)
- if !field.sqrt(new(fe2), a) {
- if !field.isQuadraticNonResidue(a) {
- t.Fatal("element is quadratic non residue, 2", i)
- }
- } else {
- i -= 1
- }
- }
-}
-
-func TestFp6Serialization(t *testing.T) {
- field := newFp6(nil)
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe6).rand(rand.Reader)
-
- b, err := field.fromBytes(field.toBytes(a))
- if err != nil {
- t.Fatal(err)
- }
-
- if !a.equal(b) {
- t.Fatal("bad serialization")
- }
- }
-}
-
-func TestFp6AdditionProperties(t *testing.T) {
- field := newFp6(nil)
- for i := 0; i < fuz; i++ {
- zero := field.zero()
- a, _ := new(fe6).rand(rand.Reader)
- b, _ := new(fe6).rand(rand.Reader)
- c_1 := field.new()
- c_2 := field.new()
- field.add(c_1, a, zero)
-
- if !c_1.equal(a) {
- t.Fatal("a + 0 == a")
- }
-
- field.sub(c_1, a, zero)
-
- if !c_1.equal(a) {
- t.Fatal("a - 0 == a")
- }
-
- field.double(c_1, zero)
-
- if !c_1.equal(zero) {
- t.Fatal("2 * 0 == 0")
- }
-
- field.neg(c_1, zero)
-
- if !c_1.equal(zero) {
- t.Fatal("-0 == 0")
- }
-
- field.sub(c_1, zero, a)
- field.neg(c_2, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("0-a == -a")
- }
-
- field.double(c_1, a)
- field.add(c_2, a, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("2 * a == a + a")
- }
-
- field.add(c_1, a, b)
- field.add(c_2, b, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("a + b = b + a")
- }
-
- field.sub(c_1, a, b)
- field.sub(c_2, b, a)
- field.neg(c_2, c_2)
-
- if !c_1.equal(c_2) {
- t.Fatal("a - b = - ( b - a )")
- }
-
- c_x, _ := new(fe6).rand(rand.Reader)
-
- field.add(c_1, a, b)
- field.add(c_1, c_1, c_x)
- field.add(c_2, a, c_x)
- field.add(c_2, c_2, b)
-
- if !c_1.equal(c_2) {
- t.Fatal("(a + b) + c == (a + c ) + b")
- }
-
- field.sub(c_1, a, b)
- field.sub(c_1, c_1, c_x)
- field.sub(c_2, a, c_x)
- field.sub(c_2, c_2, b)
-
- if !c_1.equal(c_2) {
- t.Fatal("(a - b) - c == (a - c ) -b")
- }
- }
-}
-
-func TestFp6AdditionPropertiesAssigned(t *testing.T) {
- field := newFp6(nil)
-
- for i := 0; i < fuz; i++ {
- zero := new(fe6).zero()
- a, b := new(fe6), new(fe6)
- _, _ = a.rand(rand.Reader)
- b.set(a)
- field.addAssign(a, zero)
-
- if !a.equal(b) {
- t.Fatal("a + 0 == a")
- }
-
- field.subAssign(a, zero)
-
- if !a.equal(b) {
- t.Fatal("a - 0 == a")
- }
-
- a.set(zero)
- field.doubleAssign(a)
-
- if !a.equal(zero) {
- t.Fatal("2 * 0 == 0")
- }
-
- a.set(zero)
- field.subAssign(a, b)
- field.neg(b, b)
-
- if !a.equal(b) {
- t.Fatal("0-a == -a")
- }
-
- _, _ = a.rand(rand.Reader)
- b.set(a)
- field.doubleAssign(a)
- field.addAssign(b, b)
-
- if !a.equal(b) {
- t.Fatal("2 * a == a + a")
- }
-
- _, _ = a.rand(rand.Reader)
- _, _ = b.rand(rand.Reader)
- c_1, c_2 := new(fe6).set(a), new(fe6).set(b)
- field.addAssign(c_1, b)
- field.addAssign(c_2, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("a + b = b + a")
- }
-
- _, _ = a.rand(rand.Reader)
- _, _ = b.rand(rand.Reader)
-
- c_1.set(a)
- c_2.set(b)
- field.subAssign(c_1, b)
- field.subAssign(c_2, a)
- field.neg(c_2, c_2)
-
- if !c_1.equal(c_2) {
- t.Fatal("a - b = - ( b - a )")
- }
-
- _, _ = a.rand(rand.Reader)
- _, _ = b.rand(rand.Reader)
- c, _ := new(fe6).rand(rand.Reader)
- a0 := new(fe6).set(a)
- field.addAssign(a, b)
- field.addAssign(a, c)
- field.addAssign(b, c)
- field.addAssign(b, a0)
-
- if !a.equal(b) {
- t.Fatal("(a + b) + c == (b + c) + a")
- }
-
- _, _ = a.rand(rand.Reader)
- _, _ = b.rand(rand.Reader)
- _, _ = c.rand(rand.Reader)
-
- a0.set(a)
- field.subAssign(a, b)
- field.subAssign(a, c)
- field.subAssign(a0, c)
- field.subAssign(a0, b)
-
- if !a.equal(a0) {
- t.Fatal("(a - b) - c == (a - c) -b")
- }
- }
-}
-
-func TestFp6SparseMultiplication(t *testing.T) {
- fp6 := newFp6(nil)
-
- var a, b, u *fe6
- for j := 0; j < fuz; j++ {
- a, _ = new(fe6).rand(rand.Reader)
- b, _ = new(fe6).rand(rand.Reader)
- u, _ = new(fe6).rand(rand.Reader)
-
- b[2].zero()
- fp6.mul(u, a, b)
- fp6.mulBy01(a, a, &b[0], &b[1])
-
- if !a.equal(u) {
- t.Fatal("bad mul by 01")
- }
- }
-
- for j := 0; j < fuz; j++ {
- a, _ = new(fe6).rand(rand.Reader)
- b, _ = new(fe6).rand(rand.Reader)
- u, _ = new(fe6).rand(rand.Reader)
-
- b[2].zero()
- b[0].zero()
- fp6.mul(u, a, b)
- fp6.mulBy1(a, a, &b[1])
-
- if !a.equal(u) {
- t.Fatal("bad mul by 1")
- }
- }
-}
-
-func TestFp6MultiplicationProperties(t *testing.T) {
- field := newFp6(nil)
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe6).rand(rand.Reader)
- b, _ := new(fe6).rand(rand.Reader)
- zero := field.zero()
- one := field.one()
- c_1, c_2 := field.new(), field.new()
- field.mul(c_1, a, zero)
-
- if !c_1.equal(zero) {
- t.Fatal("a * 0 == 0")
- }
-
- field.mul(c_1, a, one)
-
- if !c_1.equal(a) {
- t.Fatal("a * 1 == a")
- }
-
- field.mul(c_1, a, b)
- field.mul(c_2, b, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("a * b == b * a")
- }
-
- c_x, _ := new(fe6).rand(rand.Reader)
-
- field.mul(c_1, a, b)
- field.mul(c_1, c_1, c_x)
- field.mul(c_2, c_x, b)
- field.mul(c_2, c_2, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("(a * b) * c == (a * c) * b")
- }
-
- field.square(a, zero)
-
- if !a.equal(zero) {
- t.Fatal("0^2 == 0")
- }
-
- field.square(a, one)
-
- if !a.equal(one) {
- t.Fatal("1^2 == 1")
- }
-
- _, _ = a.rand(rand.Reader)
- field.square(c_1, a)
- field.mul(c_2, a, a)
-
- if !c_2.equal(c_1) {
- t.Fatal("a^2 == a*a")
- }
- }
-}
-
-func TestFp6MultiplicationPropertiesAssigned(t *testing.T) {
- field := newFp6(nil)
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe6).rand(rand.Reader)
- zero, one := new(fe6).zero(), new(fe6).one()
- field.mulAssign(a, zero)
-
- if !a.equal(zero) {
- t.Fatal("a * 0 == 0")
- }
-
- _, _ = a.rand(rand.Reader)
- a0 := new(fe6).set(a)
- field.mulAssign(a, one)
-
- if !a.equal(a0) {
- t.Fatal("a * 1 == a")
- }
-
- _, _ = a.rand(rand.Reader)
- b, _ := new(fe6).rand(rand.Reader)
-
- a0.set(a)
- field.mulAssign(a, b)
- field.mulAssign(b, a0)
-
- if !a.equal(b) {
- t.Fatal("a * b == b * a")
- }
-
- c, _ := new(fe6).rand(rand.Reader)
-
- a0.set(a)
- field.mulAssign(a, b)
- field.mulAssign(a, c)
- field.mulAssign(a0, c)
- field.mulAssign(a0, b)
-
- if !a.equal(a0) {
- t.Fatal("(a * b) * c == (a * c) * b")
- }
- }
-}
-
-func TestFp6Exponentiation(t *testing.T) {
- field := newFp6(nil)
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe6).rand(rand.Reader)
- u := field.new()
- field.exp(u, a, big.NewInt(0))
-
- if !u.equal(field.one()) {
- t.Fatal("a^0 == 1")
- }
-
- field.exp(u, a, big.NewInt(1))
-
- if !u.equal(a) {
- t.Fatal("a^1 == a")
- }
-
- v := field.new()
- field.mul(u, a, a)
- field.mul(u, u, u)
- field.mul(u, u, u)
- field.exp(v, a, big.NewInt(8))
-
- if !u.equal(v) {
- t.Fatal("((a^2)^2)^2 == a^8")
- }
- }
-}
-
-func TestFp6Inversion(t *testing.T) {
- field := newFp6(nil)
- for i := 0; i < fuz; i++ {
- u := field.new()
- zero := field.zero()
- one := field.one()
- field.inverse(u, zero)
-
- if !u.equal(zero) {
- t.Fatal("(0^-1) == 0)")
- }
-
- field.inverse(u, one)
-
- if !u.equal(one) {
- t.Fatal("(1^-1) == 1)")
- }
-
- a, _ := new(fe6).rand(rand.Reader)
- field.inverse(u, a)
- field.mul(u, u, a)
-
- if !u.equal(one) {
- t.Fatal("(r*a) * r*(a^-1) == r)")
- }
- }
-}
-
-func TestFp12Serialization(t *testing.T) {
- field := newFp12(nil)
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe12).rand(rand.Reader)
-
- b, err := field.fromBytes(field.toBytes(a))
- if err != nil {
- t.Fatal(err)
- }
-
- if !a.equal(b) {
- t.Fatal("bad serialization")
- }
- }
-}
-
-func TestFp12AdditionProperties(t *testing.T) {
- field := newFp12(nil)
- for i := 0; i < fuz; i++ {
- zero := field.zero()
- a, _ := new(fe12).rand(rand.Reader)
- b, _ := new(fe12).rand(rand.Reader)
- c_1 := field.new()
- c_2 := field.new()
- field.add(c_1, a, zero)
-
- if !c_1.equal(a) {
- t.Fatal("a + 0 == a")
- }
-
- field.sub(c_1, a, zero)
-
- if !c_1.equal(a) {
- t.Fatal("a - 0 == a")
- }
-
- field.double(c_1, zero)
-
- if !c_1.equal(zero) {
- t.Fatal("2 * 0 == 0")
- }
-
- field.neg(c_1, zero)
-
- if !c_1.equal(zero) {
- t.Fatal("-0 == 0")
- }
-
- field.sub(c_1, zero, a)
- field.neg(c_2, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("0-a == -a")
- }
-
- field.double(c_1, a)
- field.add(c_2, a, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("2 * a == a + a")
- }
-
- field.add(c_1, a, b)
- field.add(c_2, b, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("a + b = b + a")
- }
-
- field.sub(c_1, a, b)
- field.sub(c_2, b, a)
- field.neg(c_2, c_2)
-
- if !c_1.equal(c_2) {
- t.Fatal("a - b = - ( b - a )")
- }
-
- c_x, _ := new(fe12).rand(rand.Reader)
-
- field.add(c_1, a, b)
- field.add(c_1, c_1, c_x)
- field.add(c_2, a, c_x)
- field.add(c_2, c_2, b)
-
- if !c_1.equal(c_2) {
- t.Fatal("(a + b) + c == (a + c ) + b")
- }
-
- field.sub(c_1, a, b)
- field.sub(c_1, c_1, c_x)
- field.sub(c_2, a, c_x)
- field.sub(c_2, c_2, b)
-
- if !c_1.equal(c_2) {
- t.Fatal("(a - b) - c == (a - c ) -b")
- }
- }
-}
-
-func TestFp12MultiplicationProperties(t *testing.T) {
- field := newFp12(nil)
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe12).rand(rand.Reader)
- b, _ := new(fe12).rand(rand.Reader)
- zero := field.zero()
- one := field.one()
- c_1, c_2 := field.new(), field.new()
- field.mul(c_1, a, zero)
-
- if !c_1.equal(zero) {
- t.Fatal("a * 0 == 0")
- }
-
- field.mul(c_1, a, one)
-
- if !c_1.equal(a) {
- t.Fatal("a * 1 == a")
- }
-
- field.mul(c_1, a, b)
- field.mul(c_2, b, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("a * b == b * a")
- }
-
- c_x, _ := new(fe12).rand(rand.Reader)
-
- field.mul(c_1, a, b)
- field.mul(c_1, c_1, c_x)
- field.mul(c_2, c_x, b)
- field.mul(c_2, c_2, a)
-
- if !c_1.equal(c_2) {
- t.Fatal("(a * b) * c == (a * c) * b")
- }
-
- field.square(a, zero)
-
- if !a.equal(zero) {
- t.Fatal("0^2 == 0")
- }
-
- field.square(a, one)
-
- if !a.equal(one) {
- t.Fatal("1^2 == 1")
- }
-
- _, _ = a.rand(rand.Reader)
- field.square(c_1, a)
- field.mul(c_2, a, a)
-
- if !c_2.equal(c_1) {
- t.Fatal("a^2 == a*a")
- }
- }
-}
-
-func TestFp12MultiplicationPropertiesAssigned(t *testing.T) {
- field := newFp12(nil)
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe12).rand(rand.Reader)
- zero, one := new(fe12).zero(), new(fe12).one()
- field.mulAssign(a, zero)
-
- if !a.equal(zero) {
- t.Fatal("a * 0 == 0")
- }
-
- _, _ = a.rand(rand.Reader)
- a0 := new(fe12).set(a)
- field.mulAssign(a, one)
-
- if !a.equal(a0) {
- t.Fatal("a * 1 == a")
- }
-
- _, _ = a.rand(rand.Reader)
- b, _ := new(fe12).rand(rand.Reader)
-
- a0.set(a)
- field.mulAssign(a, b)
- field.mulAssign(b, a0)
-
- if !a.equal(b) {
- t.Fatal("a * b == b * a")
- }
-
- c, _ := new(fe12).rand(rand.Reader)
-
- a0.set(a)
- field.mulAssign(a, b)
- field.mulAssign(a, c)
- field.mulAssign(a0, c)
- field.mulAssign(a0, b)
-
- if !a.equal(a0) {
- t.Fatal("(a * b) * c == (a * c) * b")
- }
- }
-}
-
-func TestFp12SparseMultiplication(t *testing.T) {
- fp12 := newFp12(nil)
-
- var a, b, u *fe12
- for j := 0; j < fuz; j++ {
- a, _ = new(fe12).rand(rand.Reader)
- b, _ = new(fe12).rand(rand.Reader)
- u, _ = new(fe12).rand(rand.Reader)
-
- b[0][2].zero()
- b[1][0].zero()
- b[1][2].zero()
- fp12.mul(u, a, b)
- fp12.mulBy014Assign(a, &b[0][0], &b[0][1], &b[1][1])
-
- if !a.equal(u) {
- t.Fatal("bad mul by 01")
- }
- }
-}
-
-func TestFp12Exponentiation(t *testing.T) {
- field := newFp12(nil)
-
- for i := 0; i < fuz; i++ {
- a, _ := new(fe12).rand(rand.Reader)
- u := field.new()
- field.exp(u, a, big.NewInt(0))
-
- if !u.equal(field.one()) {
- t.Fatal("a^0 == 1")
- }
-
- field.exp(u, a, big.NewInt(1))
-
- if !u.equal(a) {
- t.Fatal("a^1 == a")
- }
-
- v := field.new()
- field.mul(u, a, a)
- field.mul(u, u, u)
- field.mul(u, u, u)
- field.exp(v, a, big.NewInt(8))
-
- if !u.equal(v) {
- t.Fatal("((a^2)^2)^2 == a^8")
- }
- }
-}
-
-func TestFp12Inversion(t *testing.T) {
- field := newFp12(nil)
- for i := 0; i < fuz; i++ {
- u := field.new()
- zero := field.zero()
- one := field.one()
- field.inverse(u, zero)
-
- if !u.equal(zero) {
- t.Fatal("(0^-1) == 0)")
- }
-
- field.inverse(u, one)
-
- if !u.equal(one) {
- t.Fatal("(1^-1) == 1)")
- }
-
- a, _ := new(fe12).rand(rand.Reader)
- field.inverse(u, a)
- field.mul(u, u, a)
-
- if !u.equal(one) {
- t.Fatal("(r*a) * r*(a^-1) == r)")
- }
- }
-}
-
-func BenchmarkMultiplication(t *testing.B) {
- a, _ := new(fe).rand(rand.Reader)
- b, _ := new(fe).rand(rand.Reader)
- c, _ := new(fe).rand(rand.Reader)
-
- t.ResetTimer()
-
- for i := 0; i < t.N; i++ {
- mul(c, a, b)
- }
-}
-
-func BenchmarkInverse(t *testing.B) {
- a, _ := new(fe).rand(rand.Reader)
- b, _ := new(fe).rand(rand.Reader)
-
- t.ResetTimer()
-
- for i := 0; i < t.N; i++ {
- inverse(a, b)
- }
-}
-
-func padBytes(in []byte, size int) []byte {
- out := make([]byte, size)
-
- if len(in) > size {
- panic("bad input for padding")
- }
-
- copy(out[size-len(in):], in)
-
- return out
-}
diff --git a/crypto/bls12381/g1.go b/crypto/bls12381/g1.go
deleted file mode 100644
index 23d9cf0ec7..0000000000
--- a/crypto/bls12381/g1.go
+++ /dev/null
@@ -1,489 +0,0 @@
-// Copyright 2020 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 bls12381
-
-import (
- "errors"
- "math"
- "math/big"
-)
-
-// PointG1 is type for point in G1.
-// PointG1 is both used for Affine and Jacobian point representation.
-// If z is equal to one the point is considered as in affine form.
-type PointG1 [3]fe
-
-func (p *PointG1) Set(p2 *PointG1) *PointG1 {
- p[0].set(&p2[0])
- p[1].set(&p2[1])
- p[2].set(&p2[2])
-
- return p
-}
-
-// Zero returns G1 point in point at infinity representation
-func (p *PointG1) Zero() *PointG1 {
- p[0].zero()
- p[1].one()
- p[2].zero()
-
- return p
-}
-
-type tempG1 struct {
- t [9]*fe
-}
-
-// G1 is struct for G1 group.
-type G1 struct {
- tempG1
-}
-
-// NewG1 constructs a new G1 instance.
-func NewG1() *G1 {
- t := newTempG1()
- return &G1{t}
-}
-
-func newTempG1() tempG1 {
- t := [9]*fe{}
- for i := 0; i < 9; i++ {
- t[i] = &fe{}
- }
-
- return tempG1{t}
-}
-
-// Q returns group order in big.Int.
-func (g *G1) Q() *big.Int {
- return new(big.Int).Set(q)
-}
-
-func (g *G1) fromBytesUnchecked(in []byte) (*PointG1, error) {
- p0, err := fromBytes(in[:48])
- if err != nil {
- return nil, err
- }
-
- p1, err := fromBytes(in[48:])
- if err != nil {
- return nil, err
- }
-
- p2 := new(fe).one()
-
- return &PointG1{*p0, *p1, *p2}, nil
-}
-
-// FromBytes constructs a new point given uncompressed byte input.
-// FromBytes does not take zcash flags into account.
-// Byte input expected to be larger than 96 bytes.
-// First 96 bytes should be concatenation of x and y values.
-// Point (0, 0) is considered as infinity.
-func (g *G1) FromBytes(in []byte) (*PointG1, error) {
- if len(in) != 96 {
- return nil, errors.New("input string should be equal or larger than 96")
- }
-
- p0, err := fromBytes(in[:48])
- if err != nil {
- return nil, err
- }
-
- p1, err := fromBytes(in[48:])
- if err != nil {
- return nil, err
- }
- // check if given input points to infinity
- if p0.isZero() && p1.isZero() {
- return g.Zero(), nil
- }
-
- p2 := new(fe).one()
-
- p := &PointG1{*p0, *p1, *p2}
- if !g.IsOnCurve(p) {
- return nil, errors.New("point is not on curve")
- }
-
- return p, nil
-}
-
-// DecodePoint given encoded (x, y) coordinates in 128 bytes returns a valid G1 Point.
-func (g *G1) DecodePoint(in []byte) (*PointG1, error) {
- if len(in) != 128 {
- return nil, errors.New("invalid g1 point length")
- }
-
- pointBytes := make([]byte, 96)
- // decode x
- xBytes, err := decodeFieldElement(in[:64])
- if err != nil {
- return nil, err
- }
- // decode y
- yBytes, err := decodeFieldElement(in[64:])
- if err != nil {
- return nil, err
- }
-
- copy(pointBytes[:48], xBytes)
- copy(pointBytes[48:], yBytes)
-
- return g.FromBytes(pointBytes)
-}
-
-// ToBytes serializes a point into bytes in uncompressed form.
-// ToBytes does not take zcash flags into account.
-// ToBytes returns (0, 0) if point is infinity.
-func (g *G1) ToBytes(p *PointG1) []byte {
- out := make([]byte, 96)
- if g.IsZero(p) {
- return out
- }
-
- g.Affine(p)
- copy(out[:48], toBytes(&p[0]))
- copy(out[48:], toBytes(&p[1]))
-
- return out
-}
-
-// EncodePoint encodes a point into 128 bytes.
-func (g *G1) EncodePoint(p *PointG1) []byte {
- outRaw := g.ToBytes(p)
- out := make([]byte, 128)
- // encode x
- copy(out[16:], outRaw[:48])
- // encode y
- copy(out[64+16:], outRaw[48:])
-
- return out
-}
-
-// New creates a new G1 Point which is equal to zero in other words point at infinity.
-func (g *G1) New() *PointG1 {
- return g.Zero()
-}
-
-// Zero returns a new G1 Point which is equal to point at infinity.
-func (g *G1) Zero() *PointG1 {
- return new(PointG1).Zero()
-}
-
-// One returns a new G1 Point which is equal to generator point.
-func (g *G1) One() *PointG1 {
- p := &PointG1{}
- return p.Set(&g1One)
-}
-
-// IsZero returns true if given point is equal to zero.
-func (g *G1) IsZero(p *PointG1) bool {
- return p[2].isZero()
-}
-
-// Equal checks if given two G1 point is equal in their affine form.
-func (g *G1) Equal(p1, p2 *PointG1) bool {
- if g.IsZero(p1) {
- return g.IsZero(p2)
- }
-
- if g.IsZero(p2) {
- return g.IsZero(p1)
- }
-
- t := g.t
- square(t[0], &p1[2])
- square(t[1], &p2[2])
- mul(t[2], t[0], &p2[0])
- mul(t[3], t[1], &p1[0])
- mul(t[0], t[0], &p1[2])
- mul(t[1], t[1], &p2[2])
- mul(t[1], t[1], &p1[1])
- mul(t[0], t[0], &p2[1])
-
- return t[0].equal(t[1]) && t[2].equal(t[3])
-}
-
-// InCorrectSubgroup checks whether given point is in correct subgroup.
-func (g *G1) InCorrectSubgroup(p *PointG1) bool {
- tmp := &PointG1{}
- g.MulScalar(tmp, p, q)
-
- return g.IsZero(tmp)
-}
-
-// IsOnCurve checks a G1 point is on curve.
-func (g *G1) IsOnCurve(p *PointG1) bool {
- if g.IsZero(p) {
- return true
- }
-
- t := g.t
- square(t[0], &p[1])
- square(t[1], &p[0])
- mul(t[1], t[1], &p[0])
- square(t[2], &p[2])
- square(t[3], t[2])
- mul(t[2], t[2], t[3])
- mul(t[2], b, t[2])
- add(t[1], t[1], t[2])
-
- return t[0].equal(t[1])
-}
-
-// IsAffine checks a G1 point whether it is in affine form.
-func (g *G1) IsAffine(p *PointG1) bool {
- return p[2].isOne()
-}
-
-// Affine calculates affine form of given G1 point.
-func (g *G1) Affine(p *PointG1) *PointG1 {
- if g.IsZero(p) {
- return p
- }
-
- if !g.IsAffine(p) {
- t := g.t
- inverse(t[0], &p[2])
- square(t[1], t[0])
- mul(&p[0], &p[0], t[1])
- mul(t[0], t[0], t[1])
- mul(&p[1], &p[1], t[0])
- p[2].one()
- }
-
- return p
-}
-
-// Add adds two G1 points p1, p2 and assigns the result to point at first argument.
-func (g *G1) Add(r, p1, p2 *PointG1) *PointG1 {
- // www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
- if g.IsZero(p1) {
- return r.Set(p2)
- }
-
- if g.IsZero(p2) {
- return r.Set(p1)
- }
-
- t := g.t
- square(t[7], &p1[2])
- mul(t[1], &p2[0], t[7])
- mul(t[2], &p1[2], t[7])
- mul(t[0], &p2[1], t[2])
- square(t[8], &p2[2])
- mul(t[3], &p1[0], t[8])
- mul(t[4], &p2[2], t[8])
- mul(t[2], &p1[1], t[4])
-
- if t[1].equal(t[3]) {
- if t[0].equal(t[2]) {
- return g.Double(r, p1)
- }
-
- return r.Zero()
- }
-
- sub(t[1], t[1], t[3])
- double(t[4], t[1])
- square(t[4], t[4])
- mul(t[5], t[1], t[4])
- sub(t[0], t[0], t[2])
- double(t[0], t[0])
- square(t[6], t[0])
- sub(t[6], t[6], t[5])
- mul(t[3], t[3], t[4])
- double(t[4], t[3])
- sub(&r[0], t[6], t[4])
- sub(t[4], t[3], &r[0])
- mul(t[6], t[2], t[5])
- double(t[6], t[6])
- mul(t[0], t[0], t[4])
- sub(&r[1], t[0], t[6])
- add(t[0], &p1[2], &p2[2])
- square(t[0], t[0])
- sub(t[0], t[0], t[7])
- sub(t[0], t[0], t[8])
- mul(&r[2], t[0], t[1])
-
- return r
-}
-
-// Double doubles a G1 point p and assigns the result to the point at first argument.
-func (g *G1) Double(r, p *PointG1) *PointG1 {
- // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
- if g.IsZero(p) {
- return r.Set(p)
- }
-
- t := g.t
- square(t[0], &p[0])
- square(t[1], &p[1])
- square(t[2], t[1])
- add(t[1], &p[0], t[1])
- square(t[1], t[1])
- sub(t[1], t[1], t[0])
- sub(t[1], t[1], t[2])
- double(t[1], t[1])
- double(t[3], t[0])
- add(t[0], t[3], t[0])
- square(t[4], t[0])
- double(t[3], t[1])
- sub(&r[0], t[4], t[3])
- sub(t[1], t[1], &r[0])
- double(t[2], t[2])
- double(t[2], t[2])
- double(t[2], t[2])
- mul(t[0], t[0], t[1])
- sub(t[1], t[0], t[2])
- mul(t[0], &p[1], &p[2])
- r[1].set(t[1])
- double(&r[2], t[0])
-
- return r
-}
-
-// Neg negates a G1 point p and assigns the result to the point at first argument.
-func (g *G1) Neg(r, p *PointG1) *PointG1 {
- r[0].set(&p[0])
- r[2].set(&p[2])
- neg(&r[1], &p[1])
-
- return r
-}
-
-// Sub subtracts two G1 points p1, p2 and assigns the result to point at first argument.
-func (g *G1) Sub(c, a, b *PointG1) *PointG1 {
- d := &PointG1{}
- g.Neg(d, b)
- g.Add(c, a, d)
-
- return c
-}
-
-// MulScalar multiplies a point by given scalar value in big.Int and assigns the result to point at first argument.
-func (g *G1) MulScalar(c, p *PointG1, e *big.Int) *PointG1 {
- q, n := &PointG1{}, &PointG1{}
- n.Set(p)
-
- l := e.BitLen()
- for i := 0; i < l; i++ {
- if e.Bit(i) == 1 {
- g.Add(q, q, n)
- }
-
- g.Double(n, n)
- }
-
- return c.Set(q)
-}
-
-// ClearCofactor maps given a G1 point to correct subgroup
-func (g *G1) ClearCofactor(p *PointG1) {
- g.MulScalar(p, p, cofactorEFFG1)
-}
-
-// MultiExp calculates multi exponentiation. Given pairs of G1 point and scalar values
-// (P_0, e_0), (P_1, e_1), ... (P_n, e_n) calculates r = e_0 * P_0 + e_1 * P_1 + ... + e_n * P_n
-// Length of points and scalars are expected to be equal, otherwise an error is returned.
-// Result is assigned to point at first argument.
-func (g *G1) MultiExp(r *PointG1, points []*PointG1, powers []*big.Int) (*PointG1, error) {
- if len(points) != len(powers) {
- return nil, errors.New("point and scalar vectors should be in same length")
- }
-
- var c uint32 = 3
- if len(powers) >= 32 {
- c = uint32(math.Ceil(math.Log10(float64(len(powers)))))
- }
-
- bucketSize, numBits := (1<= 0; i-- {
- g.Add(sum, sum, bucket[i])
- g.Add(acc, acc, sum)
- }
-
- windows[j] = g.New()
- windows[j].Set(acc)
-
- j++
- cur += c
- }
- acc.Zero()
-
- for i := len(windows) - 1; i >= 0; i-- {
- for j := uint32(0); j < c; j++ {
- g.Double(acc, acc)
- }
- g.Add(acc, acc, windows[i])
- }
-
- return r.Set(acc), nil
-}
-
-// MapToCurve given a byte slice returns a valid G1 point.
-// This mapping function implements the Simplified Shallue-van de Woestijne-Ulas method.
-// https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06
-// Input byte slice should be a valid field element, otherwise an error is returned.
-func (g *G1) MapToCurve(in []byte) (*PointG1, error) {
- u, err := fromBytes(in)
- if err != nil {
- return nil, err
- }
-
- x, y := swuMapG1(u)
- isogenyMapG1(x, y)
-
- one := new(fe).one()
- p := &PointG1{*x, *y, *one}
- g.ClearCofactor(p)
-
- return g.Affine(p), nil
-}
diff --git a/crypto/bls12381/g1_test.go b/crypto/bls12381/g1_test.go
deleted file mode 100644
index 5b1f956a1a..0000000000
--- a/crypto/bls12381/g1_test.go
+++ /dev/null
@@ -1,343 +0,0 @@
-package bls12381
-
-import (
- "bytes"
- "crypto/rand"
- "math/big"
- "testing"
-
- "github.com/ethereum/go-ethereum/common"
-)
-
-func (g *G1) one() *PointG1 {
- one, _ := g.fromBytesUnchecked(
- common.FromHex("" +
- "17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb" +
- "08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1",
- ),
- )
-
- return one
-}
-
-func (g *G1) rand() *PointG1 {
- k, err := rand.Int(rand.Reader, q)
- if err != nil {
- panic(err)
- }
-
- return g.MulScalar(&PointG1{}, g.one(), k)
-}
-
-func TestG1Serialization(t *testing.T) {
- g1 := NewG1()
- for i := 0; i < fuz; i++ {
- a := g1.rand()
- buf := g1.ToBytes(a)
-
- b, err := g1.FromBytes(buf)
- if err != nil {
- t.Fatal(err)
- }
-
- if !g1.Equal(a, b) {
- t.Fatal("bad serialization from/to")
- }
- }
-
- for i := 0; i < fuz; i++ {
- a := g1.rand()
- encoded := g1.EncodePoint(a)
-
- b, err := g1.DecodePoint(encoded)
- if err != nil {
- t.Fatal(err)
- }
-
- if !g1.Equal(a, b) {
- t.Fatal("bad serialization encode/decode")
- }
- }
-}
-
-func TestG1IsOnCurve(t *testing.T) {
- g := NewG1()
- zero := g.Zero()
-
- if !g.IsOnCurve(zero) {
- t.Fatal("zero must be on curve")
- }
-
- one := new(fe).one()
-
- p := &PointG1{*one, *one, *one}
- if g.IsOnCurve(p) {
- t.Fatal("(1, 1) is not on curve")
- }
-}
-
-func TestG1AdditiveProperties(t *testing.T) {
- g := NewG1()
- t0, t1 := g.New(), g.New()
- zero := g.Zero()
-
- for i := 0; i < fuz; i++ {
- a, b := g.rand(), g.rand()
- g.Add(t0, a, zero)
-
- if !g.Equal(t0, a) {
- t.Fatal("a + 0 == a")
- }
-
- g.Add(t0, zero, zero)
-
- if !g.Equal(t0, zero) {
- t.Fatal("0 + 0 == 0")
- }
-
- g.Sub(t0, a, zero)
-
- if !g.Equal(t0, a) {
- t.Fatal("a - 0 == a")
- }
-
- g.Sub(t0, zero, zero)
-
- if !g.Equal(t0, zero) {
- t.Fatal("0 - 0 == 0")
- }
-
- g.Neg(t0, zero)
-
- if !g.Equal(t0, zero) {
- t.Fatal("- 0 == 0")
- }
-
- g.Sub(t0, zero, a)
- g.Neg(t0, t0)
-
- if !g.Equal(t0, a) {
- t.Fatal(" - (0 - a) == a")
- }
-
- g.Double(t0, zero)
-
- if !g.Equal(t0, zero) {
- t.Fatal("2 * 0 == 0")
- }
-
- g.Double(t0, a)
- g.Sub(t0, t0, a)
-
- if !g.Equal(t0, a) || !g.IsOnCurve(t0) {
- t.Fatal(" (2 * a) - a == a")
- }
-
- g.Add(t0, a, b)
- g.Add(t1, b, a)
-
- if !g.Equal(t0, t1) {
- t.Fatal("a + b == b + a")
- }
-
- g.Sub(t0, a, b)
- g.Sub(t1, b, a)
- g.Neg(t1, t1)
-
- if !g.Equal(t0, t1) {
- t.Fatal("a - b == - ( b - a )")
- }
-
- c := g.rand()
- g.Add(t0, a, b)
- g.Add(t0, t0, c)
- g.Add(t1, a, c)
- g.Add(t1, t1, b)
-
- if !g.Equal(t0, t1) {
- t.Fatal("(a + b) + c == (a + c ) + b")
- }
-
- g.Sub(t0, a, b)
- g.Sub(t0, t0, c)
- g.Sub(t1, a, c)
- g.Sub(t1, t1, b)
-
- if !g.Equal(t0, t1) {
- t.Fatal("(a - b) - c == (a - c) -b")
- }
- }
-}
-
-func TestG1MultiplicativeProperties(t *testing.T) {
- g := NewG1()
- t0, t1 := g.New(), g.New()
- zero := g.Zero()
-
- for i := 0; i < fuz; i++ {
- a := g.rand()
- s1, s2, s3 := randScalar(q), randScalar(q), randScalar(q)
- sone := big.NewInt(1)
-
- g.MulScalar(t0, zero, s1)
-
- if !g.Equal(t0, zero) {
- t.Fatal(" 0 ^ s == 0")
- }
-
- g.MulScalar(t0, a, sone)
-
- if !g.Equal(t0, a) {
- t.Fatal(" a ^ 1 == a")
- }
-
- g.MulScalar(t0, zero, s1)
-
- if !g.Equal(t0, zero) {
- t.Fatal(" 0 ^ s == a")
- }
-
- g.MulScalar(t0, a, s1)
- g.MulScalar(t0, t0, s2)
- s3.Mul(s1, s2)
- g.MulScalar(t1, a, s3)
-
- if !g.Equal(t0, t1) {
- t.Errorf(" (a ^ s1) ^ s2 == a ^ (s1 * s2)")
- }
-
- g.MulScalar(t0, a, s1)
- g.MulScalar(t1, a, s2)
- g.Add(t0, t0, t1)
- s3.Add(s1, s2)
- g.MulScalar(t1, a, s3)
-
- if !g.Equal(t0, t1) {
- t.Errorf(" (a ^ s1) + (a ^ s2) == a ^ (s1 + s2)")
- }
- }
-}
-
-func TestG1MultiExpExpected(t *testing.T) {
- g := NewG1()
- one := g.one()
-
- var scalars [2]*big.Int
-
- var bases [2]*PointG1
-
- scalars[0] = big.NewInt(2)
- scalars[1] = big.NewInt(3)
- bases[0], bases[1] = new(PointG1).Set(one), new(PointG1).Set(one)
- expected, result := g.New(), g.New()
- g.MulScalar(expected, one, big.NewInt(5))
- _, _ = g.MultiExp(result, bases[:], scalars[:])
-
- if !g.Equal(expected, result) {
- t.Fatal("bad multi-exponentiation")
- }
-}
-
-func TestG1MultiExpBatch(t *testing.T) {
- g := NewG1()
- one := g.one()
- n := 1000
- bases := make([]*PointG1, n)
- scalars := make([]*big.Int, n)
- // scalars: [s0,s1 ... s(n-1)]
- // bases: [P0,P1,..P(n-1)] = [s(n-1)*G, s(n-2)*G ... s0*G]
- for i, j := 0, n-1; i < n; i, j = i+1, j-1 {
- scalars[j], _ = rand.Int(rand.Reader, big.NewInt(100000))
- bases[i] = g.New()
- g.MulScalar(bases[i], one, scalars[j])
- }
- // expected: s(n-1)*P0 + s(n-2)*P1 + s0*P(n-1)
- expected, tmp := g.New(), g.New()
- for i := 0; i < n; i++ {
- g.MulScalar(tmp, bases[i], scalars[i])
- g.Add(expected, expected, tmp)
- }
-
- result := g.New()
- _, _ = g.MultiExp(result, bases, scalars)
-
- if !g.Equal(expected, result) {
- t.Fatal("bad multi-exponentiation")
- }
-}
-
-func TestG1MapToCurve(t *testing.T) {
- for i, v := range []struct {
- u []byte
- expected []byte
- }{
- {
- u: make([]byte, 48),
- expected: common.FromHex("11a9a0372b8f332d5c30de9ad14e50372a73fa4c45d5f2fa5097f2d6fb93bcac592f2e1711ac43db0519870c7d0ea415" + "092c0f994164a0719f51c24ba3788de240ff926b55f58c445116e8bc6a47cd63392fd4e8e22bdf9feaa96ee773222133"),
- },
- {
- u: common.FromHex("07fdf49ea58e96015d61f6b5c9d1c8f277146a533ae7fbca2a8ef4c41055cd961fbc6e26979b5554e4b4f22330c0e16d"),
- expected: common.FromHex("1223effdbb2d38152495a864d78eee14cb0992d89a241707abb03819a91a6d2fd65854ab9a69e9aacb0cbebfd490732c" + "0f925d61e0b235ecd945cbf0309291878df0d06e5d80d6b84aa4ff3e00633b26f9a7cb3523ef737d90e6d71e8b98b2d5"),
- },
- {
- u: common.FromHex("1275ab3adbf824a169ed4b1fd669b49cf406d822f7fe90d6b2f8c601b5348436f89761bb1ad89a6fb1137cd91810e5d2"),
- expected: common.FromHex("179d3fd0b4fb1da43aad06cea1fb3f828806ddb1b1fa9424b1e3944dfdbab6e763c42636404017da03099af0dcca0fd6" + "0d037cb1c6d495c0f5f22b061d23f1be3d7fe64d3c6820cfcd99b6b36fa69f7b4c1f4addba2ae7aa46fb25901ab483e4"),
- },
- {
- u: common.FromHex("0e93d11d30de6d84b8578827856f5c05feef36083eef0b7b263e35ecb9b56e86299614a042e57d467fa20948e8564909"),
- expected: common.FromHex("15aa66c77eded1209db694e8b1ba49daf8b686733afaa7b68c683d0b01788dfb0617a2e2d04c0856db4981921d3004af" + "0952bb2f61739dd1d201dd0a79d74cda3285403d47655ee886afe860593a8a4e51c5b77a22d2133e3a4280eaaaa8b788"),
- },
- {
- u: common.FromHex("015a41481155d17074d20be6d8ec4d46632a51521cd9c916e265bd9b47343b3689979b50708c8546cbc2916b86cb1a3a"),
- expected: common.FromHex("06328ce5106e837935e8da84bd9af473422e62492930aa5f460369baad9545defa468d9399854c23a75495d2a80487ee" + "094bfdfe3e552447433b5a00967498a3f1314b86ce7a7164c8a8f4131f99333b30a574607e301d5f774172c627fd0bca"),
- },
- } {
- g := NewG1()
-
- p0, err := g.MapToCurve(v.u)
- if err != nil {
- t.Fatal("map to curve fails", i, err)
- }
-
- if !bytes.Equal(g.ToBytes(p0), v.expected) {
- t.Fatal("map to curve fails", i)
- }
- }
-}
-
-func BenchmarkG1Add(t *testing.B) {
- g1 := NewG1()
- a, b, c := g1.rand(), g1.rand(), PointG1{}
-
- t.ResetTimer()
-
- for i := 0; i < t.N; i++ {
- g1.Add(&c, a, b)
- }
-}
-
-func BenchmarkG1Mul(t *testing.B) {
- worstCaseScalar, _ := new(big.Int).SetString("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)
- g1 := NewG1()
- a, e, c := g1.rand(), worstCaseScalar, PointG1{}
-
- t.ResetTimer()
-
- for i := 0; i < t.N; i++ {
- g1.MulScalar(&c, a, e)
- }
-}
-
-func BenchmarkG1MapToCurve(t *testing.B) {
- a := make([]byte, 48)
- g1 := NewG1()
-
- t.ResetTimer()
-
- for i := 0; i < t.N; i++ {
- _, err := g1.MapToCurve(a)
- if err != nil {
- t.Fatal(err)
- }
- }
-}
diff --git a/crypto/bls12381/g2.go b/crypto/bls12381/g2.go
deleted file mode 100644
index a840326664..0000000000
--- a/crypto/bls12381/g2.go
+++ /dev/null
@@ -1,517 +0,0 @@
-// Copyright 2020 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 bls12381
-
-import (
- "errors"
- "math"
- "math/big"
-)
-
-// PointG2 is type for point in G2.
-// PointG2 is both used for Affine and Jacobian point representation.
-// If z is equal to one the point is considered as in affine form.
-type PointG2 [3]fe2
-
-// Set copies values of one point to another.
-func (p *PointG2) Set(p2 *PointG2) *PointG2 {
- p[0].set(&p2[0])
- p[1].set(&p2[1])
- p[2].set(&p2[2])
-
- return p
-}
-
-// Zero returns G2 point in point at infinity representation
-func (p *PointG2) Zero() *PointG2 {
- p[0].zero()
- p[1].one()
- p[2].zero()
-
- return p
-}
-
-type tempG2 struct {
- t [9]*fe2
-}
-
-// G2 is struct for G2 group.
-type G2 struct {
- f *fp2
- tempG2
-}
-
-// NewG2 constructs a new G2 instance.
-func NewG2() *G2 {
- return newG2(nil)
-}
-
-func newG2(f *fp2) *G2 {
- if f == nil {
- f = newFp2()
- }
-
- t := newTempG2()
-
- return &G2{f, t}
-}
-
-func newTempG2() tempG2 {
- t := [9]*fe2{}
- for i := 0; i < 9; i++ {
- t[i] = &fe2{}
- }
-
- return tempG2{t}
-}
-
-// Q returns group order in big.Int.
-func (g *G2) Q() *big.Int {
- return new(big.Int).Set(q)
-}
-
-func (g *G2) fromBytesUnchecked(in []byte) (*PointG2, error) {
- p0, err := g.f.fromBytes(in[:96])
- if err != nil {
- return nil, err
- }
-
- p1, err := g.f.fromBytes(in[96:])
- if err != nil {
- return nil, err
- }
-
- p2 := new(fe2).one()
-
- return &PointG2{*p0, *p1, *p2}, nil
-}
-
-// FromBytes constructs a new point given uncompressed byte input.
-// FromBytes does not take zcash flags into account.
-// Byte input expected to be larger than 96 bytes.
-// First 192 bytes should be concatenation of x and y values
-// Point (0, 0) is considered as infinity.
-func (g *G2) FromBytes(in []byte) (*PointG2, error) {
- if len(in) != 192 {
- return nil, errors.New("input string should be equal or larger than 192")
- }
-
- p0, err := g.f.fromBytes(in[:96])
- if err != nil {
- return nil, err
- }
-
- p1, err := g.f.fromBytes(in[96:])
- if err != nil {
- return nil, err
- }
- // check if given input points to infinity
- if p0.isZero() && p1.isZero() {
- return g.Zero(), nil
- }
-
- p2 := new(fe2).one()
-
- p := &PointG2{*p0, *p1, *p2}
- if !g.IsOnCurve(p) {
- return nil, errors.New("point is not on curve")
- }
-
- return p, nil
-}
-
-// DecodePoint given encoded (x, y) coordinates in 256 bytes returns a valid G2 Point.
-func (g *G2) DecodePoint(in []byte) (*PointG2, error) {
- if len(in) != 256 {
- return nil, errors.New("invalid g2 point length")
- }
-
- pointBytes := make([]byte, 192)
-
- x0Bytes, err := decodeFieldElement(in[:64])
- if err != nil {
- return nil, err
- }
-
- x1Bytes, err := decodeFieldElement(in[64:128])
- if err != nil {
- return nil, err
- }
-
- y0Bytes, err := decodeFieldElement(in[128:192])
- if err != nil {
- return nil, err
- }
-
- y1Bytes, err := decodeFieldElement(in[192:])
- if err != nil {
- return nil, err
- }
-
- copy(pointBytes[:48], x1Bytes)
- copy(pointBytes[48:96], x0Bytes)
- copy(pointBytes[96:144], y1Bytes)
- copy(pointBytes[144:192], y0Bytes)
-
- return g.FromBytes(pointBytes)
-}
-
-// ToBytes serializes a point into bytes in uncompressed form,
-// does not take zcash flags into account,
-// returns (0, 0) if point is infinity.
-func (g *G2) ToBytes(p *PointG2) []byte {
- out := make([]byte, 192)
- if g.IsZero(p) {
- return out
- }
-
- g.Affine(p)
- copy(out[:96], g.f.toBytes(&p[0]))
- copy(out[96:], g.f.toBytes(&p[1]))
-
- return out
-}
-
-// EncodePoint encodes a point into 256 bytes.
-func (g *G2) EncodePoint(p *PointG2) []byte {
- // outRaw is 96 bytes
- outRaw := g.ToBytes(p)
- out := make([]byte, 256)
- // encode x
- copy(out[16:16+48], outRaw[48:96])
- copy(out[80:80+48], outRaw[:48])
- // encode y
- copy(out[144:144+48], outRaw[144:])
- copy(out[208:208+48], outRaw[96:144])
-
- return out
-}
-
-// New creates a new G2 Point which is equal to zero in other words point at infinity.
-func (g *G2) New() *PointG2 {
- return new(PointG2).Zero()
-}
-
-// Zero returns a new G2 Point which is equal to point at infinity.
-func (g *G2) Zero() *PointG2 {
- return new(PointG2).Zero()
-}
-
-// One returns a new G2 Point which is equal to generator point.
-func (g *G2) One() *PointG2 {
- p := &PointG2{}
- return p.Set(&g2One)
-}
-
-// IsZero returns true if given point is equal to zero.
-func (g *G2) IsZero(p *PointG2) bool {
- return p[2].isZero()
-}
-
-// Equal checks if given two G2 point is equal in their affine form.
-func (g *G2) Equal(p1, p2 *PointG2) bool {
- if g.IsZero(p1) {
- return g.IsZero(p2)
- }
-
- if g.IsZero(p2) {
- return g.IsZero(p1)
- }
-
- t := g.t
- g.f.square(t[0], &p1[2])
- g.f.square(t[1], &p2[2])
- g.f.mul(t[2], t[0], &p2[0])
- g.f.mul(t[3], t[1], &p1[0])
- g.f.mul(t[0], t[0], &p1[2])
- g.f.mul(t[1], t[1], &p2[2])
- g.f.mul(t[1], t[1], &p1[1])
- g.f.mul(t[0], t[0], &p2[1])
-
- return t[0].equal(t[1]) && t[2].equal(t[3])
-}
-
-// InCorrectSubgroup checks whether given point is in correct subgroup.
-func (g *G2) InCorrectSubgroup(p *PointG2) bool {
- tmp := &PointG2{}
- g.MulScalar(tmp, p, q)
-
- return g.IsZero(tmp)
-}
-
-// IsOnCurve checks a G2 point is on curve.
-func (g *G2) IsOnCurve(p *PointG2) bool {
- if g.IsZero(p) {
- return true
- }
-
- t := g.t
- g.f.square(t[0], &p[1])
- g.f.square(t[1], &p[0])
- g.f.mul(t[1], t[1], &p[0])
- g.f.square(t[2], &p[2])
- g.f.square(t[3], t[2])
- g.f.mul(t[2], t[2], t[3])
- g.f.mul(t[2], b2, t[2])
- g.f.add(t[1], t[1], t[2])
-
- return t[0].equal(t[1])
-}
-
-// IsAffine checks a G2 point whether it is in affine form.
-func (g *G2) IsAffine(p *PointG2) bool {
- return p[2].isOne()
-}
-
-// Affine calculates affine form of given G2 point.
-func (g *G2) Affine(p *PointG2) *PointG2 {
- if g.IsZero(p) {
- return p
- }
-
- if !g.IsAffine(p) {
- t := g.t
- g.f.inverse(t[0], &p[2])
- g.f.square(t[1], t[0])
- g.f.mul(&p[0], &p[0], t[1])
- g.f.mul(t[0], t[0], t[1])
- g.f.mul(&p[1], &p[1], t[0])
- p[2].one()
- }
-
- return p
-}
-
-// Add adds two G2 points p1, p2 and assigns the result to point at first argument.
-func (g *G2) Add(r, p1, p2 *PointG2) *PointG2 {
- // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
- if g.IsZero(p1) {
- return r.Set(p2)
- }
-
- if g.IsZero(p2) {
- return r.Set(p1)
- }
-
- t := g.t
- g.f.square(t[7], &p1[2])
- g.f.mul(t[1], &p2[0], t[7])
- g.f.mul(t[2], &p1[2], t[7])
- g.f.mul(t[0], &p2[1], t[2])
- g.f.square(t[8], &p2[2])
- g.f.mul(t[3], &p1[0], t[8])
- g.f.mul(t[4], &p2[2], t[8])
- g.f.mul(t[2], &p1[1], t[4])
-
- if t[1].equal(t[3]) {
- if t[0].equal(t[2]) {
- return g.Double(r, p1)
- }
-
- return r.Zero()
- }
-
- g.f.sub(t[1], t[1], t[3])
- g.f.double(t[4], t[1])
- g.f.square(t[4], t[4])
- g.f.mul(t[5], t[1], t[4])
- g.f.sub(t[0], t[0], t[2])
- g.f.double(t[0], t[0])
- g.f.square(t[6], t[0])
- g.f.sub(t[6], t[6], t[5])
- g.f.mul(t[3], t[3], t[4])
- g.f.double(t[4], t[3])
- g.f.sub(&r[0], t[6], t[4])
- g.f.sub(t[4], t[3], &r[0])
- g.f.mul(t[6], t[2], t[5])
- g.f.double(t[6], t[6])
- g.f.mul(t[0], t[0], t[4])
- g.f.sub(&r[1], t[0], t[6])
- g.f.add(t[0], &p1[2], &p2[2])
- g.f.square(t[0], t[0])
- g.f.sub(t[0], t[0], t[7])
- g.f.sub(t[0], t[0], t[8])
- g.f.mul(&r[2], t[0], t[1])
-
- return r
-}
-
-// Double doubles a G2 point p and assigns the result to the point at first argument.
-func (g *G2) Double(r, p *PointG2) *PointG2 {
- // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
- if g.IsZero(p) {
- return r.Set(p)
- }
-
- t := g.t
- g.f.square(t[0], &p[0])
- g.f.square(t[1], &p[1])
- g.f.square(t[2], t[1])
- g.f.add(t[1], &p[0], t[1])
- g.f.square(t[1], t[1])
- g.f.sub(t[1], t[1], t[0])
- g.f.sub(t[1], t[1], t[2])
- g.f.double(t[1], t[1])
- g.f.double(t[3], t[0])
- g.f.add(t[0], t[3], t[0])
- g.f.square(t[4], t[0])
- g.f.double(t[3], t[1])
- g.f.sub(&r[0], t[4], t[3])
- g.f.sub(t[1], t[1], &r[0])
- g.f.double(t[2], t[2])
- g.f.double(t[2], t[2])
- g.f.double(t[2], t[2])
- g.f.mul(t[0], t[0], t[1])
- g.f.sub(t[1], t[0], t[2])
- g.f.mul(t[0], &p[1], &p[2])
- r[1].set(t[1])
- g.f.double(&r[2], t[0])
-
- return r
-}
-
-// Neg negates a G2 point p and assigns the result to the point at first argument.
-func (g *G2) Neg(r, p *PointG2) *PointG2 {
- r[0].set(&p[0])
- g.f.neg(&r[1], &p[1])
- r[2].set(&p[2])
-
- return r
-}
-
-// Sub subtracts two G2 points p1, p2 and assigns the result to point at first argument.
-func (g *G2) Sub(c, a, b *PointG2) *PointG2 {
- d := &PointG2{}
- g.Neg(d, b)
- g.Add(c, a, d)
-
- return c
-}
-
-// MulScalar multiplies a point by given scalar value in big.Int and assigns the result to point at first argument.
-func (g *G2) MulScalar(c, p *PointG2, e *big.Int) *PointG2 {
- q, n := &PointG2{}, &PointG2{}
- n.Set(p)
-
- l := e.BitLen()
- for i := 0; i < l; i++ {
- if e.Bit(i) == 1 {
- g.Add(q, q, n)
- }
-
- g.Double(n, n)
- }
-
- return c.Set(q)
-}
-
-// ClearCofactor maps given a G2 point to correct subgroup
-func (g *G2) ClearCofactor(p *PointG2) {
- g.MulScalar(p, p, cofactorEFFG2)
-}
-
-// MultiExp calculates multi exponentiation. Given pairs of G2 point and scalar values
-// (P_0, e_0), (P_1, e_1), ... (P_n, e_n) calculates r = e_0 * P_0 + e_1 * P_1 + ... + e_n * P_n
-// Length of points and scalars are expected to be equal, otherwise an error is returned.
-// Result is assigned to point at first argument.
-func (g *G2) MultiExp(r *PointG2, points []*PointG2, powers []*big.Int) (*PointG2, error) {
- if len(points) != len(powers) {
- return nil, errors.New("point and scalar vectors should be in same length")
- }
-
- var c uint32 = 3
- if len(powers) >= 32 {
- c = uint32(math.Ceil(math.Log10(float64(len(powers)))))
- }
-
- bucketSize, numBits := (1<= 0; i-- {
- g.Add(sum, sum, bucket[i])
- g.Add(acc, acc, sum)
- }
-
- windows[j] = g.New()
- windows[j].Set(acc)
-
- j++
- cur += c
- }
- acc.Zero()
-
- for i := len(windows) - 1; i >= 0; i-- {
- for j := uint32(0); j < c; j++ {
- g.Double(acc, acc)
- }
- g.Add(acc, acc, windows[i])
- }
-
- return r.Set(acc), nil
-}
-
-// MapToCurve given a byte slice returns a valid G2 point.
-// This mapping function implements the Simplified Shallue-van de Woestijne-Ulas method.
-// https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-05#section-6.6.2
-// Input byte slice should be a valid field element, otherwise an error is returned.
-func (g *G2) MapToCurve(in []byte) (*PointG2, error) {
- fp2 := g.f
-
- u, err := fp2.fromBytes(in)
- if err != nil {
- return nil, err
- }
-
- x, y := swuMapG2(fp2, u)
- isogenyMapG2(fp2, x, y)
-
- z := new(fe2).one()
- q := &PointG2{*x, *y, *z}
- g.ClearCofactor(q)
-
- return g.Affine(q), nil
-}
diff --git a/crypto/bls12381/g2_test.go b/crypto/bls12381/g2_test.go
deleted file mode 100644
index 1caf7c0146..0000000000
--- a/crypto/bls12381/g2_test.go
+++ /dev/null
@@ -1,346 +0,0 @@
-package bls12381
-
-import (
- "bytes"
- "crypto/rand"
- "math/big"
- "testing"
-
- "github.com/ethereum/go-ethereum/common"
-)
-
-func (g *G2) one() *PointG2 {
- one, _ := g.fromBytesUnchecked(
- common.FromHex("" +
- "13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e" +
- "024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8" +
- "0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be" +
- "0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801",
- ),
- )
-
- return one
-}
-
-func (g *G2) rand() *PointG2 {
- k, err := rand.Int(rand.Reader, q)
- if err != nil {
- panic(err)
- }
-
- return g.MulScalar(&PointG2{}, g.one(), k)
-}
-
-func TestG2Serialization(t *testing.T) {
- g2 := NewG2()
- for i := 0; i < fuz; i++ {
- a := g2.rand()
- buf := g2.ToBytes(a)
-
- b, err := g2.FromBytes(buf)
- if err != nil {
- t.Fatal(err)
- }
-
- if !g2.Equal(a, b) {
- t.Fatal("bad serialization from/to")
- }
- }
-
- for i := 0; i < fuz; i++ {
- a := g2.rand()
- encoded := g2.EncodePoint(a)
-
- b, err := g2.DecodePoint(encoded)
- if err != nil {
- t.Fatal(err)
- }
-
- if !g2.Equal(a, b) {
- t.Fatal("bad serialization encode/decode")
- }
- }
-}
-
-func TestG2IsOnCurve(t *testing.T) {
- g := NewG2()
- zero := g.Zero()
-
- if !g.IsOnCurve(zero) {
- t.Fatal("zero must be on curve")
- }
-
- one := new(fe2).one()
-
- p := &PointG2{*one, *one, *one}
- if g.IsOnCurve(p) {
- t.Fatal("(1, 1) is not on curve")
- }
-}
-
-func TestG2AdditiveProperties(t *testing.T) {
- g := NewG2()
- t0, t1 := g.New(), g.New()
- zero := g.Zero()
-
- for i := 0; i < fuz; i++ {
- a, b := g.rand(), g.rand()
- _, _, _ = b, t1, zero
- g.Add(t0, a, zero)
-
- if !g.Equal(t0, a) {
- t.Fatal("a + 0 == a")
- }
-
- g.Add(t0, zero, zero)
-
- if !g.Equal(t0, zero) {
- t.Fatal("0 + 0 == 0")
- }
-
- g.Sub(t0, a, zero)
-
- if !g.Equal(t0, a) {
- t.Fatal("a - 0 == a")
- }
-
- g.Sub(t0, zero, zero)
-
- if !g.Equal(t0, zero) {
- t.Fatal("0 - 0 == 0")
- }
-
- g.Neg(t0, zero)
-
- if !g.Equal(t0, zero) {
- t.Fatal("- 0 == 0")
- }
-
- g.Sub(t0, zero, a)
- g.Neg(t0, t0)
-
- if !g.Equal(t0, a) {
- t.Fatal(" - (0 - a) == a")
- }
-
- g.Double(t0, zero)
-
- if !g.Equal(t0, zero) {
- t.Fatal("2 * 0 == 0")
- }
-
- g.Double(t0, a)
- g.Sub(t0, t0, a)
-
- if !g.Equal(t0, a) || !g.IsOnCurve(t0) {
- t.Fatal(" (2 * a) - a == a")
- }
-
- g.Add(t0, a, b)
- g.Add(t1, b, a)
-
- if !g.Equal(t0, t1) {
- t.Fatal("a + b == b + a")
- }
-
- g.Sub(t0, a, b)
- g.Sub(t1, b, a)
- g.Neg(t1, t1)
-
- if !g.Equal(t0, t1) {
- t.Fatal("a - b == - ( b - a )")
- }
-
- c := g.rand()
- g.Add(t0, a, b)
- g.Add(t0, t0, c)
- g.Add(t1, a, c)
- g.Add(t1, t1, b)
-
- if !g.Equal(t0, t1) {
- t.Fatal("(a + b) + c == (a + c ) + b")
- }
-
- g.Sub(t0, a, b)
- g.Sub(t0, t0, c)
- g.Sub(t1, a, c)
- g.Sub(t1, t1, b)
-
- if !g.Equal(t0, t1) {
- t.Fatal("(a - b) - c == (a - c) -b")
- }
- }
-}
-
-func TestG2MultiplicativeProperties(t *testing.T) {
- g := NewG2()
- t0, t1 := g.New(), g.New()
- zero := g.Zero()
-
- for i := 0; i < fuz; i++ {
- a := g.rand()
- s1, s2, s3 := randScalar(q), randScalar(q), randScalar(q)
- sone := big.NewInt(1)
-
- g.MulScalar(t0, zero, s1)
-
- if !g.Equal(t0, zero) {
- t.Fatal(" 0 ^ s == 0")
- }
-
- g.MulScalar(t0, a, sone)
-
- if !g.Equal(t0, a) {
- t.Fatal(" a ^ 1 == a")
- }
-
- g.MulScalar(t0, zero, s1)
-
- if !g.Equal(t0, zero) {
- t.Fatal(" 0 ^ s == a")
- }
-
- g.MulScalar(t0, a, s1)
- g.MulScalar(t0, t0, s2)
- s3.Mul(s1, s2)
- g.MulScalar(t1, a, s3)
-
- if !g.Equal(t0, t1) {
- t.Errorf(" (a ^ s1) ^ s2 == a ^ (s1 * s2)")
- }
-
- g.MulScalar(t0, a, s1)
- g.MulScalar(t1, a, s2)
- g.Add(t0, t0, t1)
- s3.Add(s1, s2)
- g.MulScalar(t1, a, s3)
-
- if !g.Equal(t0, t1) {
- t.Errorf(" (a ^ s1) + (a ^ s2) == a ^ (s1 + s2)")
- }
- }
-}
-
-func TestG2MultiExpExpected(t *testing.T) {
- g := NewG2()
- one := g.one()
-
- var scalars [2]*big.Int
-
- var bases [2]*PointG2
-
- scalars[0] = big.NewInt(2)
- scalars[1] = big.NewInt(3)
- bases[0], bases[1] = new(PointG2).Set(one), new(PointG2).Set(one)
- expected, result := g.New(), g.New()
- g.MulScalar(expected, one, big.NewInt(5))
- _, _ = g.MultiExp(result, bases[:], scalars[:])
-
- if !g.Equal(expected, result) {
- t.Fatal("bad multi-exponentiation")
- }
-}
-
-func TestG2MultiExpBatch(t *testing.T) {
- g := NewG2()
- one := g.one()
- n := 1000
- bases := make([]*PointG2, n)
- scalars := make([]*big.Int, n)
- // scalars: [s0,s1 ... s(n-1)]
- // bases: [P0,P1,..P(n-1)] = [s(n-1)*G, s(n-2)*G ... s0*G]
- for i, j := 0, n-1; i < n; i, j = i+1, j-1 {
- scalars[j], _ = rand.Int(rand.Reader, big.NewInt(100000))
- bases[i] = g.New()
- g.MulScalar(bases[i], one, scalars[j])
- }
- // expected: s(n-1)*P0 + s(n-2)*P1 + s0*P(n-1)
- expected, tmp := g.New(), g.New()
- for i := 0; i < n; i++ {
- g.MulScalar(tmp, bases[i], scalars[i])
- g.Add(expected, expected, tmp)
- }
-
- result := g.New()
- _, _ = g.MultiExp(result, bases, scalars)
-
- if !g.Equal(expected, result) {
- t.Fatal("bad multi-exponentiation")
- }
-}
-
-func TestG2MapToCurve(t *testing.T) {
- for i, v := range []struct {
- u []byte
- expected []byte
- }{
- {
- u: make([]byte, 96),
- expected: common.FromHex("0a67d12118b5a35bb02d2e86b3ebfa7e23410db93de39fb06d7025fa95e96ffa428a7a27c3ae4dd4b40bd251ac658892" + "018320896ec9eef9d5e619848dc29ce266f413d02dd31d9b9d44ec0c79cd61f18b075ddba6d7bd20b7ff27a4b324bfce" + "04c69777a43f0bda07679d5805e63f18cf4e0e7c6112ac7f70266d199b4f76ae27c6269a3ceebdae30806e9a76aadf5c" + "0260e03644d1a2c321256b3246bad2b895cad13890cbe6f85df55106a0d334604fb143c7a042d878006271865bc35941"),
- },
- {
- u: common.FromHex("025fbc07711ba267b7e70c82caa70a16fbb1d470ae24ceef307f5e2000751677820b7013ad4e25492dcf30052d3e5eca" + "0e775d7827adf385b83e20e4445bd3fab21d7b4498426daf3c1d608b9d41e9edb5eda0df022e753b8bb4bc3bb7db4914"),
- expected: common.FromHex("0d4333b77becbf9f9dfa3ca928002233d1ecc854b1447e5a71f751c9042d000f42db91c1d6649a5e0ad22bd7bf7398b8" + "027e4bfada0b47f9f07e04aec463c7371e68f2fd0c738cd517932ea3801a35acf09db018deda57387b0f270f7a219e4d" + "0cc76dc777ea0d447e02a41004f37a0a7b1fafb6746884e8d9fc276716ccf47e4e0899548a2ec71c2bdf1a2a50e876db" + "053674cba9ef516ddc218fedb37324e6c47de27f88ab7ef123b006127d738293c0277187f7e2f80a299a24d84ed03da7"),
- },
- {
- u: common.FromHex("1870a7dbfd2a1deb74015a3546b20f598041bf5d5202997956a94a368d30d3f70f18cdaa1d33ce970a4e16af961cbdcb" + "045ab31ce4b5a8ba7c4b2851b64f063a66cd1223d3c85005b78e1beee65e33c90ceef0244e45fc45a5e1d6eab6644fdb"),
- expected: common.FromHex("18f0f87b40af67c056915dbaf48534c592524e82c1c2b50c3734d02c0172c80df780a60b5683759298a3303c5d942778" + "09349f1cb5b2e55489dcd45a38545343451cc30a1681c57acd4fb0a6db125f8352c09f4a67eb7d1d8242cb7d3405f97b" + "10a2ba341bc689ab947b7941ce6ef39be17acaab067bd32bd652b471ab0792c53a2bd03bdac47f96aaafe96e441f63c0" + "02f2d9deb2c7742512f5b8230bf0fd83ea42279d7d39779543c1a43b61c885982b611f6a7a24b514995e8a098496b811"),
- },
- {
- u: common.FromHex("088fe329b054db8a6474f21a7fbfdf17b4c18044db299d9007af582c3d5f17d00e56d99921d4b5640fce44b05219b5de" + "0b6e6135a4cd31ba980ddbd115ac48abef7ec60e226f264d7befe002c165f3a496f36f76dd524efd75d17422558d10b4"),
- expected: common.FromHex("19808ec5930a53c7cf5912ccce1cc33f1b3dcff24a53ce1cc4cba41fd6996dbed4843ccdd2eaf6a0cd801e562718d163" + "149fe43777d34f0d25430dea463889bd9393bdfb4932946db23671727081c629ebb98a89604f3433fba1c67d356a4af7" + "04783e391c30c83f805ca271e353582fdf19d159f6a4c39b73acbb637a9b8ac820cfbe2738d683368a7c07ad020e3e33" + "04c0d6793a766233b2982087b5f4a254f261003ccb3262ea7c50903eecef3e871d1502c293f9e063d7d293f6384f4551"),
- },
- {
- u: common.FromHex("03df16a66a05e4c1188c234788f43896e0565bfb64ac49b9639e6b284cc47dad73c47bb4ea7e677db8d496beb907fbb6" + "0f45b50647d67485295aa9eb2d91a877b44813677c67c8d35b2173ff3ba95f7bd0806f9ca8a1436b8b9d14ee81da4d7e"),
- expected: common.FromHex("0b8e0094c886487870372eb6264613a6a087c7eb9804fab789be4e47a57b29eb19b1983a51165a1b5eb025865e9fc63a" + "0804152cbf8474669ad7d1796ab92d7ca21f32d8bed70898a748ed4e4e0ec557069003732fc86866d938538a2ae95552" + "14c80f068ece15a3936bb00c3c883966f75b4e8d9ddde809c11f781ab92d23a2d1d103ad48f6f3bb158bf3e3a4063449" + "09e5c8242dd7281ad32c03fe4af3f19167770016255fb25ad9b67ec51d62fade31a1af101e8f6172ec2ee8857662be3a"),
- },
- } {
- g := NewG2()
-
- p0, err := g.MapToCurve(v.u)
- if err != nil {
- t.Fatal("map to curve fails", i, err)
- }
-
- if !bytes.Equal(g.ToBytes(p0), v.expected) {
- t.Fatal("map to curve fails", i)
- }
- }
-}
-
-func BenchmarkG2Add(t *testing.B) {
- g2 := NewG2()
- a, b, c := g2.rand(), g2.rand(), PointG2{}
-
- t.ResetTimer()
-
- for i := 0; i < t.N; i++ {
- g2.Add(&c, a, b)
- }
-}
-
-func BenchmarkG2Mul(t *testing.B) {
- worstCaseScalar, _ := new(big.Int).SetString("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)
- g2 := NewG2()
- a, e, c := g2.rand(), worstCaseScalar, PointG2{}
-
- t.ResetTimer()
-
- for i := 0; i < t.N; i++ {
- g2.MulScalar(&c, a, e)
- }
-}
-
-func BenchmarkG2SWUMap(t *testing.B) {
- a := make([]byte, 96)
- g2 := NewG2()
-
- t.ResetTimer()
-
- for i := 0; i < t.N; i++ {
- _, err := g2.MapToCurve(a)
- if err != nil {
- t.Fatal(err)
- }
- }
-}
diff --git a/crypto/bls12381/gt.go b/crypto/bls12381/gt.go
deleted file mode 100644
index 9ed91553a7..0000000000
--- a/crypto/bls12381/gt.go
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2020 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 bls12381
-
-import (
- "errors"
- "math/big"
-)
-
-// E is type for target group element
-type E = fe12
-
-// GT is type for target multiplicative group GT.
-type GT struct {
- fp12 *fp12
-}
-
-func (e *E) Set(e2 *E) *E {
- return e.set(e2)
-}
-
-// One sets a new target group element to one
-func (e *E) One() *E {
- e = new(fe12).one()
- return e
-}
-
-// IsOne returns true if given element equals to one
-func (e *E) IsOne() bool {
- return e.isOne()
-}
-
-// Equal returns true if given two element is equal, otherwise returns false
-func (g *E) Equal(g2 *E) bool {
- return g.equal(g2)
-}
-
-// NewGT constructs new target group instance.
-func NewGT() *GT {
- fp12 := newFp12(nil)
- return >{fp12}
-}
-
-// Q returns group order in big.Int.
-func (g *GT) Q() *big.Int {
- return new(big.Int).Set(q)
-}
-
-// FromBytes expects 576 byte input and returns target group element
-// FromBytes returns error if given element is not on correct subgroup.
-func (g *GT) FromBytes(in []byte) (*E, error) {
- e, err := g.fp12.fromBytes(in)
- if err != nil {
- return nil, err
- }
-
- if !g.IsValid(e) {
- return e, errors.New("invalid element")
- }
-
- return e, nil
-}
-
-// ToBytes serializes target group element.
-func (g *GT) ToBytes(e *E) []byte {
- return g.fp12.toBytes(e)
-}
-
-// IsValid checks whether given target group element is in correct subgroup.
-func (g *GT) IsValid(e *E) bool {
- r := g.New()
- g.fp12.exp(r, e, q)
-
- return r.isOne()
-}
-
-// New initializes a new target group element which is equal to one
-func (g *GT) New() *E {
- return new(E).One()
-}
-
-// Add adds two field element `a` and `b` and assigns the result to the element in first argument.
-func (g *GT) Add(c, a, b *E) {
- g.fp12.add(c, a, b)
-}
-
-// Sub subtracts two field element `a` and `b`, and assigns the result to the element in first argument.
-func (g *GT) Sub(c, a, b *E) {
- g.fp12.sub(c, a, b)
-}
-
-// Mul multiplies two field element `a` and `b` and assigns the result to the element in first argument.
-func (g *GT) Mul(c, a, b *E) {
- g.fp12.mul(c, a, b)
-}
-
-// Square squares an element `a` and assigns the result to the element in first argument.
-func (g *GT) Square(c, a *E) {
- g.fp12.cyclotomicSquare(c, a)
-}
-
-// Exp exponents an element `a` by a scalar `s` and assigns the result to the element in first argument.
-func (g *GT) Exp(c, a *E, s *big.Int) {
- g.fp12.cyclotomicExp(c, a, s)
-}
-
-// Inverse inverses an element `a` and assigns the result to the element in first argument.
-func (g *GT) Inverse(c, a *E) {
- g.fp12.inverse(c, a)
-}
diff --git a/crypto/bls12381/isogeny.go b/crypto/bls12381/isogeny.go
deleted file mode 100644
index ee5836e779..0000000000
--- a/crypto/bls12381/isogeny.go
+++ /dev/null
@@ -1,229 +0,0 @@
-// Copyright 2020 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 bls12381
-
-// isogenyMapG1 applies 11-isogeny map for BLS12-381 G1 defined at draft-irtf-cfrg-hash-to-curve-06.
-func isogenyMapG1(x, y *fe) {
- // https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#appendix-C.2
- params := isogenyConstantsG1
- degree := 15
- xNum, xDen, yNum, yDen := new(fe), new(fe), new(fe), new(fe)
- xNum.set(params[0][degree])
- xDen.set(params[1][degree])
- yNum.set(params[2][degree])
- yDen.set(params[3][degree])
-
- for i := degree - 1; i >= 0; i-- {
- mul(xNum, xNum, x)
- mul(xDen, xDen, x)
- mul(yNum, yNum, x)
- mul(yDen, yDen, x)
- add(xNum, xNum, params[0][i])
- add(xDen, xDen, params[1][i])
- add(yNum, yNum, params[2][i])
- add(yDen, yDen, params[3][i])
- }
- inverse(xDen, xDen)
- inverse(yDen, yDen)
- mul(xNum, xNum, xDen)
- mul(yNum, yNum, yDen)
- mul(yNum, yNum, y)
- x.set(xNum)
- y.set(yNum)
-}
-
-// isogenyMapG2 applies 11-isogeny map for BLS12-381 G1 defined at draft-irtf-cfrg-hash-to-curve-06.
-func isogenyMapG2(e *fp2, x, y *fe2) {
- if e == nil {
- e = newFp2()
- }
- // https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#appendix-C.2
- params := isogenyConstantsG2
- degree := 3
- xNum := new(fe2).set(params[0][degree])
- xDen := new(fe2).set(params[1][degree])
- yNum := new(fe2).set(params[2][degree])
- yDen := new(fe2).set(params[3][degree])
-
- for i := degree - 1; i >= 0; i-- {
- e.mul(xNum, xNum, x)
- e.mul(xDen, xDen, x)
- e.mul(yNum, yNum, x)
- e.mul(yDen, yDen, x)
- e.add(xNum, xNum, params[0][i])
- e.add(xDen, xDen, params[1][i])
- e.add(yNum, yNum, params[2][i])
- e.add(yDen, yDen, params[3][i])
- }
- e.inverse(xDen, xDen)
- e.inverse(yDen, yDen)
- e.mul(xNum, xNum, xDen)
- e.mul(yNum, yNum, yDen)
- e.mul(yNum, yNum, y)
- x.set(xNum)
- y.set(yNum)
-}
-
-var isogenyConstantsG1 = [4][16]*fe{
- {
- {0x4d18b6f3af00131c, 0x19fa219793fee28c, 0x3f2885f1467f19ae, 0x23dcea34f2ffb304, 0xd15b58d2ffc00054, 0x0913be200a20bef4},
- {0x898985385cdbbd8b, 0x3c79e43cc7d966aa, 0x1597e193f4cd233a, 0x8637ef1e4d6623ad, 0x11b22deed20d827b, 0x07097bc5998784ad},
- {0xa542583a480b664b, 0xfc7169c026e568c6, 0x5ba2ef314ed8b5a6, 0x5b5491c05102f0e7, 0xdf6e99707d2a0079, 0x0784151ed7605524},
- {0x494e212870f72741, 0xab9be52fbda43021, 0x26f5577994e34c3d, 0x049dfee82aefbd60, 0x65dadd7828505289, 0x0e93d431ea011aeb},
- {0x90ee774bd6a74d45, 0x7ada1c8a41bfb185, 0x0f1a8953b325f464, 0x104c24211be4805c, 0x169139d319ea7a8f, 0x09f20ead8e532bf6},
- {0x6ddd93e2f43626b7, 0xa5482c9aa1ccd7bd, 0x143245631883f4bd, 0x2e0a94ccf77ec0db, 0xb0282d480e56489f, 0x18f4bfcbb4368929},
- {0x23c5f0c953402dfd, 0x7a43ff6958ce4fe9, 0x2c390d3d2da5df63, 0xd0df5c98e1f9d70f, 0xffd89869a572b297, 0x1277ffc72f25e8fe},
- {0x79f4f0490f06a8a6, 0x85f894a88030fd81, 0x12da3054b18b6410, 0xe2a57f6505880d65, 0xbba074f260e400f1, 0x08b76279f621d028},
- {0xe67245ba78d5b00b, 0x8456ba9a1f186475, 0x7888bff6e6b33bb4, 0xe21585b9a30f86cb, 0x05a69cdcef55feee, 0x09e699dd9adfa5ac},
- {0x0de5c357bff57107, 0x0a0db4ae6b1a10b2, 0xe256bb67b3b3cd8d, 0x8ad456574e9db24f, 0x0443915f50fd4179, 0x098c4bf7de8b6375},
- {0xe6b0617e7dd929c7, 0xfe6e37d442537375, 0x1dafdeda137a489e, 0xe4efd1ad3f767ceb, 0x4a51d8667f0fe1cf, 0x054fdf4bbf1d821c},
- {0x72db2a50658d767b, 0x8abf91faa257b3d5, 0xe969d6833764ab47, 0x464170142a1009eb, 0xb14f01aadb30be2f, 0x18ae6a856f40715d},
- {0, 0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0, 0},
- },
- {
- {0xb962a077fdb0f945, 0xa6a9740fefda13a0, 0xc14d568c3ed6c544, 0xb43fc37b908b133e, 0x9c0b3ac929599016, 0x0165aa6c93ad115f},
- {0x23279a3ba506c1d9, 0x92cfca0a9465176a, 0x3b294ab13755f0ff, 0x116dda1c5070ae93, 0xed4530924cec2045, 0x083383d6ed81f1ce},
- {0x9885c2a6449fecfc, 0x4a2b54ccd37733f0, 0x17da9ffd8738c142, 0xa0fba72732b3fafd, 0xff364f36e54b6812, 0x0f29c13c660523e2},
- {0xe349cc118278f041, 0xd487228f2f3204fb, 0xc9d325849ade5150, 0x43a92bd69c15c2df, 0x1c2c7844bc417be4, 0x12025184f407440c},
- {0x587f65ae6acb057b, 0x1444ef325140201f, 0xfbf995e71270da49, 0xccda066072436a42, 0x7408904f0f186bb2, 0x13b93c63edf6c015},
- {0xfb918622cd141920, 0x4a4c64423ecaddb4, 0x0beb232927f7fb26, 0x30f94df6f83a3dc2, 0xaeedd424d780f388, 0x06cc402dd594bbeb},
- {0xd41f761151b23f8f, 0x32a92465435719b3, 0x64f436e888c62cb9, 0xdf70a9a1f757c6e4, 0x6933a38d5b594c81, 0x0c6f7f7237b46606},
- {0x693c08747876c8f7, 0x22c9850bf9cf80f0, 0x8e9071dab950c124, 0x89bc62d61c7baf23, 0xbc6be2d8dad57c23, 0x17916987aa14a122},
- {0x1be3ff439c1316fd, 0x9965243a7571dfa7, 0xc7f7f62962f5cd81, 0x32c6aa9af394361c, 0xbbc2ee18e1c227f4, 0x0c102cbac531bb34},
- {0x997614c97bacbf07, 0x61f86372b99192c0, 0x5b8c95fc14353fc3, 0xca2b066c2a87492f, 0x16178f5bbf698711, 0x12a6dcd7f0f4e0e8},
- {0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
- {0, 0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0, 0},
- },
- {
- {0x2b567ff3e2837267, 0x1d4d9e57b958a767, 0xce028fea04bd7373, 0xcc31a30a0b6cd3df, 0x7d7b18a682692693, 0x0d300744d42a0310},
- {0x99c2555fa542493f, 0xfe7f53cc4874f878, 0x5df0608b8f97608a, 0x14e03832052b49c8, 0x706326a6957dd5a4, 0x0a8dadd9c2414555},
- {0x13d942922a5cf63a, 0x357e33e36e261e7d, 0xcf05a27c8456088d, 0x0000bd1de7ba50f0, 0x83d0c7532f8c1fde, 0x13f70bf38bbf2905},
- {0x5c57fd95bfafbdbb, 0x28a359a65e541707, 0x3983ceb4f6360b6d, 0xafe19ff6f97e6d53, 0xb3468f4550192bf7, 0x0bb6cde49d8ba257},
- {0x590b62c7ff8a513f, 0x314b4ce372cacefd, 0x6bef32ce94b8a800, 0x6ddf84a095713d5f, 0x64eace4cb0982191, 0x0386213c651b888d},
- {0xa5310a31111bbcdd, 0xa14ac0f5da148982, 0xf9ad9cc95423d2e9, 0xaa6ec095283ee4a7, 0xcf5b1f022e1c9107, 0x01fddf5aed881793},
- {0x65a572b0d7a7d950, 0xe25c2d8183473a19, 0xc2fcebe7cb877dbd, 0x05b2d36c769a89b0, 0xba12961be86e9efb, 0x07eb1b29c1dfde1f},
- {0x93e09572f7c4cd24, 0x364e929076795091, 0x8569467e68af51b5, 0xa47da89439f5340f, 0xf4fa918082e44d64, 0x0ad52ba3e6695a79},
- {0x911429844e0d5f54, 0xd03f51a3516bb233, 0x3d587e5640536e66, 0xfa86d2a3a9a73482, 0xa90ed5adf1ed5537, 0x149c9c326a5e7393},
- {0x462bbeb03c12921a, 0xdc9af5fa0a274a17, 0x9a558ebde836ebed, 0x649ef8f11a4fae46, 0x8100e1652b3cdc62, 0x1862bd62c291dacb},
- {0x05c9b8ca89f12c26, 0x0194160fa9b9ac4f, 0x6a643d5a6879fa2c, 0x14665bdd8846e19d, 0xbb1d0d53af3ff6bf, 0x12c7e1c3b28962e5},
- {0xb55ebf900b8a3e17, 0xfedc77ec1a9201c4, 0x1f07db10ea1a4df4, 0x0dfbd15dc41a594d, 0x389547f2334a5391, 0x02419f98165871a4},
- {0xb416af000745fc20, 0x8e563e9d1ea6d0f5, 0x7c763e17763a0652, 0x01458ef0159ebbef, 0x8346fe421f96bb13, 0x0d2d7b829ce324d2},
- {0x93096bb538d64615, 0x6f2a2619951d823a, 0x8f66b3ea59514fa4, 0xf563e63704f7092f, 0x724b136c4cf2d9fa, 0x046959cfcfd0bf49},
- {0xea748d4b6e405346, 0x91e9079c2c02d58f, 0x41064965946d9b59, 0xa06731f1d2bbe1ee, 0x07f897e267a33f1b, 0x1017290919210e5f},
- {0x872aa6c17d985097, 0xeecc53161264562a, 0x07afe37afff55002, 0x54759078e5be6838, 0xc4b92d15db8acca8, 0x106d87d1b51d13b9},
- },
- {
- {0xeb6c359d47e52b1c, 0x18ef5f8a10634d60, 0xddfa71a0889d5b7e, 0x723e71dcc5fc1323, 0x52f45700b70d5c69, 0x0a8b981ee47691f1},
- {0x616a3c4f5535b9fb, 0x6f5f037395dbd911, 0xf25f4cc5e35c65da, 0x3e50dffea3c62658, 0x6a33dca523560776, 0x0fadeff77b6bfe3e},
- {0x2be9b66df470059c, 0x24a2c159a3d36742, 0x115dbe7ad10c2a37, 0xb6634a652ee5884d, 0x04fe8bb2b8d81af4, 0x01c2a7a256fe9c41},
- {0xf27bf8ef3b75a386, 0x898b367476c9073f, 0x24482e6b8c2f4e5f, 0xc8e0bbd6fe110806, 0x59b0c17f7631448a, 0x11037cd58b3dbfbd},
- {0x31c7912ea267eec6, 0x1dbf6f1c5fcdb700, 0xd30d4fe3ba86fdb1, 0x3cae528fbee9a2a4, 0xb1cce69b6aa9ad9a, 0x044393bb632d94fb},
- {0xc66ef6efeeb5c7e8, 0x9824c289dd72bb55, 0x71b1a4d2f119981d, 0x104fc1aafb0919cc, 0x0e49df01d942a628, 0x096c3a09773272d4},
- {0x9abc11eb5fadeff4, 0x32dca50a885728f0, 0xfb1fa3721569734c, 0xc4b76271ea6506b3, 0xd466a75599ce728e, 0x0c81d4645f4cb6ed},
- {0x4199f10e5b8be45b, 0xda64e495b1e87930, 0xcb353efe9b33e4ff, 0x9e9efb24aa6424c6, 0xf08d33680a237465, 0x0d3378023e4c7406},
- {0x7eb4ae92ec74d3a5, 0xc341b4aa9fac3497, 0x5be603899e907687, 0x03bfd9cca75cbdeb, 0x564c2935a96bfa93, 0x0ef3c33371e2fdb5},
- {0x7ee91fd449f6ac2e, 0xe5d5bd5cb9357a30, 0x773a8ca5196b1380, 0xd0fda172174ed023, 0x6cb95e0fa776aead, 0x0d22d5a40cec7cff},
- {0xf727e09285fd8519, 0xdc9d55a83017897b, 0x7549d8bd057894ae, 0x178419613d90d8f8, 0xfce95ebdeb5b490a, 0x0467ffaef23fc49e},
- {0xc1769e6a7c385f1b, 0x79bc930deac01c03, 0x5461c75a23ede3b5, 0x6e20829e5c230c45, 0x828e0f1e772a53cd, 0x116aefa749127bff},
- {0x101c10bf2744c10a, 0xbbf18d053a6a3154, 0xa0ecf39ef026f602, 0xfc009d4996dc5153, 0xb9000209d5bd08d3, 0x189e5fe4470cd73c},
- {0x7ebd546ca1575ed2, 0xe47d5a981d081b55, 0x57b2b625b6d4ca21, 0xb0a1ba04228520cc, 0x98738983c2107ff3, 0x13dddbc4799d81d6},
- {0x09319f2e39834935, 0x039e952cbdb05c21, 0x55ba77a9a2f76493, 0xfd04e3dfc6086467, 0xfb95832e7d78742e, 0x0ef9c24eccaf5e0e},
- {0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
- },
-}
-
-var isogenyConstantsG2 = [4][4]*fe2{
- {
- {
- fe{0x47f671c71ce05e62, 0x06dd57071206393e, 0x7c80cd2af3fd71a2, 0x048103ea9e6cd062, 0xc54516acc8d037f6, 0x13808f550920ea41},
- fe{0x47f671c71ce05e62, 0x06dd57071206393e, 0x7c80cd2af3fd71a2, 0x048103ea9e6cd062, 0xc54516acc8d037f6, 0x13808f550920ea41},
- },
- {
- fe{0, 0, 0, 0, 0, 0},
- fe{0x5fe55555554c71d0, 0x873fffdd236aaaa3, 0x6a6b4619b26ef918, 0x21c2888408874945, 0x2836cda7028cabc5, 0x0ac73310a7fd5abd},
- },
- {
- fe{0x0a0c5555555971c3, 0xdb0c00101f9eaaae, 0xb1fb2f941d797997, 0xd3960742ef416e1c, 0xb70040e2c20556f4, 0x149d7861e581393b},
- fe{0xaff2aaaaaaa638e8, 0x439fffee91b55551, 0xb535a30cd9377c8c, 0x90e144420443a4a2, 0x941b66d3814655e2, 0x0563998853fead5e},
- },
- {
- fe{0x40aac71c71c725ed, 0x190955557a84e38e, 0xd817050a8f41abc3, 0xd86485d4c87f6fb1, 0x696eb479f885d059, 0x198e1a74328002d2},
- fe{0, 0, 0, 0, 0, 0},
- },
- },
- {
- {
- fe{0, 0, 0, 0, 0, 0},
- fe{0x1f3affffff13ab97, 0xf25bfc611da3ff3e, 0xca3757cb3819b208, 0x3e6427366f8cec18, 0x03977bc86095b089, 0x04f69db13f39a952},
- },
- {
- fe{0x447600000027552e, 0xdcb8009a43480020, 0x6f7ee9ce4a6e8b59, 0xb10330b7c0a95bc6, 0x6140b1fcfb1e54b7, 0x0381be097f0bb4e1},
- fe{0x7588ffffffd8557d, 0x41f3ff646e0bffdf, 0xf7b1e8d2ac426aca, 0xb3741acd32dbb6f8, 0xe9daf5b9482d581f, 0x167f53e0ba7431b8},
- },
- {
- fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
- fe{0, 0, 0, 0, 0, 0},
- },
- {
- fe{0, 0, 0, 0, 0, 0},
- fe{0, 0, 0, 0, 0, 0},
- },
- },
- {
- {
- fe{0x96d8f684bdfc77be, 0xb530e4f43b66d0e2, 0x184a88ff379652fd, 0x57cb23ecfae804e1, 0x0fd2e39eada3eba9, 0x08c8055e31c5d5c3},
- fe{0x96d8f684bdfc77be, 0xb530e4f43b66d0e2, 0x184a88ff379652fd, 0x57cb23ecfae804e1, 0x0fd2e39eada3eba9, 0x08c8055e31c5d5c3},
- },
- {
- fe{0, 0, 0, 0, 0, 0},
- fe{0xbf0a71c71c91b406, 0x4d6d55d28b7638fd, 0x9d82f98e5f205aee, 0xa27aa27b1d1a18d5, 0x02c3b2b2d2938e86, 0x0c7d13420b09807f},
- },
- {
- fe{0xd7f9555555531c74, 0x21cffff748daaaa8, 0x5a9ad1866c9bbe46, 0x4870a2210221d251, 0x4a0db369c0a32af1, 0x02b1ccc429ff56af},
- fe{0xe205aaaaaaac8e37, 0xfcdc000768795556, 0x0c96011a8a1537dd, 0x1c06a963f163406e, 0x010df44c82a881e6, 0x174f45260f808feb},
- },
- {
- fe{0xa470bda12f67f35c, 0xc0fe38e23327b425, 0xc9d3d0f2c6f0678d, 0x1c55c9935b5a982e, 0x27f6c0e2f0746764, 0x117c5e6e28aa9054},
- fe{0, 0, 0, 0, 0, 0},
- },
- },
- {
- {
- fe{0x0162fffffa765adf, 0x8f7bea480083fb75, 0x561b3c2259e93611, 0x11e19fc1a9c875d5, 0xca713efc00367660, 0x03c6a03d41da1151},
- fe{0x0162fffffa765adf, 0x8f7bea480083fb75, 0x561b3c2259e93611, 0x11e19fc1a9c875d5, 0xca713efc00367660, 0x03c6a03d41da1151},
- },
- {
- fe{0, 0, 0, 0, 0, 0},
- fe{0x5db0fffffd3b02c5, 0xd713f52358ebfdba, 0x5ea60761a84d161a, 0xbb2c75a34ea6c44a, 0x0ac6735921c1119b, 0x0ee3d913bdacfbf6},
- },
- {
- fe{0x66b10000003affc5, 0xcb1400e764ec0030, 0xa73e5eb56fa5d106, 0x8984c913a0fe09a9, 0x11e10afb78ad7f13, 0x05429d0e3e918f52},
- fe{0x534dffffffc4aae6, 0x5397ff174c67ffcf, 0xbff273eb870b251d, 0xdaf2827152870915, 0x393a9cbaca9e2dc3, 0x14be74dbfaee5748},
- },
- {
- fe{0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493},
- fe{0, 0, 0, 0, 0, 0},
- },
- },
-}
diff --git a/crypto/bls12381/pairing.go b/crypto/bls12381/pairing.go
deleted file mode 100644
index 24e78bd7fc..0000000000
--- a/crypto/bls12381/pairing.go
+++ /dev/null
@@ -1,302 +0,0 @@
-// Copyright 2020 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 bls12381
-
-type pair struct {
- g1 *PointG1
- g2 *PointG2
-}
-
-func newPair(g1 *PointG1, g2 *PointG2) pair {
- return pair{g1, g2}
-}
-
-// Engine is BLS12-381 elliptic curve pairing engine
-type Engine struct {
- G1 *G1
- G2 *G2
- fp12 *fp12
- fp2 *fp2
- pairingEngineTemp
- pairs []pair
-}
-
-// NewPairingEngine creates new pairing engine instance.
-func NewPairingEngine() *Engine {
- fp2 := newFp2()
- fp6 := newFp6(fp2)
- fp12 := newFp12(fp6)
- g1 := NewG1()
- g2 := newG2(fp2)
-
- return &Engine{
- fp2: fp2,
- fp12: fp12,
- G1: g1,
- G2: g2,
- pairingEngineTemp: newEngineTemp(),
- }
-}
-
-type pairingEngineTemp struct {
- t2 [10]*fe2
- t12 [9]fe12
-}
-
-func newEngineTemp() pairingEngineTemp {
- t2 := [10]*fe2{}
- for i := 0; i < 10; i++ {
- t2[i] = &fe2{}
- }
-
- t12 := [9]fe12{}
-
- return pairingEngineTemp{t2, t12}
-}
-
-// AddPair adds a g1, g2 point pair to pairing engine
-func (e *Engine) AddPair(g1 *PointG1, g2 *PointG2) *Engine {
- p := newPair(g1, g2)
- if !e.isZero(p) {
- e.affine(p)
- e.pairs = append(e.pairs, p)
- }
-
- return e
-}
-
-// AddPairInv adds a G1, G2 point pair to pairing engine. G1 point is negated.
-func (e *Engine) AddPairInv(g1 *PointG1, g2 *PointG2) *Engine {
- e.G1.Neg(g1, g1)
- e.AddPair(g1, g2)
-
- return e
-}
-
-// Reset deletes added pairs.
-func (e *Engine) Reset() *Engine {
- e.pairs = []pair{}
- return e
-}
-
-func (e *Engine) isZero(p pair) bool {
- return e.G1.IsZero(p.g1) || e.G2.IsZero(p.g2)
-}
-
-func (e *Engine) affine(p pair) {
- e.G1.Affine(p.g1)
- e.G2.Affine(p.g2)
-}
-
-func (e *Engine) doublingStep(coeff *[3]fe2, r *PointG2) {
- // Adaptation of Formula 3 in https://eprint.iacr.org/2010/526.pdf
- fp2 := e.fp2
- t := e.t2
- fp2.mul(t[0], &r[0], &r[1])
- fp2.mulByFq(t[0], t[0], twoInv)
- fp2.square(t[1], &r[1])
- fp2.square(t[2], &r[2])
- fp2.double(t[7], t[2])
- fp2.add(t[7], t[7], t[2])
- fp2.mulByB(t[3], t[7])
- fp2.double(t[4], t[3])
- fp2.add(t[4], t[4], t[3])
- fp2.add(t[5], t[1], t[4])
- fp2.mulByFq(t[5], t[5], twoInv)
- fp2.add(t[6], &r[1], &r[2])
- fp2.square(t[6], t[6])
- fp2.add(t[7], t[2], t[1])
- fp2.sub(t[6], t[6], t[7])
- fp2.sub(&coeff[0], t[3], t[1])
- fp2.square(t[7], &r[0])
- fp2.sub(t[4], t[1], t[4])
- fp2.mul(&r[0], t[4], t[0])
- fp2.square(t[2], t[3])
- fp2.double(t[3], t[2])
- fp2.add(t[3], t[3], t[2])
- fp2.square(t[5], t[5])
- fp2.sub(&r[1], t[5], t[3])
- fp2.mul(&r[2], t[1], t[6])
- fp2.double(t[0], t[7])
- fp2.add(&coeff[1], t[0], t[7])
- fp2.neg(&coeff[2], t[6])
-}
-
-func (e *Engine) additionStep(coeff *[3]fe2, r, q *PointG2) {
- // Algorithm 12 in https://eprint.iacr.org/2010/526.pdf
- fp2 := e.fp2
- t := e.t2
- fp2.mul(t[0], &q[1], &r[2])
- fp2.neg(t[0], t[0])
- fp2.add(t[0], t[0], &r[1])
- fp2.mul(t[1], &q[0], &r[2])
- fp2.neg(t[1], t[1])
- fp2.add(t[1], t[1], &r[0])
- fp2.square(t[2], t[0])
- fp2.square(t[3], t[1])
- fp2.mul(t[4], t[1], t[3])
- fp2.mul(t[2], &r[2], t[2])
- fp2.mul(t[3], &r[0], t[3])
- fp2.double(t[5], t[3])
- fp2.sub(t[5], t[4], t[5])
- fp2.add(t[5], t[5], t[2])
- fp2.mul(&r[0], t[1], t[5])
- fp2.sub(t[2], t[3], t[5])
- fp2.mul(t[2], t[2], t[0])
- fp2.mul(t[3], &r[1], t[4])
- fp2.sub(&r[1], t[2], t[3])
- fp2.mul(&r[2], &r[2], t[4])
- fp2.mul(t[2], t[1], &q[1])
- fp2.mul(t[3], t[0], &q[0])
- fp2.sub(&coeff[0], t[3], t[2])
- fp2.neg(&coeff[1], t[0])
- coeff[2].set(t[1])
-}
-
-func (e *Engine) preCompute(ellCoeffs *[68][3]fe2, twistPoint *PointG2) {
- // Algorithm 5 in https://eprint.iacr.org/2019/077.pdf
- if e.G2.IsZero(twistPoint) {
- return
- }
-
- r := new(PointG2).Set(twistPoint)
- j := 0
-
- for i := x.BitLen() - 2; i >= 0; i-- {
- e.doublingStep(&ellCoeffs[j], r)
-
- if x.Bit(i) != 0 {
- j++
- ellCoeffs[j] = fe6{}
- e.additionStep(&ellCoeffs[j], r, twistPoint)
- }
-
- j++
- }
-}
-
-func (e *Engine) millerLoop(f *fe12) {
- pairs := e.pairs
- ellCoeffs := make([][68][3]fe2, len(pairs))
-
- for i := 0; i < len(pairs); i++ {
- e.preCompute(&ellCoeffs[i], pairs[i].g2)
- }
-
- fp12, fp2 := e.fp12, e.fp2
- t := e.t2
-
- f.one()
-
- j := 0
-
- for i := 62; /* x.BitLen() - 2 */ i >= 0; i-- {
- if i != 62 {
- fp12.square(f, f)
- }
-
- for i := 0; i <= len(pairs)-1; i++ {
- fp2.mulByFq(t[0], &ellCoeffs[i][j][2], &pairs[i].g1[1])
- fp2.mulByFq(t[1], &ellCoeffs[i][j][1], &pairs[i].g1[0])
- fp12.mulBy014Assign(f, &ellCoeffs[i][j][0], t[1], t[0])
- }
-
- if x.Bit(i) != 0 {
- j++
- for i := 0; i <= len(pairs)-1; i++ {
- fp2.mulByFq(t[0], &ellCoeffs[i][j][2], &pairs[i].g1[1])
- fp2.mulByFq(t[1], &ellCoeffs[i][j][1], &pairs[i].g1[0])
- fp12.mulBy014Assign(f, &ellCoeffs[i][j][0], t[1], t[0])
- }
- }
-
- j++
- }
- fp12.conjugate(f, f)
-}
-
-func (e *Engine) exp(c, a *fe12) {
- fp12 := e.fp12
- fp12.cyclotomicExp(c, a, x)
- fp12.conjugate(c, c)
-}
-
-func (e *Engine) finalExp(f *fe12) {
- fp12 := e.fp12
- t := e.t12
- // easy part
- fp12.frobeniusMap(&t[0], f, 6)
- fp12.inverse(&t[1], f)
- fp12.mul(&t[2], &t[0], &t[1])
- t[1].set(&t[2])
- fp12.frobeniusMapAssign(&t[2], 2)
- fp12.mulAssign(&t[2], &t[1])
- fp12.cyclotomicSquare(&t[1], &t[2])
- fp12.conjugate(&t[1], &t[1])
- // hard part
- e.exp(&t[3], &t[2])
- fp12.cyclotomicSquare(&t[4], &t[3])
- fp12.mul(&t[5], &t[1], &t[3])
- e.exp(&t[1], &t[5])
- e.exp(&t[0], &t[1])
- e.exp(&t[6], &t[0])
- fp12.mulAssign(&t[6], &t[4])
- e.exp(&t[4], &t[6])
- fp12.conjugate(&t[5], &t[5])
- fp12.mulAssign(&t[4], &t[5])
- fp12.mulAssign(&t[4], &t[2])
- fp12.conjugate(&t[5], &t[2])
- fp12.mulAssign(&t[1], &t[2])
- fp12.frobeniusMapAssign(&t[1], 3)
- fp12.mulAssign(&t[6], &t[5])
- fp12.frobeniusMapAssign(&t[6], 1)
- fp12.mulAssign(&t[3], &t[0])
- fp12.frobeniusMapAssign(&t[3], 2)
- fp12.mulAssign(&t[3], &t[1])
- fp12.mulAssign(&t[3], &t[6])
- fp12.mul(f, &t[3], &t[4])
-}
-
-func (e *Engine) calculate() *fe12 {
- f := e.fp12.one()
- if len(e.pairs) == 0 {
- return f
- }
-
- e.millerLoop(f)
- e.finalExp(f)
-
- return f
-}
-
-// Check computes pairing and checks if result is equal to one
-func (e *Engine) Check() bool {
- return e.calculate().isOne()
-}
-
-// Result computes pairing and returns target group element as result.
-func (e *Engine) Result() *E {
- r := e.calculate()
- e.Reset()
-
- return r
-}
-
-// GT returns target group instance.
-func (e *Engine) GT() *GT {
- return NewGT()
-}
diff --git a/crypto/bls12381/pairing_test.go b/crypto/bls12381/pairing_test.go
deleted file mode 100644
index bb66bd9357..0000000000
--- a/crypto/bls12381/pairing_test.go
+++ /dev/null
@@ -1,248 +0,0 @@
-package bls12381
-
-import (
- "math/big"
- "testing"
-
- "github.com/ethereum/go-ethereum/common"
-)
-
-func TestPairingExpected(t *testing.T) {
- bls := NewPairingEngine()
- G1, G2 := bls.G1, bls.G2
- GT := bls.GT()
-
- expected, err := GT.FromBytes(
- common.FromHex("" +
- "0f41e58663bf08cf068672cbd01a7ec73baca4d72ca93544deff686bfd6df543d48eaa24afe47e1efde449383b676631" +
- "04c581234d086a9902249b64728ffd21a189e87935a954051c7cdba7b3872629a4fafc05066245cb9108f0242d0fe3ef" +
- "03350f55a7aefcd3c31b4fcb6ce5771cc6a0e9786ab5973320c806ad360829107ba810c5a09ffdd9be2291a0c25a99a2" +
- "11b8b424cd48bf38fcef68083b0b0ec5c81a93b330ee1a677d0d15ff7b984e8978ef48881e32fac91b93b47333e2ba57" +
- "06fba23eb7c5af0d9f80940ca771b6ffd5857baaf222eb95a7d2809d61bfe02e1bfd1b68ff02f0b8102ae1c2d5d5ab1a" +
- "19f26337d205fb469cd6bd15c3d5a04dc88784fbb3d0b2dbdea54d43b2b73f2cbb12d58386a8703e0f948226e47ee89d" +
- "018107154f25a764bd3c79937a45b84546da634b8f6be14a8061e55cceba478b23f7dacaa35c8ca78beae9624045b4b6" +
- "01b2f522473d171391125ba84dc4007cfbf2f8da752f7c74185203fcca589ac719c34dffbbaad8431dad1c1fb597aaa5" +
- "193502b86edb8857c273fa075a50512937e0794e1e65a7617c90d8bd66065b1fffe51d7a579973b1315021ec3c19934f" +
- "1368bb445c7c2d209703f239689ce34c0378a68e72a6b3b216da0e22a5031b54ddff57309396b38c881c4c849ec23e87" +
- "089a1c5b46e5110b86750ec6a532348868a84045483c92b7af5af689452eafabf1a8943e50439f1d59882a98eaa0170f" +
- "1250ebd871fc0a92a7b2d83168d0d727272d441befa15c503dd8e90ce98db3e7b6d194f60839c508a84305aaca1789b6",
- ),
- )
- if err != nil {
- t.Fatal(err)
- }
-
- r := bls.AddPair(G1.One(), G2.One()).Result()
- if !r.Equal(expected) {
- t.Fatal("bad pairing")
- }
-
- if !GT.IsValid(r) {
- t.Fatal("element is not in correct subgroup")
- }
-}
-
-func TestPairingNonDegeneracy(t *testing.T) {
- bls := NewPairingEngine()
- G1, G2 := bls.G1, bls.G2
- g1Zero, g2Zero, g1One, g2One := G1.Zero(), G2.Zero(), G1.One(), G2.One()
- GT := bls.GT()
- // e(g1^a, g2^b) != 1
- bls.Reset()
- {
- bls.AddPair(g1One, g2One)
-
- e := bls.Result()
- if e.IsOne() {
- t.Fatal("pairing result is not expected to be one")
- }
-
- if !GT.IsValid(e) {
- t.Fatal("pairing result is not valid")
- }
- }
- // e(g1^a, 0) == 1
- bls.Reset()
- {
- bls.AddPair(g1One, g2Zero)
-
- e := bls.Result()
- if !e.IsOne() {
- t.Fatal("pairing result is expected to be one")
- }
- }
- // e(0, g2^b) == 1
- bls.Reset()
- {
- bls.AddPair(g1Zero, g2One)
-
- e := bls.Result()
- if !e.IsOne() {
- t.Fatal("pairing result is expected to be one")
- }
- }
- //
- bls.Reset()
- {
- bls.AddPair(g1Zero, g2One)
- bls.AddPair(g1One, g2Zero)
- bls.AddPair(g1Zero, g2Zero)
-
- e := bls.Result()
- if !e.IsOne() {
- t.Fatal("pairing result is expected to be one")
- }
- }
- //
- bls.Reset()
- {
- expected, err := GT.FromBytes(
- common.FromHex("" +
- "0f41e58663bf08cf068672cbd01a7ec73baca4d72ca93544deff686bfd6df543d48eaa24afe47e1efde449383b676631" +
- "04c581234d086a9902249b64728ffd21a189e87935a954051c7cdba7b3872629a4fafc05066245cb9108f0242d0fe3ef" +
- "03350f55a7aefcd3c31b4fcb6ce5771cc6a0e9786ab5973320c806ad360829107ba810c5a09ffdd9be2291a0c25a99a2" +
- "11b8b424cd48bf38fcef68083b0b0ec5c81a93b330ee1a677d0d15ff7b984e8978ef48881e32fac91b93b47333e2ba57" +
- "06fba23eb7c5af0d9f80940ca771b6ffd5857baaf222eb95a7d2809d61bfe02e1bfd1b68ff02f0b8102ae1c2d5d5ab1a" +
- "19f26337d205fb469cd6bd15c3d5a04dc88784fbb3d0b2dbdea54d43b2b73f2cbb12d58386a8703e0f948226e47ee89d" +
- "018107154f25a764bd3c79937a45b84546da634b8f6be14a8061e55cceba478b23f7dacaa35c8ca78beae9624045b4b6" +
- "01b2f522473d171391125ba84dc4007cfbf2f8da752f7c74185203fcca589ac719c34dffbbaad8431dad1c1fb597aaa5" +
- "193502b86edb8857c273fa075a50512937e0794e1e65a7617c90d8bd66065b1fffe51d7a579973b1315021ec3c19934f" +
- "1368bb445c7c2d209703f239689ce34c0378a68e72a6b3b216da0e22a5031b54ddff57309396b38c881c4c849ec23e87" +
- "089a1c5b46e5110b86750ec6a532348868a84045483c92b7af5af689452eafabf1a8943e50439f1d59882a98eaa0170f" +
- "1250ebd871fc0a92a7b2d83168d0d727272d441befa15c503dd8e90ce98db3e7b6d194f60839c508a84305aaca1789b6",
- ),
- )
- if err != nil {
- t.Fatal(err)
- }
-
- bls.AddPair(g1Zero, g2One)
- bls.AddPair(g1One, g2Zero)
- bls.AddPair(g1Zero, g2Zero)
- bls.AddPair(g1One, g2One)
-
- e := bls.Result()
- if !e.Equal(expected) {
- t.Fatal("bad pairing")
- }
- }
-}
-
-func TestPairingBilinearity(t *testing.T) {
- bls := NewPairingEngine()
- g1, g2 := bls.G1, bls.G2
- gt := bls.GT()
- // e(a*G1, b*G2) = e(G1, G2)^c
- {
- a, b := big.NewInt(17), big.NewInt(117)
- c := new(big.Int).Mul(a, b)
- G1, G2 := g1.One(), g2.One()
- e0 := bls.AddPair(G1, G2).Result()
- P1, P2 := g1.New(), g2.New()
- g1.MulScalar(P1, G1, a)
- g2.MulScalar(P2, G2, b)
- e1 := bls.AddPair(P1, P2).Result()
-
- gt.Exp(e0, e0, c)
-
- if !e0.Equal(e1) {
- t.Fatal("bad pairing, 1")
- }
- }
- // e(a * G1, b * G2) = e((a + b) * G1, G2)
- {
- // scalars
- a, b := big.NewInt(17), big.NewInt(117)
- c := new(big.Int).Mul(a, b)
- // LHS
- G1, G2 := g1.One(), g2.One()
- g1.MulScalar(G1, G1, c)
- bls.AddPair(G1, G2)
- // RHS
- P1, P2 := g1.One(), g2.One()
- g1.MulScalar(P1, P1, a)
- g2.MulScalar(P2, P2, b)
- bls.AddPairInv(P1, P2)
- // should be one
- if !bls.Check() {
- t.Fatal("bad pairing, 2")
- }
- }
- // e(a * G1, b * G2) = e((a + b) * G1, G2)
- {
- // scalars
- a, b := big.NewInt(17), big.NewInt(117)
- c := new(big.Int).Mul(a, b)
- // LHS
- G1, G2 := g1.One(), g2.One()
- g2.MulScalar(G2, G2, c)
- bls.AddPair(G1, G2)
- // RHS
- H1, H2 := g1.One(), g2.One()
- g1.MulScalar(H1, H1, a)
- g2.MulScalar(H2, H2, b)
- bls.AddPairInv(H1, H2)
- // should be one
- if !bls.Check() {
- t.Fatal("bad pairing, 3")
- }
- }
-}
-
-func TestPairingMulti(t *testing.T) {
- // e(G1, G2) ^ t == e(a01 * G1, a02 * G2) * e(a11 * G1, a12 * G2) * ... * e(an1 * G1, an2 * G2)
- // where t = sum(ai1 * ai2)
- bls := NewPairingEngine()
- g1, g2 := bls.G1, bls.G2
- numOfPair := 100
- targetExp := new(big.Int)
- // RHS
- for i := 0; i < numOfPair; i++ {
- // (ai1 * G1, ai2 * G2)
- a1, a2 := randScalar(q), randScalar(q)
- P1, P2 := g1.One(), g2.One()
- g1.MulScalar(P1, P1, a1)
- g2.MulScalar(P2, P2, a2)
- bls.AddPair(P1, P2)
- // accumulate targetExp
- // t += (ai1 * ai2)
- a1.Mul(a1, a2)
- targetExp.Add(targetExp, a1)
- }
- // LHS
- // e(t * G1, G2)
- T1, T2 := g1.One(), g2.One()
- g1.MulScalar(T1, T1, targetExp)
- bls.AddPairInv(T1, T2)
-
- if !bls.Check() {
- t.Fatal("fail multi pairing")
- }
-}
-
-func TestPairingEmpty(t *testing.T) {
- bls := NewPairingEngine()
- if !bls.Check() {
- t.Fatal("empty check should be accepted")
- }
-
- if !bls.Result().IsOne() {
- t.Fatal("empty pairing result should be one")
- }
-}
-
-func BenchmarkPairing(t *testing.B) {
- bls := NewPairingEngine()
- g1, g2, gt := bls.G1, bls.G2, bls.GT()
- bls.AddPair(g1.One(), g2.One())
-
- e := gt.New()
-
- t.ResetTimer()
-
- for i := 0; i < t.N; i++ {
- e = bls.calculate()
- }
-
- _ = e
-}
diff --git a/crypto/bls12381/swu.go b/crypto/bls12381/swu.go
deleted file mode 100644
index 01d55f6a5f..0000000000
--- a/crypto/bls12381/swu.go
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright 2020 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 bls12381
-
-// swuMapG1 is implementation of Simplified Shallue-van de Woestijne-Ulas Method
-// follows the implementation at draft-irtf-cfrg-hash-to-curve-06.
-func swuMapG1(u *fe) (*fe, *fe) {
- var params = swuParamsForG1
-
- var tv [4]*fe
- for i := 0; i < 4; i++ {
- tv[i] = new(fe)
- }
- square(tv[0], u)
- mul(tv[0], tv[0], params.z)
- square(tv[1], tv[0])
-
- x1 := new(fe)
- add(x1, tv[0], tv[1])
- inverse(x1, x1)
- e1 := x1.isZero()
- one := new(fe).one()
- add(x1, x1, one)
-
- if e1 {
- x1.set(params.zInv)
- }
-
- mul(x1, x1, params.minusBOverA)
-
- gx1 := new(fe)
- square(gx1, x1)
- add(gx1, gx1, params.a)
- mul(gx1, gx1, x1)
- add(gx1, gx1, params.b)
-
- x2 := new(fe)
- mul(x2, tv[0], x1)
- mul(tv[1], tv[0], tv[1])
-
- gx2 := new(fe)
- mul(gx2, gx1, tv[1])
- e2 := !isQuadraticNonResidue(gx1)
- x, y2 := new(fe), new(fe)
-
- if e2 {
- x.set(x1)
- y2.set(gx1)
- } else {
- x.set(x2)
- y2.set(gx2)
- }
-
- y := new(fe)
- sqrt(y, y2)
-
- if y.sign() != u.sign() {
- neg(y, y)
- }
-
- return x, y
-}
-
-// swuMapG2 is implementation of Simplified Shallue-van de Woestijne-Ulas Method
-// defined at draft-irtf-cfrg-hash-to-curve-06.
-func swuMapG2(e *fp2, u *fe2) (*fe2, *fe2) {
- if e == nil {
- e = newFp2()
- }
-
- params := swuParamsForG2
-
- var tv [4]*fe2
- for i := 0; i < 4; i++ {
- tv[i] = e.new()
- }
- e.square(tv[0], u)
- e.mul(tv[0], tv[0], params.z)
- e.square(tv[1], tv[0])
- x1 := e.new()
- e.add(x1, tv[0], tv[1])
- e.inverse(x1, x1)
- e1 := x1.isZero()
- e.add(x1, x1, e.one())
-
- if e1 {
- x1.set(params.zInv)
- }
-
- e.mul(x1, x1, params.minusBOverA)
- gx1 := e.new()
- e.square(gx1, x1)
- e.add(gx1, gx1, params.a)
- e.mul(gx1, gx1, x1)
- e.add(gx1, gx1, params.b)
- x2 := e.new()
- e.mul(x2, tv[0], x1)
- e.mul(tv[1], tv[0], tv[1])
- gx2 := e.new()
- e.mul(gx2, gx1, tv[1])
- e2 := !e.isQuadraticNonResidue(gx1)
- x, y2 := e.new(), e.new()
-
- if e2 {
- x.set(x1)
- y2.set(gx1)
- } else {
- x.set(x2)
- y2.set(gx2)
- }
-
- y := e.new()
- e.sqrt(y, y2)
-
- if y.sign() != u.sign() {
- e.neg(y, y)
- }
-
- return x, y
-}
-
-var swuParamsForG1 = struct {
- z *fe
- zInv *fe
- a *fe
- b *fe
- minusBOverA *fe
-}{
- a: &fe{0x2f65aa0e9af5aa51, 0x86464c2d1e8416c3, 0xb85ce591b7bd31e2, 0x27e11c91b5f24e7c, 0x28376eda6bfc1835, 0x155455c3e5071d85},
- b: &fe{0xfb996971fe22a1e0, 0x9aa93eb35b742d6f, 0x8c476013de99c5c4, 0x873e27c3a221e571, 0xca72b5e45a52d888, 0x06824061418a386b},
- z: &fe{0x886c00000023ffdc, 0x0f70008d3090001d, 0x77672417ed5828c3, 0x9dac23e943dc1740, 0x50553f1b9c131521, 0x078c712fbe0ab6e8},
- zInv: &fe{0x0e8a2e8ba2e83e10, 0x5b28ba2ca4d745d1, 0x678cd5473847377a, 0x4c506dd8a8076116, 0x9bcb227d79284139, 0x0e8d3154b0ba099a},
- minusBOverA: &fe{0x052583c93555a7fe, 0x3b40d72430f93c82, 0x1b75faa0105ec983, 0x2527e7dc63851767, 0x99fffd1f34fc181d, 0x097cab54770ca0d3},
-}
-
-var swuParamsForG2 = struct {
- z *fe2
- zInv *fe2
- a *fe2
- b *fe2
- minusBOverA *fe2
-}{
- a: &fe2{
- fe{0, 0, 0, 0, 0, 0},
- fe{0xe53a000003135242, 0x01080c0fdef80285, 0xe7889edbe340f6bd, 0x0b51375126310601, 0x02d6985717c744ab, 0x1220b4e979ea5467},
- },
- b: &fe2{
- fe{0x22ea00000cf89db2, 0x6ec832df71380aa4, 0x6e1b94403db5a66e, 0x75bf3c53a79473ba, 0x3dd3a569412c0a34, 0x125cdb5e74dc4fd1},
- fe{0x22ea00000cf89db2, 0x6ec832df71380aa4, 0x6e1b94403db5a66e, 0x75bf3c53a79473ba, 0x3dd3a569412c0a34, 0x125cdb5e74dc4fd1},
- },
- z: &fe2{
- fe{0x87ebfffffff9555c, 0x656fffe5da8ffffa, 0x0fd0749345d33ad2, 0xd951e663066576f4, 0xde291a3d41e980d3, 0x0815664c7dfe040d},
- fe{0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x07e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x040ab3263eff0206},
- },
- zInv: &fe2{
- fe{0xacd0000000011110, 0x9dd9999dc88ccccd, 0xb5ca2ac9b76352bf, 0xf1b574bcf4bc90ce, 0x42dab41f28a77081, 0x132fc6ac14cd1e12},
- fe{0xe396ffffffff2223, 0x4fbf332fcd0d9998, 0x0c4bbd3c1aff4cc4, 0x6b9c91267926ca58, 0x29ae4da6aef7f496, 0x10692e942f195791},
- },
- minusBOverA: &fe2{
- fe{0x903c555555474fb3, 0x5f98cc95ce451105, 0x9f8e582eefe0fade, 0xc68946b6aebbd062, 0x467a4ad10ee6de53, 0x0e7146f483e23a05},
- fe{0x29c2aaaaaab85af8, 0xbf133368e30eeefa, 0xc7a27a7206cffb45, 0x9dee04ce44c9425c, 0x04a15ce53464ce83, 0x0b8fcaf5b59dac95},
- },
-}
diff --git a/crypto/bn256/cloudflare/gfp_decl.go b/crypto/bn256/cloudflare/gfp_decl.go
index cf7f565423..1954d14a4a 100644
--- a/crypto/bn256/cloudflare/gfp_decl.go
+++ b/crypto/bn256/cloudflare/gfp_decl.go
@@ -13,7 +13,7 @@ import (
//nolint:varcheck,unused,deadcode
var hasBMI2 = cpu.X86.HasBMI2
-// go:noescape
+//go:noescape
func gfpNeg(c, a *gfP)
//go:noescape
diff --git a/crypto/bn256/google/bn256.go b/crypto/bn256/google/bn256.go
index dc1c08b41a..b6f25f27e1 100644
--- a/crypto/bn256/google/bn256.go
+++ b/crypto/bn256/google/bn256.go
@@ -29,7 +29,7 @@ import (
)
// BUG(agl): this implementation is not constant time.
-// TODO(agl): keep GF(p²) elements in Mongomery form.
+// TODO(agl): keep GF(p²) elements in Montgomery form.
// G1 is an abstract cyclic group. The zero value is suitable for use as the
// output of an operation, but cannot be used as an input.
@@ -181,7 +181,7 @@ type G2 struct {
p *twistPoint
}
-// RandomG1 returns x and gâ‚‚Ë£ where x is a random, non-zero number read from r.
+// RandomG2 returns x and gâ‚‚Ë£ where x is a random, non-zero number read from r.
func RandomG2(r io.Reader) (*big.Int, *G2, error) {
var k *big.Int
diff --git a/crypto/crypto.go b/crypto/crypto.go
index d8fde83d1d..cce7a5ebe5 100644
--- a/crypto/crypto.go
+++ b/crypto/crypto.go
@@ -305,7 +305,5 @@ func PubkeyToAddress(p ecdsa.PublicKey) common.Address {
}
func zeroBytes(bytes []byte) {
- for i := range bytes {
- bytes[i] = 0
- }
+ clear(bytes)
}
diff --git a/crypto/kzg4844/kzg4844.go b/crypto/kzg4844/kzg4844.go
index 5969d1c2ce..39fdfbe740 100644
--- a/crypto/kzg4844/kzg4844.go
+++ b/crypto/kzg4844/kzg4844.go
@@ -20,21 +20,61 @@ package kzg4844
import (
"embed"
"errors"
+ "hash"
+ "reflect"
"sync/atomic"
+
+ "github.com/ethereum/go-ethereum/common/hexutil"
)
//go:embed trusted_setup.json
var content embed.FS
+var (
+ blobT = reflect.TypeOf(Blob{})
+ commitmentT = reflect.TypeOf(Commitment{})
+ proofT = reflect.TypeOf(Proof{})
+)
+
// Blob represents a 4844 data blob.
type Blob [131072]byte
+// UnmarshalJSON parses a blob in hex syntax.
+func (b *Blob) UnmarshalJSON(input []byte) error {
+ return hexutil.UnmarshalFixedJSON(blobT, input, b[:])
+}
+
+// MarshalText returns the hex representation of b.
+func (b Blob) MarshalText() ([]byte, error) {
+ return hexutil.Bytes(b[:]).MarshalText()
+}
+
// Commitment is a serialized commitment to a polynomial.
type Commitment [48]byte
+// UnmarshalJSON parses a commitment in hex syntax.
+func (c *Commitment) UnmarshalJSON(input []byte) error {
+ return hexutil.UnmarshalFixedJSON(commitmentT, input, c[:])
+}
+
+// MarshalText returns the hex representation of c.
+func (c Commitment) MarshalText() ([]byte, error) {
+ return hexutil.Bytes(c[:]).MarshalText()
+}
+
// Proof is a serialized commitment to the quotient polynomial.
type Proof [48]byte
+// UnmarshalJSON parses a proof in hex syntax.
+func (p *Proof) UnmarshalJSON(input []byte) error {
+ return hexutil.UnmarshalFixedJSON(proofT, input, p[:])
+}
+
+// MarshalText returns the hex representation of p.
+func (p Proof) MarshalText() ([]byte, error) {
+ return hexutil.Bytes(p[:]).MarshalText()
+}
+
// Point is a BLS field element.
type Point [32]byte
@@ -45,7 +85,7 @@ type Claim [32]byte
var useCKZG atomic.Bool
// UseCKZG can be called to switch the default Go implementation of KZG to the C
-// library if fo some reason the user wishes to do so (e.g. consensus bug in one
+// library if for some reason the user wishes to do so (e.g. consensus bug in one
// or the other).
func UseCKZG(use bool) error {
if use && !ckzgAvailable {
@@ -65,7 +105,7 @@ func UseCKZG(use bool) error {
}
// BlobToCommitment creates a small commitment out of a data blob.
-func BlobToCommitment(blob Blob) (Commitment, error) {
+func BlobToCommitment(blob *Blob) (Commitment, error) {
if useCKZG.Load() {
return ckzgBlobToCommitment(blob)
}
@@ -74,7 +114,7 @@ func BlobToCommitment(blob Blob) (Commitment, error) {
// ComputeProof computes the KZG proof at the given point for the polynomial
// represented by the blob.
-func ComputeProof(blob Blob, point Point) (Proof, Claim, error) {
+func ComputeProof(blob *Blob, point Point) (Proof, Claim, error) {
if useCKZG.Load() {
return ckzgComputeProof(blob, point)
}
@@ -94,7 +134,7 @@ func VerifyProof(commitment Commitment, point Point, claim Claim, proof Proof) e
// the commitment.
//
// This method does not verify that the commitment is correct with respect to blob.
-func ComputeBlobProof(blob Blob, commitment Commitment) (Proof, error) {
+func ComputeBlobProof(blob *Blob, commitment Commitment) (Proof, error) {
if useCKZG.Load() {
return ckzgComputeBlobProof(blob, commitment)
}
@@ -102,9 +142,27 @@ func ComputeBlobProof(blob Blob, commitment Commitment) (Proof, error) {
}
// VerifyBlobProof verifies that the blob data corresponds to the provided commitment.
-func VerifyBlobProof(blob Blob, commitment Commitment, proof Proof) error {
+func VerifyBlobProof(blob *Blob, commitment Commitment, proof Proof) error {
if useCKZG.Load() {
return ckzgVerifyBlobProof(blob, commitment, proof)
}
return gokzgVerifyBlobProof(blob, commitment, proof)
}
+
+// CalcBlobHashV1 calculates the 'versioned blob hash' of a commitment.
+// The given hasher must be a sha256 hash instance, otherwise the result will be invalid!
+func CalcBlobHashV1(hasher hash.Hash, commit *Commitment) (vh [32]byte) {
+ if hasher.Size() != 32 {
+ panic("wrong hash size")
+ }
+ hasher.Reset()
+ hasher.Write(commit[:])
+ hasher.Sum(vh[:0])
+ vh[0] = 0x01 // version
+ return vh
+}
+
+// IsValidVersionedHash checks that h is a structurally-valid versioned blob hash.
+func IsValidVersionedHash(h []byte) bool {
+ return len(h) == 32 && h[0] == 0x01
+}
diff --git a/crypto/kzg4844/kzg4844_ckzg_cgo.go b/crypto/kzg4844/kzg4844_ckzg_cgo.go
index 5400285698..11bc451b58 100644
--- a/crypto/kzg4844/kzg4844_ckzg_cgo.go
+++ b/crypto/kzg4844/kzg4844_ckzg_cgo.go
@@ -61,10 +61,10 @@ func ckzgInit() {
}
// ckzgBlobToCommitment creates a small commitment out of a data blob.
-func ckzgBlobToCommitment(blob Blob) (Commitment, error) {
+func ckzgBlobToCommitment(blob *Blob) (Commitment, error) {
ckzgIniter.Do(ckzgInit)
- commitment, err := ckzg4844.BlobToKZGCommitment((ckzg4844.Blob)(blob))
+ commitment, err := ckzg4844.BlobToKZGCommitment((*ckzg4844.Blob)(blob))
if err != nil {
return Commitment{}, err
}
@@ -73,10 +73,10 @@ func ckzgBlobToCommitment(blob Blob) (Commitment, error) {
// ckzgComputeProof computes the KZG proof at the given point for the polynomial
// represented by the blob.
-func ckzgComputeProof(blob Blob, point Point) (Proof, Claim, error) {
+func ckzgComputeProof(blob *Blob, point Point) (Proof, Claim, error) {
ckzgIniter.Do(ckzgInit)
- proof, claim, err := ckzg4844.ComputeKZGProof((ckzg4844.Blob)(blob), (ckzg4844.Bytes32)(point))
+ proof, claim, err := ckzg4844.ComputeKZGProof((*ckzg4844.Blob)(blob), (ckzg4844.Bytes32)(point))
if err != nil {
return Proof{}, Claim{}, err
}
@@ -102,10 +102,10 @@ func ckzgVerifyProof(commitment Commitment, point Point, claim Claim, proof Proo
// the commitment.
//
// This method does not verify that the commitment is correct with respect to blob.
-func ckzgComputeBlobProof(blob Blob, commitment Commitment) (Proof, error) {
+func ckzgComputeBlobProof(blob *Blob, commitment Commitment) (Proof, error) {
ckzgIniter.Do(ckzgInit)
- proof, err := ckzg4844.ComputeBlobKZGProof((ckzg4844.Blob)(blob), (ckzg4844.Bytes48)(commitment))
+ proof, err := ckzg4844.ComputeBlobKZGProof((*ckzg4844.Blob)(blob), (ckzg4844.Bytes48)(commitment))
if err != nil {
return Proof{}, err
}
@@ -113,10 +113,10 @@ func ckzgComputeBlobProof(blob Blob, commitment Commitment) (Proof, error) {
}
// ckzgVerifyBlobProof verifies that the blob data corresponds to the provided commitment.
-func ckzgVerifyBlobProof(blob Blob, commitment Commitment, proof Proof) error {
+func ckzgVerifyBlobProof(blob *Blob, commitment Commitment, proof Proof) error {
ckzgIniter.Do(ckzgInit)
- valid, err := ckzg4844.VerifyBlobKZGProof((ckzg4844.Blob)(blob), (ckzg4844.Bytes48)(commitment), (ckzg4844.Bytes48)(proof))
+ valid, err := ckzg4844.VerifyBlobKZGProof((*ckzg4844.Blob)(blob), (ckzg4844.Bytes48)(commitment), (ckzg4844.Bytes48)(proof))
if err != nil {
return err
}
diff --git a/crypto/kzg4844/kzg4844_ckzg_nocgo.go b/crypto/kzg4844/kzg4844_ckzg_nocgo.go
index ed840c75bb..70a78e80d1 100644
--- a/crypto/kzg4844/kzg4844_ckzg_nocgo.go
+++ b/crypto/kzg4844/kzg4844_ckzg_nocgo.go
@@ -32,13 +32,13 @@ func ckzgInit() {
}
// ckzgBlobToCommitment creates a small commitment out of a data blob.
-func ckzgBlobToCommitment(blob Blob) (Commitment, error) {
+func ckzgBlobToCommitment(blob *Blob) (Commitment, error) {
panic("unsupported platform")
}
// ckzgComputeProof computes the KZG proof at the given point for the polynomial
// represented by the blob.
-func ckzgComputeProof(blob Blob, point Point) (Proof, Claim, error) {
+func ckzgComputeProof(blob *Blob, point Point) (Proof, Claim, error) {
panic("unsupported platform")
}
@@ -52,11 +52,11 @@ func ckzgVerifyProof(commitment Commitment, point Point, claim Claim, proof Proo
// the commitment.
//
// This method does not verify that the commitment is correct with respect to blob.
-func ckzgComputeBlobProof(blob Blob, commitment Commitment) (Proof, error) {
+func ckzgComputeBlobProof(blob *Blob, commitment Commitment) (Proof, error) {
panic("unsupported platform")
}
// ckzgVerifyBlobProof verifies that the blob data corresponds to the provided commitment.
-func ckzgVerifyBlobProof(blob Blob, commitment Commitment, proof Proof) error {
+func ckzgVerifyBlobProof(blob *Blob, commitment Commitment, proof Proof) error {
panic("unsupported platform")
}
diff --git a/crypto/kzg4844/kzg4844_gokzg.go b/crypto/kzg4844/kzg4844_gokzg.go
index 3f03bb5273..b4af9b1671 100644
--- a/crypto/kzg4844/kzg4844_gokzg.go
+++ b/crypto/kzg4844/kzg4844_gokzg.go
@@ -46,10 +46,10 @@ func gokzgInit() {
}
// gokzgBlobToCommitment creates a small commitment out of a data blob.
-func gokzgBlobToCommitment(blob Blob) (Commitment, error) {
+func gokzgBlobToCommitment(blob *Blob) (Commitment, error) {
gokzgIniter.Do(gokzgInit)
- commitment, err := context.BlobToKZGCommitment((gokzg4844.Blob)(blob), 0)
+ commitment, err := context.BlobToKZGCommitment((*gokzg4844.Blob)(blob), 0)
if err != nil {
return Commitment{}, err
}
@@ -58,10 +58,10 @@ func gokzgBlobToCommitment(blob Blob) (Commitment, error) {
// gokzgComputeProof computes the KZG proof at the given point for the polynomial
// represented by the blob.
-func gokzgComputeProof(blob Blob, point Point) (Proof, Claim, error) {
+func gokzgComputeProof(blob *Blob, point Point) (Proof, Claim, error) {
gokzgIniter.Do(gokzgInit)
- proof, claim, err := context.ComputeKZGProof((gokzg4844.Blob)(blob), (gokzg4844.Scalar)(point), 0)
+ proof, claim, err := context.ComputeKZGProof((*gokzg4844.Blob)(blob), (gokzg4844.Scalar)(point), 0)
if err != nil {
return Proof{}, Claim{}, err
}
@@ -80,10 +80,10 @@ func gokzgVerifyProof(commitment Commitment, point Point, claim Claim, proof Pro
// the commitment.
//
// This method does not verify that the commitment is correct with respect to blob.
-func gokzgComputeBlobProof(blob Blob, commitment Commitment) (Proof, error) {
+func gokzgComputeBlobProof(blob *Blob, commitment Commitment) (Proof, error) {
gokzgIniter.Do(gokzgInit)
- proof, err := context.ComputeBlobKZGProof((gokzg4844.Blob)(blob), (gokzg4844.KZGCommitment)(commitment), 0)
+ proof, err := context.ComputeBlobKZGProof((*gokzg4844.Blob)(blob), (gokzg4844.KZGCommitment)(commitment), 0)
if err != nil {
return Proof{}, err
}
@@ -91,8 +91,8 @@ func gokzgComputeBlobProof(blob Blob, commitment Commitment) (Proof, error) {
}
// gokzgVerifyBlobProof verifies that the blob data corresponds to the provided commitment.
-func gokzgVerifyBlobProof(blob Blob, commitment Commitment, proof Proof) error {
+func gokzgVerifyBlobProof(blob *Blob, commitment Commitment, proof Proof) error {
gokzgIniter.Do(gokzgInit)
- return context.VerifyBlobKZGProof((gokzg4844.Blob)(blob), (gokzg4844.KZGCommitment)(commitment), (gokzg4844.KZGProof)(proof))
+ return context.VerifyBlobKZGProof((*gokzg4844.Blob)(blob), (gokzg4844.KZGCommitment)(commitment), (gokzg4844.KZGProof)(proof))
}
diff --git a/crypto/kzg4844/kzg4844_test.go b/crypto/kzg4844/kzg4844_test.go
index 28f572f1e4..ba2dd7480a 100644
--- a/crypto/kzg4844/kzg4844_test.go
+++ b/crypto/kzg4844/kzg4844_test.go
@@ -36,13 +36,13 @@ func randFieldElement() [32]byte {
return gokzg4844.SerializeScalar(r)
}
-func randBlob() Blob {
+func randBlob() *Blob {
var blob Blob
for i := 0; i < len(blob); i += gokzg4844.SerializedScalarSize {
fieldElementBytes := randFieldElement()
copy(blob[i:i+gokzg4844.SerializedScalarSize], fieldElementBytes[:])
}
- return blob
+ return &blob
}
func TestCKZGWithPoint(t *testing.T) { testKZGWithPoint(t, true) }
diff --git a/crypto/secp256k1/curve.go b/crypto/secp256k1/curve.go
index bdedf06b8c..705d387ddf 100644
--- a/crypto/secp256k1/curve.go
+++ b/crypto/secp256k1/curve.go
@@ -79,53 +79,52 @@ type BitCurve struct {
BitSize int // the size of the underlying field
}
-func (BitCurve *BitCurve) Params() *elliptic.CurveParams {
+func (bitCurve *BitCurve) Params() *elliptic.CurveParams {
return &elliptic.CurveParams{
- P: BitCurve.P,
- N: BitCurve.N,
- B: BitCurve.B,
- Gx: BitCurve.Gx,
- Gy: BitCurve.Gy,
- BitSize: BitCurve.BitSize,
+ P: bitCurve.P,
+ N: bitCurve.N,
+ B: bitCurve.B,
+ Gx: bitCurve.Gx,
+ Gy: bitCurve.Gy,
+ BitSize: bitCurve.BitSize,
}
}
// IsOnCurve returns true if the given (x,y) lies on the BitCurve.
-func (BitCurve *BitCurve) IsOnCurve(x, y *big.Int) bool {
+func (bitCurve *BitCurve) IsOnCurve(x, y *big.Int) bool {
// y² = x³ + b
y2 := new(big.Int).Mul(y, y) //y²
- y2.Mod(y2, BitCurve.P) //y²%P
+ y2.Mod(y2, bitCurve.P) //y²%P
x3 := new(big.Int).Mul(x, x) //x²
x3.Mul(x3, x) //x³
- x3.Add(x3, BitCurve.B) //x³+B
- x3.Mod(x3, BitCurve.P) //(x³+B)%P
+ x3.Add(x3, bitCurve.B) //x³+B
+ x3.Mod(x3, bitCurve.P) //(x³+B)%P
return x3.Cmp(y2) == 0
}
// affineFromJacobian reverses the Jacobian transform. See the comment at the
// top of the file.
-func (BitCurve *BitCurve) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) {
+func (bitCurve *BitCurve) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) {
if z.Sign() == 0 {
return new(big.Int), new(big.Int)
}
- zinv := new(big.Int).ModInverse(z, BitCurve.P)
+ zinv := new(big.Int).ModInverse(z, bitCurve.P)
zinvsq := new(big.Int).Mul(zinv, zinv)
xOut = new(big.Int).Mul(x, zinvsq)
- xOut.Mod(xOut, BitCurve.P)
+ xOut.Mod(xOut, bitCurve.P)
zinvsq.Mul(zinvsq, zinv)
yOut = new(big.Int).Mul(y, zinvsq)
- yOut.Mod(yOut, BitCurve.P)
-
+ yOut.Mod(yOut, bitCurve.P)
return
}
// Add returns the sum of (x1,y1) and (x2,y2)
-func (BitCurve *BitCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
+func (bitCurve *BitCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
// If one point is at infinity, return the other point.
// Adding the point at infinity to any point will preserve the other point.
if x1.Sign() == 0 && y1.Sign() == 0 {
@@ -138,31 +137,27 @@ func (BitCurve *BitCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
z := new(big.Int).SetInt64(1)
if x1.Cmp(x2) == 0 && y1.Cmp(y2) == 0 {
- return BitCurve.affineFromJacobian(BitCurve.doubleJacobian(x1, y1, z))
+ return bitCurve.affineFromJacobian(bitCurve.doubleJacobian(x1, y1, z))
}
-
- return BitCurve.affineFromJacobian(BitCurve.addJacobian(x1, y1, z, x2, y2, z))
+ return bitCurve.affineFromJacobian(bitCurve.addJacobian(x1, y1, z, x2, y2, z))
}
// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and
// (x2, y2, z2) and returns their sum, also in Jacobian form.
-func (BitCurve *BitCurve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) {
+func (bitCurve *BitCurve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) {
// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
z1z1 := new(big.Int).Mul(z1, z1)
- z1z1.Mod(z1z1, BitCurve.P)
-
+ z1z1.Mod(z1z1, bitCurve.P)
z2z2 := new(big.Int).Mul(z2, z2)
- z2z2.Mod(z2z2, BitCurve.P)
+ z2z2.Mod(z2z2, bitCurve.P)
u1 := new(big.Int).Mul(x1, z2z2)
- u1.Mod(u1, BitCurve.P)
-
+ u1.Mod(u1, bitCurve.P)
u2 := new(big.Int).Mul(x2, z1z1)
- u2.Mod(u2, BitCurve.P)
-
+ u2.Mod(u2, bitCurve.P)
h := new(big.Int).Sub(u2, u1)
if h.Sign() == -1 {
- h.Add(h, BitCurve.P)
+ h.Add(h, bitCurve.P)
}
i := new(big.Int).Lsh(h, 1)
@@ -171,15 +166,13 @@ func (BitCurve *BitCurve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
s1 := new(big.Int).Mul(y1, z2)
s1.Mul(s1, z2z2)
- s1.Mod(s1, BitCurve.P)
-
+ s1.Mod(s1, bitCurve.P)
s2 := new(big.Int).Mul(y2, z1)
s2.Mul(s2, z1z1)
- s2.Mod(s2, BitCurve.P)
-
+ s2.Mod(s2, bitCurve.P)
r := new(big.Int).Sub(s2, s1)
if r.Sign() == -1 {
- r.Add(r, BitCurve.P)
+ r.Add(r, bitCurve.P)
}
r.Lsh(r, 1)
@@ -191,7 +184,7 @@ func (BitCurve *BitCurve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
x3.Sub(x3, j)
x3.Sub(x3, v)
x3.Sub(x3, v)
- x3.Mod(x3, BitCurve.P)
+ x3.Mod(x3, bitCurve.P)
y3 := new(big.Int).Set(r)
@@ -200,37 +193,37 @@ func (BitCurve *BitCurve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
s1.Mul(s1, j)
s1.Lsh(s1, 1)
y3.Sub(y3, s1)
- y3.Mod(y3, BitCurve.P)
+ y3.Mod(y3, bitCurve.P)
z3 := new(big.Int).Add(z1, z2)
z3.Mul(z3, z3)
z3.Sub(z3, z1z1)
if z3.Sign() == -1 {
- z3.Add(z3, BitCurve.P)
+ z3.Add(z3, bitCurve.P)
}
z3.Sub(z3, z2z2)
if z3.Sign() == -1 {
- z3.Add(z3, BitCurve.P)
+ z3.Add(z3, bitCurve.P)
}
z3.Mul(z3, h)
- z3.Mod(z3, BitCurve.P)
+ z3.Mod(z3, bitCurve.P)
return x3, y3, z3
}
// Double returns 2*(x,y)
-func (BitCurve *BitCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
+func (bitCurve *BitCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
z1 := new(big.Int).SetInt64(1)
- return BitCurve.affineFromJacobian(BitCurve.doubleJacobian(x1, y1, z1))
+ return bitCurve.affineFromJacobian(bitCurve.doubleJacobian(x1, y1, z1))
}
// doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and
// returns its double, also in Jacobian form.
-func (BitCurve *BitCurve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) {
+func (bitCurve *BitCurve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) {
// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
a := new(big.Int).Mul(x, x) //X1²
b := new(big.Int).Mul(y, y) //Y1²
@@ -247,30 +240,30 @@ func (BitCurve *BitCurve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int,
x3 := new(big.Int).Mul(big.NewInt(2), d) //2*D
x3.Sub(f, x3) //F-2*D
- x3.Mod(x3, BitCurve.P)
+ x3.Mod(x3, bitCurve.P)
y3 := new(big.Int).Sub(d, x3) //D-X3
y3.Mul(e, y3) //E*(D-X3)
y3.Sub(y3, new(big.Int).Mul(big.NewInt(8), c)) //E*(D-X3)-8*C
- y3.Mod(y3, BitCurve.P)
+ y3.Mod(y3, bitCurve.P)
z3 := new(big.Int).Mul(y, z) //Y1*Z1
z3.Mul(big.NewInt(2), z3) //3*Y1*Z1
- z3.Mod(z3, BitCurve.P)
+ z3.Mod(z3, bitCurve.P)
return x3, y3, z3
}
// ScalarBaseMult returns k*G, where G is the base point of the group and k is
// an integer in big-endian form.
-func (BitCurve *BitCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
- return BitCurve.ScalarMult(BitCurve.Gx, BitCurve.Gy, k)
+func (bitCurve *BitCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
+ return bitCurve.ScalarMult(bitCurve.Gx, bitCurve.Gy, k)
}
// Marshal converts a point into the form specified in section 4.3.6 of ANSI
// X9.62.
-func (BitCurve *BitCurve) Marshal(x, y *big.Int) []byte {
- byteLen := (BitCurve.BitSize + 7) >> 3
+func (bitCurve *BitCurve) Marshal(x, y *big.Int) []byte {
+ byteLen := (bitCurve.BitSize + 7) >> 3
ret := make([]byte, 1+2*byteLen)
ret[0] = 4 // uncompressed point flag
readBits(x, ret[1:1+byteLen])
@@ -281,8 +274,8 @@ func (BitCurve *BitCurve) Marshal(x, y *big.Int) []byte {
// Unmarshal converts a point, serialised by Marshal, into an x, y pair. On
// error, x = nil.
-func (BitCurve *BitCurve) Unmarshal(data []byte) (x, y *big.Int) {
- byteLen := (BitCurve.BitSize + 7) >> 3
+func (bitCurve *BitCurve) Unmarshal(data []byte) (x, y *big.Int) {
+ byteLen := (bitCurve.BitSize + 7) >> 3
if len(data) != 1+2*byteLen {
return
}
diff --git a/crypto/secp256k1/libsecp256k1/include/secp256k1.h b/crypto/secp256k1/libsecp256k1/include/secp256k1.h
index f268e309d0..76af839691 100644
--- a/crypto/secp256k1/libsecp256k1/include/secp256k1.h
+++ b/crypto/secp256k1/libsecp256k1/include/secp256k1.h
@@ -357,7 +357,7 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
/** Verify an ECDSA signature.
*
* Returns: 1: correct signature
- * 0: incorrect or unparseable signature
+ * 0: incorrect or unparsable signature
* Args: ctx: a secp256k1 context object, initialized for verification.
* In: sig: the signature being verified (cannot be NULL)
* msg32: the 32-byte message hash being verified (cannot be NULL)
diff --git a/crypto/secp256k1/libsecp256k1/sage/group_prover.sage b/crypto/secp256k1/libsecp256k1/sage/group_prover.sage
index ab580c5b23..68882e9365 100644
--- a/crypto/secp256k1/libsecp256k1/sage/group_prover.sage
+++ b/crypto/secp256k1/libsecp256k1/sage/group_prover.sage
@@ -17,7 +17,7 @@
# - A constraint describing the requirements of the law, called "require"
# * Implementations are transliterated into functions that operate as well on
# algebraic input points, and are called once per combination of branches
-# exectured. Each execution returns:
+# executed. Each execution returns:
# - A constraint describing the assumptions this implementation requires
# (such as Z1=1), called "assumeFormula"
# - A constraint describing the assumptions this specific branch requires,
diff --git a/crypto/secp256k1/scalar_mult_cgo.go b/crypto/secp256k1/scalar_mult_cgo.go
index 8afa9d023b..d11c11faf8 100644
--- a/crypto/secp256k1/scalar_mult_cgo.go
+++ b/crypto/secp256k1/scalar_mult_cgo.go
@@ -21,7 +21,7 @@ extern int secp256k1_ext_scalar_mul(const secp256k1_context* ctx, const unsigned
*/
import "C"
-func (BitCurve *BitCurve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
+func (bitCurve *BitCurve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
// Ensure scalar is exactly 32 bytes. We pad always, even if
// scalar is 32 bytes long, to avoid a timing side channel.
if len(scalar) > 32 {
@@ -44,12 +44,8 @@ func (BitCurve *BitCurve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int,
// Unpack the result and clear temporaries.
x := new(big.Int).SetBytes(point[:32])
y := new(big.Int).SetBytes(point[32:])
- for i := range point {
- point[i] = 0
- }
- for i := range padded {
- scalar[i] = 0
- }
+ clear(point)
+ clear(scalar)
if res != 1 {
return nil, nil
}
diff --git a/crypto/secp256k1/scalar_mult_nocgo.go b/crypto/secp256k1/scalar_mult_nocgo.go
index 22f53ac6ae..feb13a8dfd 100644
--- a/crypto/secp256k1/scalar_mult_nocgo.go
+++ b/crypto/secp256k1/scalar_mult_nocgo.go
@@ -9,6 +9,6 @@ package secp256k1
import "math/big"
-func (BitCurve *BitCurve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
+func (bitCurve *BitCurve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
panic("ScalarMult is not available when secp256k1 is built without cgo")
}
diff --git a/crypto/secp256k1/secp256_test.go b/crypto/secp256k1/secp256_test.go
index 78d3ce9df3..c8775fb925 100644
--- a/crypto/secp256k1/secp256_test.go
+++ b/crypto/secp256k1/secp256_test.go
@@ -50,7 +50,7 @@ func randSig() []byte {
}
// tests for malleability
-// highest bit of signature ECDSA s value must be 0, in the 33th byte
+// the highest bit of signature ECDSA s value must be 0, in the 33th byte
func compactSigCheck(t *testing.T, sig []byte) {
var b = int(sig[32])
if b < 0 {
diff --git a/crypto/signature_nocgo.go b/crypto/signature_nocgo.go
index f70617019e..989057442b 100644
--- a/crypto/signature_nocgo.go
+++ b/crypto/signature_nocgo.go
@@ -167,7 +167,7 @@ type btCurve struct {
*btcec.KoblitzCurve
}
-// Marshall converts a point given as (x, y) into a byte slice.
+// Marshal converts a point given as (x, y) into a byte slice.
func (curve btCurve) Marshal(x, y *big.Int) []byte {
byteLen := (curve.Params().BitSize + 7) / 8
diff --git a/crypto/signature_test.go b/crypto/signature_test.go
index a8383fe87d..437669f114 100644
--- a/crypto/signature_test.go
+++ b/crypto/signature_test.go
@@ -79,7 +79,7 @@ func TestVerifySignature(t *testing.T) {
wrongkey[10]++
if VerifySignature(wrongkey, testmsg, sig) {
- t.Errorf("signature valid with with wrong public key")
+ t.Errorf("signature valid with wrong public key")
}
}
diff --git a/crypto/signify/signify_fuzz.go b/crypto/signify/signify_fuzz.go
index 457af044d1..239a2134df 100644
--- a/crypto/signify/signify_fuzz.go
+++ b/crypto/signify/signify_fuzz.go
@@ -134,6 +134,7 @@ func createKeyPair() (string, string) {
defer os.Remove(tmpKey.Name())
defer os.Remove(tmpKey.Name() + ".pub")
defer os.Remove(tmpKey.Name() + ".sec")
+ defer tmpKey.Close()
cmd := exec.Command("signify", "-G", "-n", "-p", tmpKey.Name()+".pub", "-s", tmpKey.Name()+".sec")
if output, err := cmd.CombinedOutput(); err != nil {
panic(fmt.Sprintf("could not verify the file: %v, output: \n%s", err, output))
diff --git a/docs/cli/example_config.toml b/docs/cli/example_config.toml
index 21705db055..ea869925c4 100644
--- a/docs/cli/example_config.toml
+++ b/docs/cli/example_config.toml
@@ -61,7 +61,7 @@ devfakeauthor = false # Run miner without validator set authorization
nolocals = false # Disables price exemptions for locally submitted transactions
journal = "transactions.rlp" # Disk journal for local transaction to survive node restarts
rejournal = "1h0m0s" # Time interval to regenerate the local transaction journal
- pricelimit = 30000000000 # Minimum gas price limit to enforce for acceptance into the pool. Regardless the value set, it will be enforced to 30000000000 in bor.
+ pricelimit = 25000000000 # Minimum gas price limit to enforce for acceptance into the pool. Regardless the value set, it will be enforced to 25000000000 for all networks
pricebump = 10 # Price bump percentage to replace an already existing transaction
accountslots = 16 # Minimum number of executable transaction slots guaranteed per account
globalslots = 32768 # Maximum number of executable transaction slots for all accounts
@@ -74,7 +74,7 @@ devfakeauthor = false # Run miner without validator set authorization
etherbase = "" # Public address for block mining rewards
extradata = "" # Block extra data set by the miner (default = client version)
gaslimit = 30000000 # Target gas ceiling for mined blocks
- gasprice = "30000000000" # Minimum gas price for mining a transaction. Regardless the value set, it will be enforced to 30000000000 in bor, default suitable for amoy/mumbai/devnet.
+ gasprice = "25000000000" # Minimum gas price for mining a transaction. Regardless the value set, it will be enforced to 25000000000 for all networks
recommit = "2m5s" # The time interval for miner to re-create mining work
commitinterrupt = true # Interrupt the current mining work when time is exceeded and create partial blocks
@@ -128,7 +128,7 @@ devfakeauthor = false # Run miner without validator set authorization
maxheaderhistory = 1024 # Maximum header history of gasprice oracle
maxblockhistory = 1024 # Maximum block history of gasprice oracle
maxprice = "5000000000000" # Maximum gas price will be recommended by gpo
- ignoreprice = "2" # Gas price below which gpo will ignore transactions (recommended for mainnet = 30000000000, default suitable for amoy/mumbai/devnet)
+ ignoreprice = "25000000000" # Gas price below which gpo will ignore transactions. Regardless the value set, it will be enforced to 25000000000 for all networks
[telemetry]
metrics = false # Enable metrics collection and reporting
diff --git a/docs/cli/server.md b/docs/cli/server.md
index fc04f12022..adeacd731a 100644
--- a/docs/cli/server.md
+++ b/docs/cli/server.md
@@ -46,7 +46,7 @@ The ```bor server``` command runs the Bor client.
- ```gpo.blocks```: Number of recent blocks to check for gas prices (default: 20)
-- ```gpo.ignoreprice```: Gas price below which gpo will ignore transactions (default: 30000000000). It's set to 30gwei in bor
+- ```gpo.ignoreprice```: Gas price below which gpo will ignore transactions (default: 25000000000)
- ```gpo.maxblockhistory```: Maximum block history of gasprice oracle (default: 1024)
@@ -218,6 +218,8 @@ The ```bor server``` command runs the Bor client.
- ```bootnodes```: Comma separated enode URLs for P2P discovery bootstrap
+- ```discovery.dns```: Comma separated list of enrtree:// URLs which will be queried for nodes to connect to
+
- ```maxpeers```: Maximum number of network peers (network disabled if set to 0) (default: 50)
- ```maxpendpeers```: Maximum number of pending connection attempts (default: 50)
@@ -250,7 +252,7 @@ The ```bor server``` command runs the Bor client.
- ```miner.gaslimit```: Target gas ceiling (gas limit) for mined blocks (default: 30000000)
-- ```miner.gasprice```: Minimum gas price for mining a transaction (default: 30000000000). It's set to 30gwei in bor
+- ```miner.gasprice```: Minimum gas price for mining a transaction (default: 25000000000)
- ```miner.interruptcommit```: Interrupt block commit when block creation time is passed (default: true)
@@ -306,6 +308,6 @@ The ```bor server``` command runs the Bor client.
- ```txpool.pricebump```: Price bump percentage to replace an already existing transaction (default: 10)
-- ```txpool.pricelimit```: Minimum gas price limit to enforce the acceptance of txs into the pool (default: 30000000000). It's set to 30gwei in bor
+- ```txpool.pricelimit```: Minimum gas price limit to enforce for acceptance into the pool (default: 25000000000)
- ```txpool.rejournal```: Time interval to regenerate the local transaction journal (default: 1h0m0s)
\ No newline at end of file
diff --git a/docs/postmortems/2021-08-22-split-postmortem.md b/docs/postmortems/2021-08-22-split-postmortem.md
index 962aa51f64..0986f00b65 100644
--- a/docs/postmortems/2021-08-22-split-postmortem.md
+++ b/docs/postmortems/2021-08-22-split-postmortem.md
@@ -87,7 +87,7 @@ The blocks on the 'bad' chain were investigated, and Tim Beiko reached out to th
### Disclosure decision
-The geth-team have an official policy regarding [vulnerability disclosure](https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities).
+The geth-team have an official policy regarding [vulnerability disclosure](https://geth.ethereum.org/docs/developers/geth-developer/disclosures).
> The primary goal for the Geth team is the health of the Ethereum network as a whole, and the decision whether or not to publish details about a serious vulnerability boils down to minimizing the risk and/or impact of discovery and exploitation.
diff --git a/eth/api_backend.go b/eth/api_backend.go
index c71db480b3..612571845c 100644
--- a/eth/api_backend.go
+++ b/eth/api_backend.go
@@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
+ "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/rawdb"
@@ -154,13 +155,13 @@ func (b *EthAPIBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumbe
}
if number == rpc.SafeBlockNumber {
- if !b.eth.Merger().TDDReached() {
- return nil, errors.New("'safe' tag not supported on pre-merge network")
- }
-
header := b.eth.blockchain.CurrentSafeBlock()
- return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil
+ if header == nil {
+ return nil, errors.New("safe block not found")
+ } else {
+ return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil
+ }
}
return b.eth.blockchain.GetBlockByNumber(uint64(number)), nil
@@ -209,14 +210,14 @@ func (b *EthAPIBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash r
return nil, errors.New("invalid arguments; neither block nor hash specified")
}
-func (b *EthAPIBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) {
- return b.eth.miner.PendingBlockAndReceipts()
+func (b *EthAPIBackend) Pending() (*types.Block, types.Receipts, *state.StateDB) {
+ return b.eth.miner.Pending()
}
func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
// Pending state is only known by the miner
if number == rpc.PendingBlockNumber {
- block, state := b.eth.miner.Pending()
+ block, _, state := b.eth.miner.Pending()
if block == nil || state == nil {
return nil, nil, errors.New("pending state is not available")
}
@@ -296,7 +297,7 @@ func (b *EthAPIBackend) GetEVM(ctx context.Context, msg *core.Message, state *st
} else {
context = core.NewEVMBlockContext(header, b.eth.BlockChain(), nil)
}
- return vm.NewEVM(context, txContext, state, b.eth.blockchain.Config(), *vmConfig)
+ return vm.NewEVM(context, txContext, state, b.ChainConfig(), *vmConfig)
}
func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
@@ -328,7 +329,7 @@ func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction)
}
func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) {
- pending := b.eth.txPool.Pending(false)
+ pending := b.eth.txPool.Pending(txpool.PendingFilter{})
var txs types.Transactions
@@ -347,9 +348,25 @@ func (b *EthAPIBackend) GetPoolTransaction(hash common.Hash) *types.Transaction
return b.eth.txPool.Get(hash)
}
-func (b *EthAPIBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
- tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.eth.ChainDb(), txHash)
- return tx, blockHash, blockNumber, index, nil
+// GetTransaction retrieves the lookup along with the transaction itself associate
+// with the given transaction hash.
+//
+// An error will be returned if the transaction is not found, and background
+// indexing for transactions is still in progress. The error is used to indicate the
+// scenario explicitly that the transaction might be reachable shortly.
+//
+// A null will be returned in the transaction is not found and background transaction
+// indexing is already finished. The transaction is not existent from the perspective
+// of node.
+func (b *EthAPIBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
+ lookup, tx, err := b.eth.blockchain.GetTransactionLookup(txHash)
+ if err != nil {
+ return false, nil, common.Hash{}, 0, 0, err
+ }
+ if lookup == nil || tx == nil {
+ return false, nil, common.Hash{}, 0, 0, nil
+ }
+ return true, tx, lookup.BlockHash, lookup.BlockIndex, lookup.Index, nil
}
func (b *EthAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
@@ -377,17 +394,29 @@ func (b *EthAPIBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.S
}
func (b *EthAPIBackend) SyncProgress() ethereum.SyncProgress {
- return b.eth.Downloader().Progress()
+ prog := b.eth.Downloader().Progress()
+ if txProg, err := b.eth.blockchain.TxIndexProgress(); err == nil {
+ prog.TxIndexFinishedBlocks = txProg.Indexed
+ prog.TxIndexRemainingBlocks = txProg.Remaining
+ }
+ return prog
}
func (b *EthAPIBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
return b.gpo.SuggestTipCap(ctx)
}
-func (b *EthAPIBackend) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (firstBlock *big.Int, reward [][]*big.Int, baseFee []*big.Int, gasUsedRatio []float64, err error) {
+func (b *EthAPIBackend) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (firstBlock *big.Int, reward [][]*big.Int, baseFee []*big.Int, gasUsedRatio []float64, baseFeePerBlobGas []*big.Int, blobGasUsedRatio []float64, err error) {
return b.gpo.FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles)
}
+func (b *EthAPIBackend) BlobBaseFee(ctx context.Context) *big.Int {
+ if excess := b.CurrentHeader().ExcessBlobGas; excess != nil {
+ return eip4844.CalcBlobFee(*excess)
+ }
+ return nil
+}
+
func (b *EthAPIBackend) ChainDb() ethdb.Database {
return b.eth.ChainDb()
}
@@ -455,7 +484,7 @@ func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, re
return b.eth.stateAtBlock(ctx, block, reexec, base, readOnly, preferDisk)
}
-func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) {
+func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) {
return b.eth.stateAtTransaction(ctx, block, txIndex, reexec)
}
diff --git a/eth/api_debug.go b/eth/api_debug.go
index 2052d880e6..aff2af50d3 100644
--- a/eth/api_debug.go
+++ b/eth/api_debug.go
@@ -56,7 +56,7 @@ func (api *DebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) {
// If we're dumping the pending state, we need to request
// both the pending block as well as the pending state from
// the miner and operate on those
- _, stateDb := api.eth.miner.Pending()
+ _, _, stateDb := api.eth.miner.Pending()
if stateDb == nil {
return state.Dump{}, errors.New("pending state is not available")
}
@@ -142,7 +142,7 @@ func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hex
// If we're dumping the pending state, we need to request
// both the pending block as well as the pending state from
// the miner and operate on those
- _, stateDb = api.eth.miner.Pending()
+ _, _, stateDb = api.eth.miner.Pending()
if stateDb == nil {
return state.Dump{}, errors.New("pending state is not available")
}
diff --git a/eth/api_debug_test.go b/eth/api_debug_test.go
index 4ccda71def..b7b5db0a73 100644
--- a/eth/api_debug_test.go
+++ b/eth/api_debug_test.go
@@ -19,8 +19,8 @@ package eth
import (
"bytes"
"fmt"
- "math/big"
"reflect"
+ "slices"
"strings"
"testing"
@@ -28,10 +28,11 @@ import (
"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/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/trie"
- "golang.org/x/exp/slices"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/holiman/uint256"
)
var dumper = spew.ConfigState{Indent: " "}
@@ -64,7 +65,7 @@ func TestAccountRange(t *testing.T) {
t.Parallel()
var (
- statedb = state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &trie.Config{Preimages: true})
+ statedb = state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &triedb.Config{Preimages: true})
sdb, _ = state.New(types.EmptyRootHash, statedb, nil)
addrs = [AccountRangeMaxResults * 2]common.Address{}
m = map[common.Address]bool{}
@@ -74,7 +75,7 @@ func TestAccountRange(t *testing.T) {
hash := common.HexToHash(fmt.Sprintf("%x", i))
addr := common.BytesToAddress(crypto.Keccak256Hash(hash.Bytes()).Bytes())
addrs[i] = addr
- sdb.SetBalance(addrs[i], big.NewInt(1))
+ sdb.SetBalance(addrs[i], uint256.NewInt(1), tracing.BalanceChangeUnspecified)
if _, ok := m[addr]; ok {
t.Fatalf("bad")
} else {
@@ -162,7 +163,7 @@ func TestStorageRangeAt(t *testing.T) {
// Create a state where account 0x010000... has a few storage entries.
var (
- db = state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &trie.Config{Preimages: true})
+ db = state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), &triedb.Config{Preimages: true})
sdb, _ = state.New(types.EmptyRootHash, db, nil)
addr = common.Address{0x01}
keys = []common.Hash{ // hashes of Keys of storage
diff --git a/eth/api_miner.go b/eth/api_miner.go
index 2fe296548a..8c96f4c54a 100644
--- a/eth/api_miner.go
+++ b/eth/api_miner.go
@@ -18,9 +18,7 @@ package eth
import (
"math/big"
- "time"
- "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)
@@ -29,26 +27,11 @@ type MinerAPI struct {
e *Ethereum
}
-// NewMinerAPI create a new MinerAPI instance.
+// NewMinerAPI creates a new MinerAPI instance.
func NewMinerAPI(e *Ethereum) *MinerAPI {
return &MinerAPI{e}
}
-// Start starts the miner with the given number of threads. If threads is nil,
-// the number of workers started is equal to the number of logical CPUs that are
-// usable by this process. If mining is already running, this method adjust the
-// number of threads allowed to use and updates the minimum price required by the
-// transaction pool.
-func (api *MinerAPI) Start() error {
- return api.e.StartMining()
-}
-
-// Stop terminates the miner, both at the consensus engine level as well as at
-// the block creation level.
-func (api *MinerAPI) Stop() {
- api.e.StopMining()
-}
-
// SetExtra sets the extra data string that is included when this miner mines a block.
func (api *MinerAPI) SetExtra(extra string) (bool, error) {
if err := api.e.Miner().SetExtra([]byte(extra)); err != nil {
@@ -73,14 +56,3 @@ func (api *MinerAPI) SetGasLimit(gasLimit hexutil.Uint64) bool {
api.e.Miner().SetGasCeil(uint64(gasLimit))
return true
}
-
-// SetEtherbase sets the etherbase of the miner.
-func (api *MinerAPI) SetEtherbase(etherbase common.Address) bool {
- api.e.SetEtherbase(etherbase)
- return true
-}
-
-// SetRecommitInterval updates the interval for miner sealing work recommitting.
-func (api *MinerAPI) SetRecommitInterval(interval int) {
- api.e.Miner().SetRecommitInterval(time.Duration(interval) * time.Millisecond)
-}
diff --git a/eth/backend.go b/eth/backend.go
index 627e39d1f0..818d45cb73 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -19,6 +19,7 @@ package eth
import (
"context"
+ "encoding/json"
"errors"
"fmt"
"math/big"
@@ -49,6 +50,7 @@ import (
"github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/eth/protocols/snap"
+ "github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/internal/ethapi"
@@ -62,7 +64,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
// Config contains the configuration options of the ETH protocol.
@@ -80,7 +82,6 @@ type Ethereum struct {
handler *handler
ethDialCandidates enode.Iterator
snapDialCandidates enode.Iterator
- merger *consensus.Merger
// DB interfaces
chainDb ethdb.Database // Block chain database
@@ -112,21 +113,20 @@ type Ethereum struct {
shutdownTracker *shutdowncheck.ShutdownTracker // Tracks if and when the node has shutdown ungracefully
}
-// New creates a new Ethereum object (including the
-// initialisation of the common Ethereum object)
+// New creates a new Ethereum object (including the initialisation of the common Ethereum object),
+// whose lifecycle will be managed by the provided node.
func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
// Ensure configuration values are compatible and sane
- if config.SyncMode == downloader.LightSync {
- return nil, errors.New("can't run eth.Ethereum in light sync mode, light mode has been deprecated")
- }
if !config.SyncMode.IsValid() {
return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode)
}
- // enforce minimum gas price of 30 gwei in bor
+
+ // PIP-35: Enforce min gas price to 25 gwei
if config.Miner.GasPrice == nil || config.Miner.GasPrice.Cmp(big.NewInt(params.BorDefaultMinerGasPrice)) != 0 {
log.Warn("Sanitizing invalid miner gas price", "provided", config.Miner.GasPrice, "updated", ethconfig.Defaults.Miner.GasPrice)
- config.Miner.GasPrice = new(big.Int).Set(ethconfig.Defaults.Miner.GasPrice)
+ config.Miner.GasPrice = ethconfig.Defaults.Miner.GasPrice
}
+
if config.NoPruning && config.TrieDirtyCache > 0 {
if config.SnapshotCache > 0 {
config.TrieCleanCache += config.TrieDirtyCache * 3 / 5
@@ -157,7 +157,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
// START: Bor changes
eth := &Ethereum{
config: config,
- merger: consensus.NewMerger(chainDb),
chainDb: chainDb,
eventMux: stack.EventMux(),
accountManager: stack.AccountManager(),
@@ -193,7 +192,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
overrides.OverrideVerkle = config.OverrideVerkle
}
- chainConfig, _, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, trie.NewDatabase(chainDb, trie.HashDefaults), config.Genesis, &overrides)
+ chainConfig, _, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, triedb.NewDatabase(chainDb, triedb.HashDefaults), config.Genesis, &overrides)
if _, isCompat := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !isCompat {
return nil, genesisErr
}
@@ -226,6 +225,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
var (
vmConfig = vm.Config{
EnablePreimageRecording: config.EnablePreimageRecording,
+ EnableWitnessCollection: config.EnableWitnessCollection,
}
cacheConfig = &core.CacheConfig{
TrieCleanLimit: config.TrieCleanCache,
@@ -241,6 +241,18 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
}
)
+ if config.VMTrace != "" {
+ var traceConfig json.RawMessage
+ if config.VMTraceJsonConfig != "" {
+ traceConfig = json.RawMessage(config.VMTraceJsonConfig)
+ }
+ t, err := tracers.LiveDirectory.New(config.VMTrace, traceConfig)
+ if err != nil {
+ return nil, fmt.Errorf("failed to create tracer %s: %v", config.VMTrace, err)
+ }
+ vmConfig.Tracer = t
+ }
+
checker := whitelist.NewService(chainDb)
// check if Parallel EVM is enabled
@@ -273,17 +285,23 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
}
legacyPool := legacypool.New(config.TxPool, eth.blockchain)
- eth.txPool, err = txpool.New(new(big.Int).SetUint64(config.TxPool.PriceLimit), eth.blockchain, []txpool.SubPool{legacyPool})
+ // BOR changes
+ // Blob pool is removed from Subpool for Bor
+ eth.txPool, err = txpool.New(config.TxPool.PriceLimit, eth.blockchain, []txpool.SubPool{legacyPool})
if err != nil {
return nil, err
}
+
+ // The `config.TxPool.PriceLimit` used above doesn't reflect the sanitized/enforced changes
+ // made in the txpool. Update the `gasTip` explicitly to reflect the enforced value.
+ eth.txPool.SetGasTip(new(big.Int).SetUint64(params.BorDefaultTxPoolPriceLimit))
+
// Permit the downloader to use the trie cache allowance during fast sync
cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit
if eth.handler, err = newHandler(&handlerConfig{
Database: chainDb,
Chain: eth.blockchain,
TxPool: eth.txPool,
- Merger: eth.merger,
Network: config.NetworkId,
Sync: config.SyncMode,
BloomCache: uint64(cacheLimit),
@@ -291,7 +309,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
RequiredBlocks: config.RequiredBlocks,
EthAPI: blockChainAPI,
checker: checker,
- txArrivalWait: eth.p2pServer.TxArrivalWait,
enableBlockTracking: eth.config.EnableBlockTracking,
}); err != nil {
return nil, err
@@ -360,7 +377,7 @@ func (s *Ethereum) APIs() []rpc.API {
// BOR change starts
filterSystem := filters.NewFilterSystem(s.APIBackend, filters.Config{})
// set genesis to public filter api
- publicFilterAPI := filters.NewFilterAPI(filterSystem, false, s.config.BorLogs)
+ publicFilterAPI := filters.NewFilterAPI(filterSystem, s.config.BorLogs)
// avoiding constructor changed by introducing new method to set genesis
publicFilterAPI.SetChainConfig(s.blockchain.Config())
// BOR change ends
@@ -368,9 +385,6 @@ func (s *Ethereum) APIs() []rpc.API {
// Append all the local APIs and return
return append(apis, []rpc.API{
{
- Namespace: "eth",
- Service: NewEthereumAPI(s),
- }, {
Namespace: "miner",
Service: NewMinerAPI(s),
}, {
@@ -569,11 +583,6 @@ func (s *Ethereum) Synced() bool { return s.handler.synced
func (s *Ethereum) SetSynced() { s.handler.enableSyncedFeatures() }
func (s *Ethereum) ArchiveMode() bool { return s.config.NoPruning }
func (s *Ethereum) BloomIndexer() *core.ChainIndexer { return s.bloomIndexer }
-func (s *Ethereum) Merger() *consensus.Merger { return s.merger }
-func (s *Ethereum) SyncMode() downloader.SyncMode {
- mode, _ := s.handler.chainSync.modeAndLocalHead()
- return mode
-}
// SetAuthorized sets the authorized bool variable
// denoting that consensus has been authorized while creation
@@ -695,16 +704,12 @@ func retryHeimdallHandler(fn heimdallHandler, tickerDuration time.Duration, time
return
}
- // first run for fetching milestones
+ // first run
firstCtx, cancel := context.WithTimeout(context.Background(), timeout)
- err = fn(firstCtx, ethHandler, bor)
+ _ = fn(firstCtx, ethHandler, bor)
cancel()
- if err != nil {
- log.Warn(fmt.Sprintf("unable to start the %s service - first run", fnName), "err", err)
- }
-
ticker := time.NewTicker(tickerDuration)
defer ticker.Stop()
@@ -712,13 +717,11 @@ func retryHeimdallHandler(fn heimdallHandler, tickerDuration time.Duration, time
select {
case <-ticker.C:
ctx, cancel := context.WithTimeout(context.Background(), timeout)
- err := fn(ctx, ethHandler, bor)
- cancel()
+ // Skip any error reporting here as it's handled in respective functions
+ _ = fn(ctx, ethHandler, bor)
- if err != nil {
- log.Warn(fmt.Sprintf("unable to handle %s", fnName), "err", err)
- }
+ cancel()
case <-closeCh:
return
}
@@ -754,7 +757,7 @@ func (s *Ethereum) handleMilestone(ctx context.Context, ethHandler *ethHandler,
// If the current chain head is behind the received milestone, add it to the future milestone
// list. Also, the hash mismatch (end block hash) error will lead to rewind so also
// add that milestone to the future milestone list.
- if errors.Is(err, errMissingBlocks) || errors.Is(err, errHashMismatch) {
+ if errors.Is(err, errChainOutOfSync) || errors.Is(err, errHashMismatch) {
ethHandler.downloader.ProcessFutureMilestone(num, hash)
}
@@ -858,3 +861,29 @@ func (s *Ethereum) Stop() error {
func (s *Ethereum) SetBlockchain(blockchain *core.BlockChain) {
s.blockchain = blockchain
}
+
+// SyncMode retrieves the current sync mode, either explicitly set, or derived
+// from the chain status.
+func (s *Ethereum) SyncMode() downloader.SyncMode {
+ // If we're in snap sync mode, return that directly
+ if s.handler.snapSync.Load() {
+ return downloader.SnapSync
+ }
+ // We are probably in full sync, but we might have rewound to before the
+ // snap sync pivot, check if we should re-enable snap sync.
+ head := s.blockchain.CurrentBlock()
+ if pivot := rawdb.ReadLastPivotNumber(s.chainDb); pivot != nil {
+ if head.Number.Uint64() < *pivot {
+ return downloader.SnapSync
+ }
+ }
+ // We are in a full sync, but the associated head state is missing. To complete
+ // the head state, forcefully rerun the snap sync. Note it doesn't mean the
+ // persistent state is corrupted, just mismatch with the head block.
+ if !s.blockchain.HasState(head.Root) {
+ log.Info("Reenabled snap sync as chain is stateless")
+ return downloader.SnapSync
+ }
+ // Nope, we're really full syncing
+ return downloader.FullSync
+}
diff --git a/eth/bor_api_backend.go b/eth/bor_api_backend.go
index d320b45527..0d82741d67 100644
--- a/eth/bor_api_backend.go
+++ b/eth/bor_api_backend.go
@@ -53,16 +53,16 @@ func (b *EthAPIBackend) GetVoteOnHash(ctx context.Context, starBlockNr uint64, e
return false, errBorEngineNotAvailable
}
- //Confirmation of 16 blocks on the endblock
+ // Confirmation of 16 blocks on the endblock
tipConfirmationBlockNr := endBlockNr + uint64(16)
- //Check if tipConfirmation block exit
+ // Check if tipConfirmation block exit
_, err := b.BlockByNumber(ctx, rpc.BlockNumber(tipConfirmationBlockNr))
if err != nil {
return false, errTipConfirmationBlock
}
- //Check if end block exist
+ // Check if end block exist
localEndBlock, err := b.BlockByNumber(ctx, rpc.BlockNumber(endBlockNr))
if err != nil {
return false, errEndBlock
@@ -75,12 +75,12 @@ func (b *EthAPIBackend) GetVoteOnHash(ctx context.Context, starBlockNr uint64, e
if !isLocked {
downloader.UnlockMutex(false, "", endBlockNr, common.Hash{})
- return false, errors.New("Whitelisted number or locked sprint number is more than the received end block number")
+ return false, errors.New("whitelisted number or locked sprint number is more than the received end block number")
}
if localEndBlockHash != hash {
downloader.UnlockMutex(false, "", endBlockNr, common.Hash{})
- return false, fmt.Errorf("Hash mismatch: localChainHash %s, milestoneHash %s", localEndBlockHash, hash)
+ return false, fmt.Errorf("hash mismatch: localChainHash %s, milestoneHash %s", localEndBlockHash, hash)
}
downloader.UnlockMutex(true, milestoneId, endBlockNr, localEndBlock.Hash())
diff --git a/eth/bor_checkpoint_verifier.go b/eth/bor_checkpoint_verifier.go
index b2fd2c2d21..4d7a054374 100644
--- a/eth/bor_checkpoint_verifier.go
+++ b/eth/bor_checkpoint_verifier.go
@@ -12,12 +12,16 @@ import (
)
var (
- // errMissingBlocks is returned when we don't have the blocks locally, yet.
- errMissingBlocks = errors.New("missing blocks")
+ // errMissingCurrentBlock is returned when we don't have the current block
+ // present locally.
+ errMissingCurrentBlock = errors.New("current block missing")
- // errRootHash is returned when we aren't able to calculate the root hash
- // locally for a range of blocks.
- errRootHash = errors.New("failed to get local root hash")
+ // errChainOutOfSync is returned when we're trying to process a future
+ // checkpoint/milestone and we haven't reached at that number yet.
+ errChainOutOfSync = errors.New("chain out of sync")
+
+ // errRootHash is returned when the root hash calculation for a range of blocks fails.
+ errRootHash = errors.New("root hash calculation failed")
// errHashMismatch is returned when the local hash doesn't match
// with the hash of checkpoint/milestone. It is the root hash of blocks
@@ -27,13 +31,10 @@ var (
// errEndBlock is returned when we're unable to fetch a block locally.
errEndBlock = errors.New("failed to get end block")
- // errEndBlock is returned when we're unable to fetch a block locally.
+ // errEndBlock is returned when we're unable to fetch the tip confirmation block locally.
errTipConfirmationBlock = errors.New("failed to get tip confirmation block")
- // errBlockNumberConversion is returned when we get err in parsing hexautil block number
- errBlockNumberConversion = errors.New("failed to parse the block number")
-
- //Metrics for collecting the rewindLength
+ // rewindLengthMeter for collecting info about the length of chain rewinded
rewindLengthMeter = metrics.NewRegisteredMeter("chain/autorewind/length", nil)
)
@@ -57,14 +58,14 @@ func borVerify(ctx context.Context, eth *Ethereum, handler *ethHandler, start ui
currentBlock := eth.BlockChain().CurrentBlock()
if currentBlock == nil {
log.Debug(fmt.Sprintf("Failed to fetch current block from blockchain while verifying incoming %s", str))
- return hash, errMissingBlocks
+ return hash, errMissingCurrentBlock
}
head := currentBlock.Number.Uint64()
if head < end {
log.Debug(fmt.Sprintf("Current head block behind incoming %s block", str), "head", head, "end block", end)
- return hash, errMissingBlocks
+ return hash, errChainOutOfSync
}
var localHash string
@@ -77,15 +78,15 @@ func borVerify(ctx context.Context, eth *Ethereum, handler *ethHandler, start ui
localHash, err = handler.ethAPI.GetRootHash(ctx, start, end)
if err != nil {
- log.Debug("Failed to get root hash of given block range while whitelisting checkpoint", "start", start, "end", end, "err", err)
- return hash, errRootHash
+ log.Debug("Failed to calculate root hash of given block range while whitelisting checkpoint", "start", start, "end", end, "err", err)
+ return hash, fmt.Errorf("%w: %v", errRootHash, err)
}
} else {
// in case of milestone(isCheckpoint==false) get the hash of endBlock
block, err := handler.ethAPI.GetBlockByNumber(ctx, rpc.BlockNumber(end), false)
if err != nil {
log.Debug("Failed to get end block hash while whitelisting milestone", "number", end, "err", err)
- return hash, errEndBlock
+ return hash, fmt.Errorf("%w: %v", errEndBlock, err)
}
localHash = fmt.Sprintf("%v", block["hash"])[2:]
@@ -93,7 +94,6 @@ func borVerify(ctx context.Context, eth *Ethereum, handler *ethHandler, start ui
//nolint
if localHash != hash {
-
if isCheckpoint {
log.Warn("Root hash mismatch while whitelisting checkpoint", "expected", localHash, "got", hash)
} else {
@@ -124,9 +124,9 @@ func borVerify(ctx context.Context, eth *Ethereum, handler *ethHandler, start ui
}
if isCheckpoint {
- log.Warn("Rewinding chain due to checkpoint root hash mismatch", "number", rewindTo)
+ log.Info("Rewinding chain due to checkpoint root hash mismatch", "number", rewindTo)
} else {
- log.Warn("Rewinding chain due to milestone endblock hash mismatch", "number", rewindTo)
+ log.Info("Rewinding chain due to milestone endblock hash mismatch", "number", rewindTo)
}
rewindBack(eth, head, rewindTo)
@@ -138,7 +138,7 @@ func borVerify(ctx context.Context, eth *Ethereum, handler *ethHandler, start ui
block, err := handler.ethAPI.GetBlockByNumber(ctx, rpc.BlockNumber(end), false)
if err != nil {
log.Debug("Failed to get end block hash while whitelisting", "err", err)
- return hash, errEndBlock
+ return hash, fmt.Errorf("%w: %v", errEndBlock, err)
}
hash = fmt.Sprintf("%v", block["hash"])
@@ -170,5 +170,4 @@ func rewind(eth *Ethereum, head uint64, rewindTo uint64) {
} else {
rewindLengthMeter.Mark(int64(head - rewindTo))
}
-
}
diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go
index 923e0ec3bd..b35703a658 100644
--- a/eth/catalyst/api.go
+++ b/eth/catalyst/api.go
@@ -21,6 +21,7 @@ import (
"errors"
"fmt"
"math/big"
+ "strconv"
"sync"
"time"
@@ -31,9 +32,12 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/downloader"
+ "github.com/ethereum/go-ethereum/internal/version"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/node"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/params/forks"
"github.com/ethereum/go-ethereum/rpc"
)
@@ -88,6 +92,7 @@ var caps = []string{
"engine_newPayloadV3",
"engine_getPayloadBodiesByHashV1",
"engine_getPayloadBodiesByRangeV1",
+ "engine_getClientVersionV1",
}
type ConsensusAPI struct {
@@ -173,61 +178,63 @@ func newConsensusAPIWithoutHeartbeat(eth *eth.Ethereum) *ConsensusAPI {
// and return its payloadID.
func (api *ConsensusAPI) ForkchoiceUpdatedV1(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
if payloadAttributes != nil {
- if payloadAttributes.Withdrawals != nil {
- return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("withdrawals not supported in V1"))
+ if payloadAttributes.Withdrawals != nil || payloadAttributes.BeaconRoot != nil {
+ return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("withdrawals and beacon root not supported in V1"))
}
if api.eth.BlockChain().Config().IsShanghai(api.eth.BlockChain().Config().LondonBlock) {
return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("forkChoiceUpdateV1 called post-shanghai"))
}
}
- return api.forkchoiceUpdated(update, payloadAttributes)
+ return api.forkchoiceUpdated(update, payloadAttributes, engine.PayloadV1, false)
}
-// ForkchoiceUpdatedV2 is equivalent to V1 with the addition of withdrawals in the payload attributes.
-func (api *ConsensusAPI) ForkchoiceUpdatedV2(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
- if payloadAttributes != nil {
- if err := api.verifyPayloadAttributes(payloadAttributes); err != nil {
- return engine.STATUS_INVALID, engine.InvalidParams.With(err)
+// ForkchoiceUpdatedV2 is equivalent to V1 with the addition of withdrawals in the payload
+// attributes. It supports both PayloadAttributesV1 and PayloadAttributesV2.
+func (api *ConsensusAPI) ForkchoiceUpdatedV2(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
+ if params != nil {
+ if params.BeaconRoot != nil {
+ return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("unexpected beacon root"))
+ }
+ switch api.eth.BlockChain().Config().LatestFork(params.Timestamp) {
+ case forks.Paris:
+ if params.Withdrawals != nil {
+ return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("withdrawals before shanghai"))
+ }
+ case forks.Shanghai:
+ if params.Withdrawals == nil {
+ return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing withdrawals"))
+ }
+ default:
+ return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV2 must only be called with paris and shanghai payloads"))
}
}
- return api.forkchoiceUpdated(update, payloadAttributes)
+ return api.forkchoiceUpdated(update, params, engine.PayloadV2, false)
}
-// ForkchoiceUpdatedV3 is equivalent to V2 with the addition of parent beacon block root in the payload attributes.
-func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
- if payloadAttributes != nil {
- if err := api.verifyPayloadAttributes(payloadAttributes); err != nil {
- return engine.STATUS_INVALID, engine.InvalidParams.With(err)
+// ForkchoiceUpdatedV3 is equivalent to V2 with the addition of parent beacon block root
+// in the payload attributes. It supports only PayloadAttributesV3.
+func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
+ if params != nil {
+ if params.Withdrawals == nil {
+ return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing withdrawals"))
+ }
+ if params.BeaconRoot == nil {
+ return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing beacon root"))
+ }
+ if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun {
+ return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV3 must only be called for cancun payloads"))
}
}
- return api.forkchoiceUpdated(update, payloadAttributes)
-}
-func (api *ConsensusAPI) verifyPayloadAttributes(attr *engine.PayloadAttributes) error {
- c := api.eth.BlockChain().Config()
+ // TODO(matt): the spec requires that fcu is applied when called on a valid
+ // hash, even if params are wrong. To do this we need to split up
+ // forkchoiceUpdate into a function that only updates the head and then a
+ // function that kicks off block construction.
- // Verify withdrawals attribute for Shanghai.
- if err := checkAttribute(c.IsShanghai, attr.Withdrawals != nil, c.LondonBlock, attr.Timestamp); err != nil {
- return fmt.Errorf("invalid withdrawals: %w", err)
- }
- // Verify beacon root attribute for Cancun.
- if err := checkAttribute(c.IsCancun, attr.BeaconRoot != nil, c.LondonBlock, attr.Timestamp); err != nil {
- return fmt.Errorf("invalid parent beacon block root: %w", err)
- }
- return nil
+ return api.forkchoiceUpdated(update, params, engine.PayloadV3, false)
}
-func checkAttribute(active func(*big.Int) bool, exists bool, block *big.Int, time uint64) error {
- if active(block) && !exists {
- return errors.New("fork active, missing expected attribute")
- }
- if !active(block) && exists {
- return errors.New("fork inactive, unexpected attribute set")
- }
- return nil
-}
-
-func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
+func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes, payloadVersion engine.PayloadVersion, simulatorMode bool) (engine.ForkChoiceResponse, error) {
api.forkchoiceLock.Lock()
defer api.forkchoiceLock.Unlock()
@@ -264,12 +271,6 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
finalized := api.remoteBlocks.get(update.FinalizedBlockHash)
// Header advertised via a past newPayload request. Start syncing to it.
- // Before we do however, make sure any legacy sync in switched off so we
- // don't accidentally have 2 cycles running.
- if merger := api.eth.Merger(); !merger.TDDReached() {
- merger.ReachTTD()
- api.eth.Downloader().Cancel()
- }
context := []interface{}{"number", header.Number, "hash", header.Hash()}
if update.FinalizedBlockHash != (common.Hash{}) {
if finalized == nil {
@@ -331,10 +332,7 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
// If the beacon client also advertised a finalized block, mark the local
// chain final and completely in PoS mode.
if update.FinalizedBlockHash != (common.Hash{}) {
- if merger := api.eth.Merger(); !merger.PoSFinalized() {
- merger.FinalizePoS()
- }
- // If the finalized block is not in our canonical tree, somethings wrong
+ // If the finalized block is not in our canonical tree, something is wrong
finalBlock := api.eth.BlockChain().GetBlockByHash(update.FinalizedBlockHash)
if finalBlock == nil {
log.Warn("Final block not available in database", "hash", update.FinalizedBlockHash)
@@ -346,7 +344,7 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
// Set the finalized block
api.eth.BlockChain().SetFinalized(finalBlock.Header())
}
- // Check if the safe block hash is in our canonical tree, if not somethings wrong
+ // Check if the safe block hash is in our canonical tree, if not something is wrong
if update.SafeBlockHash != (common.Hash{}) {
safeBlock := api.eth.BlockChain().GetBlockByHash(update.SafeBlockHash)
if safeBlock == nil {
@@ -371,6 +369,7 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
Random: payloadAttributes.Random,
Withdrawals: payloadAttributes.Withdrawals,
BeaconRoot: payloadAttributes.BeaconRoot,
+ Version: payloadVersion,
}
id := args.Id()
// If we already are busy generating this work, then we do not need
@@ -378,6 +377,19 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
if api.localBlocks.has(id) {
return valid(&id), nil
}
+ // If the beacon chain is ran by a simulator, then transaction insertion,
+ // block insertion and block production will happen without any timing
+ // delay between them. This will cause flaky simulator executions due to
+ // the transaction pool running its internal reset operation on a back-
+ // ground thread. To avoid the racey behavior - in simulator mode - the
+ // pool will be explicitly blocked on its reset before continuing to the
+ // block production below.
+ if simulatorMode {
+ if err := api.eth.TxPool().Sync(); err != nil {
+ log.Error("Failed to sync transaction pool", "err", err)
+ return valid(nil), engine.InvalidPayloadAttributes.With(err)
+ }
+ }
payload, err := api.eth.Miner().BuildPayload(args)
if err != nil {
log.Error("Failed to build payload", "err", err)
@@ -421,6 +433,9 @@ func (api *ConsensusAPI) ExchangeTransitionConfigurationV1(config engine.Transit
// GetPayloadV1 returns a cached payload by id.
func (api *ConsensusAPI) GetPayloadV1(payloadID engine.PayloadID) (*engine.ExecutableData, error) {
+ if !payloadID.Is(engine.PayloadV1) {
+ return nil, engine.UnsupportedFork
+ }
data, err := api.getPayload(payloadID, false)
if err != nil {
return nil, err
@@ -430,11 +445,17 @@ func (api *ConsensusAPI) GetPayloadV1(payloadID engine.PayloadID) (*engine.Execu
// GetPayloadV2 returns a cached payload by id.
func (api *ConsensusAPI) GetPayloadV2(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) {
+ if !payloadID.Is(engine.PayloadV1, engine.PayloadV2) {
+ return nil, engine.UnsupportedFork
+ }
return api.getPayload(payloadID, false)
}
// GetPayloadV3 returns a cached payload by id.
func (api *ConsensusAPI) GetPayloadV3(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) {
+ if !payloadID.Is(engine.PayloadV3) {
+ return nil, engine.UnsupportedFork
+ }
return api.getPayload(payloadID, false)
}
@@ -461,9 +482,12 @@ func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.Payl
if params.Withdrawals == nil {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai"))
}
- } else if params.Withdrawals != nil {
- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("non-nil withdrawals pre-shanghai"))
+ } else {
+ if params.Withdrawals != nil {
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("non-nil withdrawals pre-shanghai"))
+ }
}
+
if api.eth.BlockChain().Config().IsCancun(new(big.Int).SetUint64(params.Number)) {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("newPayloadV2 called post-cancun"))
}
@@ -472,23 +496,26 @@ func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.Payl
// NewPayloadV3 creates an Eth1 block, inserts it in the chain, and returns the status of the chain.
func (api *ConsensusAPI) NewPayloadV3(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) {
+ if params.Withdrawals == nil {
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai"))
+ }
if params.ExcessBlobGas == nil {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil excessBlobGas post-cancun"))
}
if params.BlobGasUsed == nil {
- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil params.BlobGasUsed post-cancun"))
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil blobGasUsed post-cancun"))
}
+
if versionedHashes == nil {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil versionedHashes post-cancun"))
}
if beaconRoot == nil {
- return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil parentBeaconBlockRoot post-cancun"))
+ return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun"))
}
if !api.eth.BlockChain().Config().IsCancun(new(big.Int).SetUint64(params.Number)) {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadV3 called pre-cancun"))
}
-
return api.newPayload(params, versionedHashes, beaconRoot)
}
@@ -512,7 +539,33 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashe
log.Trace("Engine API request received", "method", "NewPayload", "number", params.Number, "hash", params.BlockHash)
block, err := engine.ExecutableDataToBlock(params, versionedHashes, beaconRoot)
if err != nil {
- log.Warn("Invalid NewPayload params", "params", params, "error", err)
+ bgu := "nil"
+ if params.BlobGasUsed != nil {
+ bgu = strconv.Itoa(int(*params.BlobGasUsed))
+ }
+ ebg := "nil"
+ if params.BlobGasUsed != nil {
+ ebg = strconv.Itoa(int(*params.ExcessBlobGas))
+ }
+ log.Warn("Invalid NewPayload params",
+ "params.Number", params.Number,
+ "params.ParentHash", params.ParentHash,
+ "params.BlockHash", params.BlockHash,
+ "params.StateRoot", params.StateRoot,
+ "params.FeeRecipient", params.FeeRecipient,
+ "params.LogsBloom", common.PrettyBytes(params.LogsBloom),
+ "params.Random", params.Random,
+ "params.GasLimit", params.GasLimit,
+ "params.GasUsed", params.GasUsed,
+ "params.Timestamp", params.Timestamp,
+ "params.ExtraData", common.PrettyBytes(params.ExtraData),
+ "params.BaseFeePerGas", params.BaseFeePerGas,
+ "params.BlobGasUsed", bgu,
+ "params.ExcessBlobGas", ebg,
+ "len(params.Transactions)", len(params.Transactions),
+ "len(params.Withdrawals)", len(params.Withdrawals),
+ "beaconRoot", beaconRoot,
+ "error", err)
return api.invalid(err, nil), nil
}
// Stash away the last update to warn the user if the beacon client goes offline
@@ -539,7 +592,7 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashe
// update after legit payload executions.
parent := api.eth.BlockChain().GetBlock(block.ParentHash(), block.NumberU64()-1)
if parent == nil {
- return api.delayPayloadImport(block)
+ return api.delayPayloadImport(block), nil
}
// We have an existing parent, do some sanity checks to avoid the beacon client
// triggering too early
@@ -565,14 +618,14 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashe
// into the database directly will conflict with the assumptions of snap sync
// that it has an empty db that it can fill itself.
if api.eth.SyncMode() != downloader.FullSync {
- return api.delayPayloadImport(block)
+ return api.delayPayloadImport(block), nil
}
if !api.eth.BlockChain().HasBlockAndState(block.ParentHash(), block.NumberU64()-1) {
api.remoteBlocks.put(block.Hash(), block.Header())
log.Warn("State not available, ignoring new payload")
return engine.PayloadStatusV1{Status: engine.ACCEPTED}, nil
}
- log.Trace("Inserting block without sethead", "hash", block.Hash(), "number", block.Number)
+ log.Trace("Inserting block without sethead", "hash", block.Hash(), "number", block.Number())
if err := api.eth.BlockChain().InsertBlockWithoutSetHead(block); err != nil {
log.Warn("NewPayloadV1: inserting block failed", "error", err)
@@ -583,13 +636,6 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashe
return api.invalid(err, parent.Header()), nil
}
- // We've accepted a valid payload from the beacon client. Mark the local
- // chain transitions to notify other subsystems (e.g. downloader) of the
- // behavioral change.
- if merger := api.eth.Merger(); !merger.TDDReached() {
- merger.ReachTTD()
- api.eth.Downloader().Cancel()
- }
hash := block.Hash()
return engine.PayloadStatusV1{Status: engine.VALID, LatestValidHash: &hash}, nil
}
@@ -598,23 +644,23 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashe
// either via a forkchoice update or a sync extension. This method is meant to
// be called by the newpayload command when the block seems to be ok, but some
// prerequisite prevents it from being processed (e.g. no parent, or snap sync).
-func (api *ConsensusAPI) delayPayloadImport(block *types.Block) (engine.PayloadStatusV1, error) {
+func (api *ConsensusAPI) delayPayloadImport(block *types.Block) engine.PayloadStatusV1 {
// Sanity check that this block's parent is not on a previously invalidated
// chain. If it is, mark the block as invalid too.
if res := api.checkInvalidAncestor(block.ParentHash(), block.Hash()); res != nil {
- return *res, nil
+ return *res
}
// Stash the block away for a potential forced forkchoice update to it
// at a later time.
api.remoteBlocks.put(block.Hash(), block.Header())
// Although we don't want to trigger a sync, if there is one already in
- // progress, try to extend if with the current payload request to relieve
+ // progress, try to extend it with the current payload request to relieve
// some strain from the forkchoice update.
err := api.eth.Downloader().BeaconExtend(api.eth.SyncMode(), block.Header())
if err == nil {
log.Debug("Payload accepted for sync extension", "number", block.NumberU64(), "hash", block.Hash())
- return engine.PayloadStatusV1{Status: engine.SYNCING}, nil
+ return engine.PayloadStatusV1{Status: engine.SYNCING}
}
// Either no beacon sync was started yet, or it rejected the delivered
// payload as non-integratable on top of the existing sync. We'll just
@@ -631,7 +677,7 @@ func (api *ConsensusAPI) delayPayloadImport(block *types.Block) (engine.PayloadS
// and cannot afford concurrent out-if-band modifications via imports.
log.Warn("Ignoring payload while snap syncing", "number", block.NumberU64(), "hash", block.Hash(), "reason", err)
}
- return engine.PayloadStatusV1{Status: engine.SYNCING}, nil
+ return engine.PayloadStatusV1{Status: engine.SYNCING}
}
// setInvalidAncestor is a callback for the downloader to notify us if a bad block
@@ -747,26 +793,23 @@ func (api *ConsensusAPI) heartbeat() {
// If there have been no updates for the past while, warn the user
// that the beacon client is probably offline
- if api.eth.BlockChain().Config().TerminalTotalDifficultyPassed || api.eth.Merger().TDDReached() {
- if time.Since(lastForkchoiceUpdate) <= beaconUpdateConsensusTimeout || time.Since(lastNewPayloadUpdate) <= beaconUpdateConsensusTimeout {
- offlineLogged = time.Time{}
- continue
- }
-
- if time.Since(offlineLogged) > beaconUpdateWarnFrequency {
- if lastForkchoiceUpdate.IsZero() && lastNewPayloadUpdate.IsZero() {
- if lastTransitionUpdate.IsZero() {
- log.Warn("Post-merge network, but no beacon client seen. Please launch one to follow the chain!")
- } else {
- log.Warn("Beacon client online, but never received consensus updates. Please ensure your beacon client is operational to follow the chain!")
- }
+ if time.Since(lastForkchoiceUpdate) <= beaconUpdateConsensusTimeout || time.Since(lastNewPayloadUpdate) <= beaconUpdateConsensusTimeout {
+ offlineLogged = time.Time{}
+ continue
+ }
+ if time.Since(offlineLogged) > beaconUpdateWarnFrequency {
+ if lastForkchoiceUpdate.IsZero() && lastNewPayloadUpdate.IsZero() {
+ if lastTransitionUpdate.IsZero() {
+ log.Warn("Post-merge network, but no beacon client seen. Please launch one to follow the chain!")
} else {
- log.Warn("Beacon client online, but no consensus updates received in a while. Please fix your beacon client to follow the chain!")
+ log.Warn("Beacon client online, but never received consensus updates. Please ensure your beacon client is operational to follow the chain!")
}
- offlineLogged = time.Now()
+ } else {
+ log.Warn("Beacon client online, but no consensus updates received in a while. Please fix your beacon client to follow the chain!")
}
- continue
+ offlineLogged = time.Now()
}
+ continue
}
}
@@ -775,6 +818,23 @@ func (api *ConsensusAPI) ExchangeCapabilities([]string) []string {
return caps
}
+// GetClientVersionV1 exchanges client version data of this node.
+func (api *ConsensusAPI) GetClientVersionV1(info engine.ClientVersionV1) []engine.ClientVersionV1 {
+ log.Trace("Engine API request received", "method", "GetClientVersionV1", "info", info.String())
+ commit := make([]byte, 4)
+ if vcs, ok := version.VCS(); ok {
+ commit = common.FromHex(vcs.Commit)[0:4]
+ }
+ return []engine.ClientVersionV1{
+ {
+ Code: engine.ClientCode,
+ Name: engine.ClientName,
+ Version: params.VersionWithMeta,
+ Commit: hexutil.Encode(commit),
+ },
+ }
+}
+
// GetPayloadBodiesByHashV1 implements engine_getPayloadBodiesByHashV1 which allows for retrieval of a list
// of block bodies by the engine api.
func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engine.ExecutionPayloadBodyV1 {
@@ -821,8 +881,7 @@ func getBody(block *types.Block) *engine.ExecutionPayloadBodyV1 {
)
for j, tx := range body.Transactions {
- data, _ := tx.MarshalBinary()
- txs[j] = hexutil.Bytes(data)
+ txs[j], _ = tx.MarshalBinary()
}
// Post-shanghai withdrawals MUST be set to empty slice instead of nil
diff --git a/eth/catalyst/api_test.go b/eth/catalyst/api_test.go
index 3e95b57eba..fb45ff15a0 100644
--- a/eth/catalyst/api_test.go
+++ b/eth/catalyst/api_test.go
@@ -71,9 +71,9 @@ func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) {
}
genesis := &core.Genesis{
Config: &config,
- Alloc: core.GenesisAlloc{
- testAddr: {Balance: testBalance},
- params.BeaconRootsStorageAddress: {Balance: common.Big0, Code: common.Hex2Bytes("3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500")},
+ Alloc: types.GenesisAlloc{
+ testAddr: {Balance: testBalance},
+ params.BeaconRootsAddress: {Balance: common.Big0, Code: common.Hex2Bytes("3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500")},
},
ExtraData: []byte("test genesis"),
Timestamp: 9000,
@@ -84,7 +84,7 @@ func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) {
generate := func(i int, g *core.BlockGen) {
g.OffsetTime(5)
g.SetExtra([]byte("test"))
- tx, _ := types.SignTx(types.NewTransaction(testNonce, common.HexToAddress("0x9a9070028361F7AAbeB3f2F2Dc07F82C4a98A02a"), big.NewInt(1), params.TxGas, big.NewInt(params.InitialBaseFee*32), nil), types.LatestSigner(&config), testKey)
+ tx, _ := types.SignTx(types.NewTransaction(testNonce, common.HexToAddress("0x9a9070028361F7AAbeB3f2F2Dc07F82C4a98A02a"), big.NewInt(1), params.TxGas, big.NewInt(params.InitialBaseFee*26), nil), types.LatestSigner(&config), testKey)
g.AddTx(tx)
testNonce++
}
@@ -112,7 +112,7 @@ func TestEth2AssembleBlock(t *testing.T) {
if err != nil {
t.Fatalf("error signing transaction, err=%v", err)
}
- ethservice.TxPool().Add([]*types.Transaction{tx}, true, false)
+ ethservice.TxPool().Add([]*types.Transaction{tx}, true, true)
blockParams := engine.PayloadAttributes{
Timestamp: blocks[9].Time() + 5,
}
@@ -189,7 +189,7 @@ func TestEth2PrepareAndGetPayload(t *testing.T) {
// Put the 10th block's tx in the pool and produce a new block
txs := blocks[9].Transactions()
- ethservice.TxPool().Add(txs, true, false)
+ ethservice.TxPool().Add(txs, true, true)
blockParams := engine.PayloadAttributes{
Timestamp: blocks[8].Time() + 5,
}
@@ -210,6 +210,7 @@ func TestEth2PrepareAndGetPayload(t *testing.T) {
FeeRecipient: blockParams.SuggestedFeeRecipient,
Random: blockParams.Random,
BeaconRoot: blockParams.BeaconRoot,
+ Version: engine.PayloadV1,
}).Id()
execData, err := api.GetPayloadV1(payloadID)
if err != nil {
@@ -261,11 +262,8 @@ func TestInvalidPayloadTimestamp(t *testing.T) {
{0, true},
{parent.Time, true},
{parent.Time - 1, true},
-
- // TODO (MariusVanDerWijden) following tests are currently broken,
- // fixed in upcoming merge-kiln-v2 pr
- //{parent.Time() + 1, false},
- //{uint64(time.Now().Unix()) + uint64(time.Minute), false},
+ {parent.Time + 1, false},
+ {uint64(time.Now().Unix()) + uint64(time.Minute), false},
}
for i, test := range tests {
@@ -312,13 +310,13 @@ func TestEth2NewBlock(t *testing.T) {
statedb, _ := ethservice.BlockChain().StateAt(parent.Root())
nonce := statedb.GetNonce(testAddr)
tx, _ := types.SignTx(types.NewContractCreation(nonce, new(big.Int), 1000000, big.NewInt(2*params.InitialBaseFee), logCode), types.LatestSigner(ethservice.BlockChain().Config()), testKey)
- ethservice.TxPool().Add([]*types.Transaction{tx}, true, false)
+ ethservice.TxPool().Add([]*types.Transaction{tx}, true, true)
execData, err := assembleWithTransactions(api, parent.Hash(), &engine.PayloadAttributes{
Timestamp: parent.Time() + 5,
}, 1)
if err != nil {
- t.Fatalf("Failed to create the executable data %v", err)
+ t.Fatalf("Failed to create the executable data, block %d: %v", i, err)
}
block, err := engine.ExecutableDataToBlock(*execData, nil, nil)
if err != nil {
@@ -449,7 +447,9 @@ func startEthService(t *testing.T, genesis *core.Genesis, blocks []*types.Block)
t.Fatal("can't create node:", err)
}
- ethcfg := ðconfig.Config{Genesis: genesis, SyncMode: downloader.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256}
+ mcfg := miner.DefaultConfig
+ mcfg.Etherbase = testAddr
+ ethcfg := ðconfig.Config{Genesis: genesis, SyncMode: downloader.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256, Miner: mcfg}
ethservice, err := eth.New(n, ethcfg)
if err != nil {
t.Fatal("can't create eth service:", err)
@@ -462,7 +462,6 @@ func startEthService(t *testing.T, genesis *core.Genesis, blocks []*types.Block)
t.Fatal("can't import test blocks:", err)
}
- ethservice.SetEtherbase(testAddr)
ethservice.SetSynced()
return n, ethservice
}
@@ -604,7 +603,7 @@ func TestNewPayloadOnInvalidChain(t *testing.T) {
Nonce: statedb.GetNonce(testAddr),
Value: new(big.Int),
Gas: 1000000,
- GasPrice: big.NewInt(32 * params.InitialBaseFee),
+ GasPrice: big.NewInt(26 * params.InitialBaseFee),
Data: logCode,
})
ethservice.TxPool().Add([]*types.Transaction{tx}, false, true)
@@ -780,7 +779,7 @@ func setBlockhash(data *engine.ExecutableData) *engine.ExecutableData {
Extra: data.ExtraData,
MixDigest: data.Random,
}
- block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */)
+ block := types.NewBlockWithHeader(header).WithBody(types.Body{Transactions: txs})
data.BlockHash = block.Hash()
return data
}
@@ -864,7 +863,6 @@ func TestTrickRemoteBlockCache(t *testing.T) {
func TestInvalidBloom(t *testing.T) {
genesis, preMergeBlocks := generateMergeChain(10, false)
n, ethservice := startEthService(t, genesis, preMergeBlocks)
- ethservice.Merger().ReachTTD()
defer n.Close()
commonAncestor := ethservice.BlockChain().CurrentBlock()
@@ -937,7 +935,7 @@ func TestNewPayloadOnInvalidTerminalBlock(t *testing.T) {
Extra: data.ExtraData,
MixDigest: data.Random,
}
- block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */)
+ block := types.NewBlockWithHeader(header).WithBody(types.Body{Transactions: txs})
data.BlockHash = block.Hash()
// Send the new payload
resp2, err := api.NewPayloadV1(data)
@@ -981,11 +979,11 @@ func TestSimultaneousNewBlock(t *testing.T) {
defer wg.Done()
if newResp, err := api.NewPayloadV1(*execData); err != nil {
errMu.Lock()
- testErr = fmt.Errorf("Failed to insert block: %w", err)
+ testErr = fmt.Errorf("failed to insert block: %w", err)
errMu.Unlock()
} else if newResp.Status != "VALID" {
errMu.Lock()
- testErr = fmt.Errorf("Failed to insert block: %v", newResp.Status)
+ testErr = fmt.Errorf("failed to insert block: %v", newResp.Status)
errMu.Unlock()
}
}()
@@ -1020,7 +1018,7 @@ func TestSimultaneousNewBlock(t *testing.T) {
defer wg.Done()
if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
errMu.Lock()
- testErr = fmt.Errorf("Failed to insert block: %w", err)
+ testErr = fmt.Errorf("failed to insert block: %w", err)
errMu.Unlock()
}
}()
@@ -1543,7 +1541,7 @@ func TestBlockToPayloadWithBlobs(t *testing.T) {
},
}
- block := types.NewBlock(&header, txs, nil, nil, trie.NewStackTrie(nil))
+ block := types.NewBlock(&header, &types.Body{Transactions: txs}, nil, trie.NewStackTrie(nil))
envelope := engine.BlockToExecutableData(block, nil, sidecars)
var want int
for _, tx := range txs {
@@ -1573,7 +1571,6 @@ func TestParentBeaconBlockRoot(t *testing.T) {
genesis, blocks := generateMergeChain(10, true)
n, ethservice := startEthService(t, genesis, blocks)
- ethservice.Merger().ReachTTD()
defer n.Close()
api := NewConsensusAPI(ethservice)
@@ -1588,7 +1585,7 @@ func TestParentBeaconBlockRoot(t *testing.T) {
fcState := engine.ForkchoiceStateV1{
HeadBlockHash: parent.Hash(),
}
- resp, err := api.ForkchoiceUpdatedV2(fcState, &blockParams)
+ resp, err := api.ForkchoiceUpdatedV3(fcState, &blockParams)
if err != nil {
t.Fatalf("error preparing payload, err=%v", err.(*engine.EngineAPIError).ErrorData())
}
@@ -1604,6 +1601,7 @@ func TestParentBeaconBlockRoot(t *testing.T) {
Random: blockParams.Random,
Withdrawals: blockParams.Withdrawals,
BeaconRoot: blockParams.BeaconRoot,
+ Version: engine.PayloadV3,
}).Id()
execData, err := api.GetPayloadV3(payloadID)
if err != nil {
@@ -1636,10 +1634,33 @@ func TestParentBeaconBlockRoot(t *testing.T) {
rootIdx = common.BigToHash(big.NewInt(int64((execData.ExecutionPayload.Timestamp % 98304) + 98304)))
)
- if num := db.GetState(params.BeaconRootsStorageAddress, timeIdx); num != timeIdx {
+ if num := db.GetState(params.BeaconRootsAddress, timeIdx); num != timeIdx {
t.Fatalf("incorrect number stored: want %s, got %s", timeIdx, num)
}
- if root := db.GetState(params.BeaconRootsStorageAddress, rootIdx); root != *blockParams.BeaconRoot {
+ if root := db.GetState(params.BeaconRootsAddress, rootIdx); root != *blockParams.BeaconRoot {
t.Fatalf("incorrect root stored: want %s, got %s", *blockParams.BeaconRoot, root)
}
}
+
+// TestGetClientVersion verifies the expected version info is returned.
+func TestGetClientVersion(t *testing.T) {
+ genesis, preMergeBlocks := generateMergeChain(10, false)
+ n, ethservice := startEthService(t, genesis, preMergeBlocks)
+ defer n.Close()
+
+ api := NewConsensusAPI(ethservice)
+ info := engine.ClientVersionV1{
+ Code: "TT",
+ Name: "test",
+ Version: "1.1.1",
+ Commit: "0x12345678",
+ }
+ infos := api.GetClientVersionV1(info)
+ if len(infos) != 1 {
+ t.Fatalf("expected only one returned client version, got %d", len(infos))
+ }
+ info = infos[0]
+ if info.Code != engine.ClientCode || info.Name != engine.ClientName || info.Version != params.VersionWithMeta {
+ t.Fatalf("client info does match expected, got %s", info.String())
+ }
+}
diff --git a/eth/catalyst/simulated_beacon.go b/eth/catalyst/simulated_beacon.go
index d8b8641e6a..2d6569e422 100644
--- a/eth/catalyst/simulated_beacon.go
+++ b/eth/catalyst/simulated_beacon.go
@@ -18,17 +18,21 @@ package catalyst
import (
"crypto/rand"
+ "crypto/sha256"
"errors"
+ "math/big"
"sync"
"time"
"github.com/ethereum/go-ethereum/beacon/engine"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
+ "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
)
@@ -59,7 +63,7 @@ func (w *withdrawalQueue) gatherPending(maxCount int) []*types.Withdrawal {
case withdrawal := <-w.pending:
withdrawals = append(withdrawals, withdrawal)
if len(withdrawals) == maxCount {
- break
+ return withdrawals
}
default:
return withdrawals
@@ -81,6 +85,11 @@ type SimulatedBeacon struct {
lastBlockTime uint64
}
+// NewSimulatedBeacon constructs a new simulated beacon chain.
+// Period sets the period in which blocks should be produced.
+//
+// - If period is set to 0, a block is produced on every transaction.
+// via Commit, Fork and AdjustTime.
func NewSimulatedBeacon(period uint64, eth *eth.Ethereum) (*SimulatedBeacon, error) {
block := eth.BlockChain().CurrentBlock()
current := engine.ForkchoiceStateV1{
@@ -116,7 +125,9 @@ func (c *SimulatedBeacon) setFeeRecipient(feeRecipient common.Address) {
// Start invokes the SimulatedBeacon life-cycle function in a goroutine.
func (c *SimulatedBeacon) Start() error {
if c.period == 0 {
- go c.loopOnDemand()
+ // if period is set to 0, do not mine at all
+ // this is used in the simulated backend where blocks
+ // are explicitly mined via Commit, AdjustTime and Fork
} else {
go c.loop()
}
@@ -131,10 +142,9 @@ func (c *SimulatedBeacon) Stop() error {
// sealBlock initiates payload building for a new block and creates a new block
// with the completed payload.
-func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal) error {
- tstamp := uint64(time.Now().Unix())
- if tstamp <= c.lastBlockTime {
- tstamp = c.lastBlockTime + 1
+func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp uint64) error {
+ if timestamp <= c.lastBlockTime {
+ timestamp = c.lastBlockTime + 1
}
c.feeRecipientLock.Lock()
feeRecipient := c.feeRecipient
@@ -148,19 +158,19 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal) error {
var random [32]byte
rand.Read(random[:])
- fcResponse, err := c.engineAPI.ForkchoiceUpdatedV2(c.curForkchoiceState, &engine.PayloadAttributes{
- Timestamp: tstamp,
+ fcResponse, err := c.engineAPI.forkchoiceUpdated(c.curForkchoiceState, &engine.PayloadAttributes{
+ Timestamp: timestamp,
SuggestedFeeRecipient: feeRecipient,
Withdrawals: withdrawals,
Random: random,
- })
+ BeaconRoot: &common.Hash{},
+ }, engine.PayloadV3, true)
if err != nil {
return err
}
if fcResponse == engine.STATUS_SYNCING {
return errors.New("chain rewind prevented invocation of payload creation")
}
-
envelope, err := c.engineAPI.getPayload(*fcResponse.PayloadID, true)
if err != nil {
return err
@@ -178,11 +188,25 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal) error {
}
}
+ // Independently calculate the blob hashes from sidecars.
+ blobHashes := make([]common.Hash, 0)
+ if envelope.BlobsBundle != nil {
+ hasher := sha256.New()
+ for _, commit := range envelope.BlobsBundle.Commitments {
+ var c kzg4844.Commitment
+ if len(commit) != len(c) {
+ return errors.New("invalid commitment length")
+ }
+ copy(c[:], commit)
+ blobHashes = append(blobHashes, kzg4844.CalcBlobHashV1(hasher, &c))
+ }
+ }
// Mark the payload as canon
- if _, err = c.engineAPI.NewPayloadV2(*payload); err != nil {
+ if _, err = c.engineAPI.NewPayloadV3(*payload, blobHashes, &common.Hash{}); err != nil {
return err
}
c.setCurrentState(payload.BlockHash, finalizedHash)
+
// Mark the block containing the payload as canonical
if _, err = c.engineAPI.ForkchoiceUpdatedV2(c.curForkchoiceState, nil); err != nil {
return err
@@ -191,32 +215,6 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal) error {
return nil
}
-// loopOnDemand runs the block production loop for "on-demand" configuration (period = 0)
-func (c *SimulatedBeacon) loopOnDemand() {
- var (
- newTxs = make(chan core.NewTxsEvent)
- sub = c.eth.TxPool().SubscribeTransactions(newTxs, true)
- )
- defer sub.Unsubscribe()
-
- for {
- select {
- case <-c.shutdownCh:
- return
- case w := <-c.withdrawals.pending:
- withdrawals := append(c.withdrawals.gatherPending(9), w)
- if err := c.sealBlock(withdrawals); err != nil {
- log.Warn("Error performing sealing work", "err", err)
- }
- case <-newTxs:
- withdrawals := c.withdrawals.gatherPending(10)
- if err := c.sealBlock(withdrawals); err != nil {
- log.Warn("Error performing sealing work", "err", err)
- }
- }
- }
-}
-
// loop runs the block production loop for non-zero period configuration
func (c *SimulatedBeacon) loop() {
timer := time.NewTimer(0)
@@ -226,7 +224,7 @@ func (c *SimulatedBeacon) loop() {
return
case <-timer.C:
withdrawals := c.withdrawals.gatherPending(10)
- if err := c.sealBlock(withdrawals); err != nil {
+ if err := c.sealBlock(withdrawals, uint64(time.Now().Unix())); err != nil {
log.Warn("Error performing sealing work", "err", err)
} else {
timer.Reset(time.Second * time.Duration(c.period))
@@ -235,8 +233,8 @@ func (c *SimulatedBeacon) loop() {
}
}
-// finalizedBlockHash returns the block hash of the finalized block corresponding to the given number
-// or nil if doesn't exist in the chain.
+// finalizedBlockHash returns the block hash of the finalized block corresponding
+// to the given number or nil if doesn't exist in the chain.
func (c *SimulatedBeacon) finalizedBlockHash(number uint64) *common.Hash {
var finalizedNumber uint64
if number%devEpochLength == 0 {
@@ -244,7 +242,6 @@ func (c *SimulatedBeacon) finalizedBlockHash(number uint64) *common.Hash {
} else {
finalizedNumber = (number - 1) / devEpochLength * devEpochLength
}
-
if finalizedBlock := c.eth.BlockChain().GetBlockByNumber(finalizedNumber); finalizedBlock != nil {
fh := finalizedBlock.Hash()
return &fh
@@ -261,11 +258,63 @@ func (c *SimulatedBeacon) setCurrentState(headHash, finalizedHash common.Hash) {
}
}
+// Commit seals a block on demand.
+func (c *SimulatedBeacon) Commit() common.Hash {
+ withdrawals := c.withdrawals.gatherPending(10)
+ if err := c.sealBlock(withdrawals, uint64(time.Now().Unix())); err != nil {
+ log.Warn("Error performing sealing work", "err", err)
+ }
+ return c.eth.BlockChain().CurrentBlock().Hash()
+}
+
+// Rollback un-sends previously added transactions.
+func (c *SimulatedBeacon) Rollback() {
+ // Flush all transactions from the transaction pools
+ maxUint256 := new(big.Int).Sub(new(big.Int).Lsh(common.Big1, 256), common.Big1)
+ c.eth.TxPool().SetGasTip(maxUint256)
+ // Set the gas tip back to accept new transactions
+ // TODO (Marius van der Wijden): set gas tip to parameter passed by config
+ c.eth.TxPool().SetGasTip(big.NewInt(params.GWei))
+}
+
+// Fork sets the head to the provided hash.
+func (c *SimulatedBeacon) Fork(parentHash common.Hash) error {
+ // Ensure no pending transactions.
+ c.eth.TxPool().Sync()
+ if len(c.eth.TxPool().Pending(txpool.PendingFilter{})) != 0 {
+ return errors.New("pending block dirty")
+ }
+
+ parent := c.eth.BlockChain().GetBlockByHash(parentHash)
+ if parent == nil {
+ return errors.New("parent not found")
+ }
+ return c.eth.BlockChain().SetHead(parent.NumberU64())
+}
+
+// AdjustTime creates a new block with an adjusted timestamp.
+func (c *SimulatedBeacon) AdjustTime(adjustment time.Duration) error {
+ if len(c.eth.TxPool().Pending(txpool.PendingFilter{})) != 0 {
+ return errors.New("could not adjust time on non-empty block")
+ }
+ parent := c.eth.BlockChain().CurrentBlock()
+ if parent == nil {
+ return errors.New("parent not found")
+ }
+ withdrawals := c.withdrawals.gatherPending(10)
+ return c.sealBlock(withdrawals, parent.Time+uint64(adjustment))
+}
+
func RegisterSimulatedBeaconAPIs(stack *node.Node, sim *SimulatedBeacon) {
+ api := &api{sim}
+ if sim.period == 0 {
+ // mine on demand if period is set to 0
+ go api.loop()
+ }
stack.RegisterAPIs([]rpc.API{
{
Namespace: "dev",
- Service: &api{sim},
+ Service: api,
Version: "1.0",
},
})
diff --git a/eth/catalyst/simulated_beacon_api.go b/eth/catalyst/simulated_beacon_api.go
index 93670257f6..73d0a5921d 100644
--- a/eth/catalyst/simulated_beacon_api.go
+++ b/eth/catalyst/simulated_beacon_api.go
@@ -18,19 +18,44 @@ package catalyst
import (
"context"
+ "time"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/log"
)
type api struct {
- simBeacon *SimulatedBeacon
+ sim *SimulatedBeacon
+}
+
+func (a *api) loop() {
+ var (
+ newTxs = make(chan core.NewTxsEvent)
+ sub = a.sim.eth.TxPool().SubscribeTransactions(newTxs, true)
+ )
+ defer sub.Unsubscribe()
+
+ for {
+ select {
+ case <-a.sim.shutdownCh:
+ return
+ case w := <-a.sim.withdrawals.pending:
+ withdrawals := append(a.sim.withdrawals.gatherPending(9), w)
+ if err := a.sim.sealBlock(withdrawals, uint64(time.Now().Unix())); err != nil {
+ log.Warn("Error performing sealing work", "err", err)
+ }
+ case <-newTxs:
+ a.sim.Commit()
+ }
+ }
}
func (a *api) AddWithdrawal(ctx context.Context, withdrawal *types.Withdrawal) error {
- return a.simBeacon.withdrawals.add(withdrawal)
+ return a.sim.withdrawals.add(withdrawal)
}
func (a *api) SetFeeRecipient(ctx context.Context, feeRecipient common.Address) {
- a.simBeacon.setFeeRecipient(feeRecipient)
+ a.sim.setFeeRecipient(feeRecipient)
}
diff --git a/eth/catalyst/simulated_beacon_test.go b/eth/catalyst/simulated_beacon_test.go
index a4dfb335f6..492f6b3ae4 100644
--- a/eth/catalyst/simulated_beacon_test.go
+++ b/eth/catalyst/simulated_beacon_test.go
@@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/ethconfig"
+ "github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/params"
@@ -48,7 +49,7 @@ func startSimulatedBeaconEthService(t *testing.T, genesis *core.Genesis) (*node.
t.Fatal("can't create node:", err)
}
- ethcfg := ðconfig.Config{Genesis: genesis, SyncMode: downloader.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256}
+ ethcfg := ðconfig.Config{Genesis: genesis, SyncMode: downloader.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256, Miner: miner.DefaultConfig}
ethservice, err := eth.New(n, ethcfg)
if err != nil {
t.Fatal("can't create eth service:", err)
@@ -74,7 +75,7 @@ func startSimulatedBeaconEthService(t *testing.T, genesis *core.Genesis) (*node.
func TestSimulatedBeaconSendWithdrawals(t *testing.T) {
t.Skip()
var withdrawals []types.Withdrawal
- txs := make(map[common.Hash]types.Transaction)
+ txs := make(map[common.Hash]*types.Transaction)
var (
// testKey is a private key to use for funding a tester account.
@@ -110,7 +111,7 @@ func TestSimulatedBeaconSendWithdrawals(t *testing.T) {
if err != nil {
t.Fatalf("error signing transaction, err=%v", err)
}
- txs[tx.Hash()] = *tx
+ txs[tx.Hash()] = tx
if err := ethService.APIBackend.SendTx(context.Background(), tx); err != nil {
t.Fatal("SendTx failed", err)
diff --git a/eth/downloader/api.go b/eth/downloader/api.go
index 27cea07233..ac175672a0 100644
--- a/eth/downloader/api.go
+++ b/eth/downloader/api.go
@@ -19,51 +19,80 @@ package downloader
import (
"context"
"sync"
+ "time"
"github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/rpc"
)
-// DownloaderAPI provides an API which gives information about the current synchronisation status.
-// It offers only methods that operates on data that can be available to anyone without security risks.
+// DownloaderAPI provides an API which gives information about the current
+// synchronisation status. It offers only methods that operates on data that
+// can be available to anyone without security risks.
type DownloaderAPI struct {
d *Downloader
+ chain *core.BlockChain
mux *event.TypeMux
installSyncSubscription chan chan interface{}
uninstallSyncSubscription chan *uninstallSyncSubscriptionRequest
}
-// NewDownloaderAPI create a new DownloaderAPI. The API has an internal event loop that
+// NewDownloaderAPI creates a new DownloaderAPI. The API has an internal event loop that
// listens for events from the downloader through the global event mux. In case it receives one of
// these events it broadcasts it to all syncing subscriptions that are installed through the
// installSyncSubscription channel.
-// nolint: staticcheck
-func NewDownloaderAPI(d *Downloader, m *event.TypeMux) *DownloaderAPI {
+func NewDownloaderAPI(d *Downloader, chain *core.BlockChain, m *event.TypeMux) *DownloaderAPI {
api := &DownloaderAPI{
d: d,
+ chain: chain,
mux: m,
installSyncSubscription: make(chan chan interface{}),
uninstallSyncSubscription: make(chan *uninstallSyncSubscriptionRequest),
}
-
go api.eventLoop()
-
return api
}
-// eventLoop runs a loop until the event mux closes. It will install and uninstall new
-// sync subscriptions and broadcasts sync status updates to the installed sync subscriptions.
+// eventLoop runs a loop until the event mux closes. It will install and uninstall
+// new sync subscriptions and broadcasts sync status updates to the installed sync
+// subscriptions.
+//
+// The sync status pushed to subscriptions can be a stream like:
+// >>> {Syncing: true, Progress: {...}}
+// >>> {false}
+//
+// If the node is already synced up, then only a single event subscribers will
+// receive is {false}.
func (api *DownloaderAPI) eventLoop() {
var (
- sub = api.mux.Subscribe(StartEvent{}, DoneEvent{}, FailedEvent{})
+ sub = api.mux.Subscribe(StartEvent{})
syncSubscriptions = make(map[chan interface{}]struct{})
+ checkInterval = time.Second * 60
+ checkTimer = time.NewTimer(checkInterval)
+
+ // status flags
+ started bool
+ done bool
+
+ getProgress = func() ethereum.SyncProgress {
+ prog := api.d.Progress()
+ if txProg, err := api.chain.TxIndexProgress(); err == nil {
+ prog.TxIndexFinishedBlocks = txProg.Indexed
+ prog.TxIndexRemainingBlocks = txProg.Remaining
+ }
+ return prog
+ }
)
+ defer checkTimer.Stop()
for {
select {
case i := <-api.installSyncSubscription:
syncSubscriptions[i] = struct{}{}
+ if done {
+ i <- false
+ }
case u := <-api.uninstallSyncSubscription:
delete(syncSubscriptions, u.c)
close(u.uninstalled)
@@ -71,26 +100,36 @@ func (api *DownloaderAPI) eventLoop() {
if event == nil {
return
}
-
- var notification interface{}
switch event.Data.(type) {
case StartEvent:
- notification = &SyncingResult{
+ started = true
+ }
+ case <-checkTimer.C:
+ if !started {
+ checkTimer.Reset(checkInterval)
+ continue
+ }
+ prog := getProgress()
+ if !prog.Done() {
+ notification := &SyncingResult{
Syncing: true,
- Status: api.d.Progress(),
+ Status: prog,
}
- case DoneEvent, FailedEvent:
- notification = false
+ for c := range syncSubscriptions {
+ c <- notification
+ }
+ checkTimer.Reset(checkInterval)
+ continue
}
- // broadcast
for c := range syncSubscriptions {
- c <- notification
+ c <- false
}
+ done = true
}
}
}
-// Syncing provides information when this nodes starts synchronising with the Ethereum network and when it's finished.
+// Syncing provides information when this node starts synchronising with the Ethereum network and when it's finished.
func (api *DownloaderAPI) Syncing(ctx context.Context) (*rpc.Subscription, error) {
notifier, supported := rpc.NotifierFromContext(ctx)
if !supported {
@@ -102,16 +141,13 @@ func (api *DownloaderAPI) Syncing(ctx context.Context) (*rpc.Subscription, error
go func() {
statuses := make(chan interface{})
sub := api.SubscribeSyncStatus(statuses)
+ defer sub.Unsubscribe()
for {
select {
case status := <-statuses:
notifier.Notify(rpcSub.ID, status)
case <-rpcSub.Err():
- sub.Unsubscribe()
- return
- case <-notifier.Closed():
- sub.Unsubscribe()
return
}
}
diff --git a/eth/downloader/downloader.go b/eth/downloader/bor_downloader.go
similarity index 95%
rename from eth/downloader/downloader.go
rename to eth/downloader/bor_downloader.go
index 4773275a1b..b4a11bfad1 100644
--- a/eth/downloader/downloader.go
+++ b/eth/downloader/bor_downloader.go
@@ -36,7 +36,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
var (
@@ -45,11 +45,10 @@ var (
MaxSkeletonSize = 128 // Number of header fetches to need for a skeleton assembly
MaxReceiptFetch = 256 // Amount of transaction receipts to allow fetching per request
- maxQueuedHeaders = 32 * 1024 // [eth/62] Maximum number of headers to queue for import (DOS protection)
- maxHeadersProcess = 2048 // Number of header download results to import at once into the chain
- maxResultsProcess = 2048 // Number of content download results to import at once into the chain
- fullMaxForkAncestry uint64 = params.FullImmutabilityThreshold // Maximum chain reorganisation (locally redeclared so tests can reduce it)
- lightMaxForkAncestry uint64 = params.LightImmutabilityThreshold // Maximum chain reorganisation (locally redeclared so tests can reduce it)
+ maxQueuedHeaders = 32 * 1024 // [eth/62] Maximum number of headers to queue for import (DOS protection)
+ maxHeadersProcess = 2048 // Number of header download results to import at once into the chain
+ maxResultsProcess = 2048 // Number of content download results to import at once into the chain
+ fullMaxForkAncestry uint64 = params.FullImmutabilityThreshold // Maximum chain reorganisation (locally redeclared so tests can reduce it)
reorgProtThreshold = 48 // Threshold number of recent blocks to disable mini reorg protection
reorgProtHeaderDelay = 2 // Number of headers to delay delivering to cover mini reorgs
@@ -102,9 +101,8 @@ type Downloader struct {
mode atomic.Uint32 // Synchronisation mode defining the strategy used (per sync cycle), use d.getMode() to get the SyncMode
mux *event.TypeMux // Event multiplexer to announce sync operation events
- genesis uint64 // Genesis block number to limit sync to (e.g. light client CHT)
- queue *queue // Scheduler for selecting the hashes to download
- peers *peerSet // Set of active peers from which download can proceed
+ queue *queue // Scheduler for selecting the hashes to download
+ peers *peerSet // Set of active peers from which download can proceed
stateDB ethdb.Database // Database to state sync into (and deduplicate via)
@@ -221,7 +219,7 @@ type BlockChain interface {
// TrieDB retrieves the low level trie database used for interacting
// with trie nodes.
- TrieDB() *trie.Database
+ TrieDB() *triedb.Database
}
// New creates a new downloader to fetch hashes and blocks from remote peers.
@@ -938,34 +936,11 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header)
// Recap floor value for binary search
maxForkAncestry := fullMaxForkAncestry
- if d.getMode() == LightSync {
- maxForkAncestry = lightMaxForkAncestry
- }
if localHeight >= maxForkAncestry {
// We're above the max reorg threshold, find the earliest fork point
floor = int64(localHeight - maxForkAncestry)
}
- // If we're doing a light sync, ensure the floor doesn't go below the CHT, as
- // all headers before that point will be missing.
- if mode == LightSync {
- // If we don't know the current CHT position, find it
- if d.genesis == 0 {
- header := d.lightchain.CurrentHeader()
- for header != nil {
- d.genesis = header.Number.Uint64()
- if floor >= int64(d.genesis)-1 {
- break
- }
-
- header = d.lightchain.GetHeaderByHash(header.ParentHash)
- }
- }
- // We already know the "genesis" block number, cap floor to that
- if floor < int64(d.genesis)-1 {
- floor = int64(d.genesis) - 1
- }
- }
ancestor, err := d.findAncestorSpanSearch(p, mode, remoteHeight, localHeight, floor)
if err == nil {
@@ -1134,7 +1109,6 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, head uint64) e
skeleton = true // Skeleton assembly phase or finishing up
pivoting = false // Whether the next request is pivot verification
ancestor = from
- mode = d.getMode()
)
for {
@@ -1293,14 +1267,11 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, head uint64) e
if n := len(headers); n > 0 {
// Retrieve the current head we're at
var head uint64
- if mode == LightSync {
- head = d.lightchain.CurrentHeader().Number.Uint64()
- } else {
- head = d.blockchain.CurrentSnapBlock().Number.Uint64()
- if full := d.blockchain.CurrentBlock().Number.Uint64(); head < full {
- head = full
- }
+ head = d.blockchain.CurrentSnapBlock().Number.Uint64()
+ if full := d.blockchain.CurrentBlock().Number.Uint64(); head < full {
+ head = full
}
+
// If the head is below the common ancestor, we're actually deduplicating
// already existing chain segments, so use the ancestor as the fake head.
// Otherwise, we might end up delaying header deliveries pointlessly.
@@ -1413,6 +1384,7 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode
mode = d.getMode()
gotHeaders = false // Wait for batches of headers to process
)
+
for {
select {
case <-d.cancelCh:
@@ -1432,23 +1404,9 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode
// violations from malicious peers. That is not needed in beacon
// mode and we can skip to terminating sync.
if !beaconMode {
- // If no headers were retrieved at all, the peer violated its TD promise that it had a
- // better chain compared to ours. The only exception is if its promised blocks were
- // already imported by other means (e.g. fetcher):
- //
- // R , L : Both at block 10
- // R: Mine block 11, and propagate it to L
- // L: Queue block 11 for import
- // L: Notice that R's head and TD increased compared to ours, start sync
- // L: Import of block 11 finishes
- // L: Sync begins, and finds common ancestor at 11
- // L: Request new headers up from 11 (R's TD was higher, it must have something)
- // R: Nothing to give
- if mode != LightSync {
- head := d.blockchain.CurrentBlock()
- if !gotHeaders && td.Cmp(d.blockchain.GetTd(head.Hash(), head.Number.Uint64())) > 0 {
- return errStallingPeer
- }
+ head := d.blockchain.CurrentBlock()
+ if !gotHeaders && td.Cmp(d.blockchain.GetTd(head.Hash(), head.Number.Uint64())) > 0 {
+ return errStallingPeer
}
// If snap or light syncing, ensure promised headers are indeed delivered. This is
// needed to detect scenarios where an attacker feeds a bad pivot and then bails out
@@ -1457,7 +1415,7 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode
// This check cannot be executed "as is" for full imports, since blocks may still be
// queued for processing when the header download completes. However, as long as the
// peer gave us something useful, we're already happy/progressed (above check).
- if mode == SnapSync || mode == LightSync {
+ if mode == SnapSync {
head := d.lightchain.CurrentHeader()
if td.Cmp(d.lightchain.GetTd(head.Hash(), head.Number.Uint64())) > 0 {
return errStallingPeer
@@ -1488,7 +1446,7 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode
chunkHashes := hashes[:limit]
// In case of header only syncing, validate the chunk immediately
- if mode == SnapSync || mode == LightSync {
+ if mode == SnapSync {
// Although the received headers might be all valid, a legacy
// PoW/PoA sync must not accept post-merge headers. Make sure
// that any transition is rejected at this point.
@@ -1653,7 +1611,11 @@ func (d *Downloader) importBlockResults(results []*fetchResult) error {
blocks := make([]*types.Block, len(results))
for i, result := range results {
- blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles).WithWithdrawals(result.Withdrawals)
+ blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(types.Body{
+ Transactions: result.Transactions,
+ Uncles: result.Uncles,
+ Withdrawals: result.Withdrawals,
+ })
}
// Downloaded blocks are always regarded as trusted after the
// transition. Because the downloaded chain is guided by the
@@ -1892,7 +1854,11 @@ func (d *Downloader) commitSnapSyncData(results []*fetchResult, stateSync *state
receipts := make([]types.Receipts, len(results))
for i, result := range results {
- blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles).WithWithdrawals(result.Withdrawals)
+ blocks[i] = types.NewBlockWithHeader(result.Header).WithBody(types.Body{
+ Transactions: result.Transactions,
+ Uncles: result.Uncles,
+ Withdrawals: result.Withdrawals,
+ })
receipts[i] = result.Receipts
}
@@ -1905,7 +1871,11 @@ func (d *Downloader) commitSnapSyncData(results []*fetchResult, stateSync *state
}
func (d *Downloader) commitPivotBlock(result *fetchResult) error {
- block := types.NewBlockWithHeader(result.Header).WithBody(result.Transactions, result.Uncles).WithWithdrawals(result.Withdrawals)
+ block := types.NewBlockWithHeader(result.Header).WithBody(types.Body{
+ Transactions: result.Transactions,
+ Uncles: result.Uncles,
+ Withdrawals: result.Withdrawals,
+ })
log.Debug("Committing snap sync pivot as new head", "number", block.Number(), "hash", block.Hash())
// Commit the pivot block as the new head, will require full sync from here on
diff --git a/eth/downloader/downloader_test.go b/eth/downloader/bor_downloader_test.go
similarity index 85%
rename from eth/downloader/downloader_test.go
rename to eth/downloader/bor_downloader_test.go
index 46d58f315b..884e9e1dd6 100644
--- a/eth/downloader/downloader_test.go
+++ b/eth/downloader/bor_downloader_test.go
@@ -78,7 +78,7 @@ func newTesterWithNotification(t *testing.T, success func()) *downloadTester {
gspec := &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}},
+ Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}},
BaseFee: big.NewInt(params.InitialBaseFee),
}
@@ -465,9 +465,6 @@ func assertOwnChain(t *testing.T, tester *downloadTester, length int) {
t.Helper()
headers, blocks, receipts := length, length, length
- if tester.downloader.getMode() == LightSync {
- blocks, receipts = 1, 1
- }
if hs := int(tester.chain.CurrentHeader().Number.Uint64()) + 1; hs != headers {
t.Fatalf("synchronised headers mismatch: have %v, want %v", hs, headers)
@@ -482,12 +479,10 @@ func assertOwnChain(t *testing.T, tester *downloadTester, length int) {
}
}
-func TestCanonicalSynchronisation68Full(t *testing.T) { testCanonSync(t, eth.ETH68, FullSync) }
-func TestCanonicalSynchronisation68Snap(t *testing.T) { testCanonSync(t, eth.ETH68, SnapSync) }
-func TestCanonicalSynchronisation68Light(t *testing.T) { testCanonSync(t, eth.ETH68, LightSync) }
-func TestCanonicalSynchronisation67Full(t *testing.T) { testCanonSync(t, eth.ETH67, FullSync) }
-func TestCanonicalSynchronisation67Snap(t *testing.T) { testCanonSync(t, eth.ETH67, SnapSync) }
-func TestCanonicalSynchronisation67Light(t *testing.T) { testCanonSync(t, eth.ETH67, LightSync) }
+func TestCanonicalSynchronisation68Full(t *testing.T) { testCanonSync(t, eth.ETH68, FullSync) }
+func TestCanonicalSynchronisation68Snap(t *testing.T) { testCanonSync(t, eth.ETH68, SnapSync) }
+func TestCanonicalSynchronisation67Full(t *testing.T) { testCanonSync(t, eth.ETH67, FullSync) }
+func TestCanonicalSynchronisation67Snap(t *testing.T) { testCanonSync(t, eth.ETH67, SnapSync) }
func testCanonSync(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -594,12 +589,10 @@ func testThrottling(t *testing.T, protocol uint, mode SyncMode) {
// Tests that simple synchronization against a forked chain works correctly. In
// this test common ancestor lookup should *not* be short circuited, and a full
// binary search should be executed.
-func TestForkedSync68Full(t *testing.T) { testForkedSync(t, eth.ETH68, FullSync) }
-func TestForkedSync68Snap(t *testing.T) { testForkedSync(t, eth.ETH68, SnapSync) }
-func TestForkedSync68Light(t *testing.T) { testForkedSync(t, eth.ETH68, LightSync) }
-func TestForkedSync67Full(t *testing.T) { testForkedSync(t, eth.ETH67, FullSync) }
-func TestForkedSync67Snap(t *testing.T) { testForkedSync(t, eth.ETH67, SnapSync) }
-func TestForkedSync67Light(t *testing.T) { testForkedSync(t, eth.ETH67, LightSync) }
+func TestForkedSync68Full(t *testing.T) { testForkedSync(t, eth.ETH68, FullSync) }
+func TestForkedSync68Snap(t *testing.T) { testForkedSync(t, eth.ETH68, SnapSync) }
+func TestForkedSync67Full(t *testing.T) { testForkedSync(t, eth.ETH67, FullSync) }
+func TestForkedSync67Snap(t *testing.T) { testForkedSync(t, eth.ETH67, SnapSync) }
func testForkedSync(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -626,12 +619,10 @@ func testForkedSync(t *testing.T, protocol uint, mode SyncMode) {
// Tests that synchronising against a much shorter but much heavier fork works
// currently and is not dropped.
-func TestHeavyForkedSync68Full(t *testing.T) { testHeavyForkedSync(t, eth.ETH68, FullSync) }
-func TestHeavyForkedSync68Snap(t *testing.T) { testHeavyForkedSync(t, eth.ETH68, SnapSync) }
-func TestHeavyForkedSync68Light(t *testing.T) { testHeavyForkedSync(t, eth.ETH68, LightSync) }
-func TestHeavyForkedSync67Full(t *testing.T) { testHeavyForkedSync(t, eth.ETH67, FullSync) }
-func TestHeavyForkedSync67Snap(t *testing.T) { testHeavyForkedSync(t, eth.ETH67, SnapSync) }
-func TestHeavyForkedSync67Light(t *testing.T) { testHeavyForkedSync(t, eth.ETH67, LightSync) }
+func TestHeavyForkedSync68Full(t *testing.T) { testHeavyForkedSync(t, eth.ETH68, FullSync) }
+func TestHeavyForkedSync68Snap(t *testing.T) { testHeavyForkedSync(t, eth.ETH68, SnapSync) }
+func TestHeavyForkedSync67Full(t *testing.T) { testHeavyForkedSync(t, eth.ETH67, FullSync) }
+func TestHeavyForkedSync67Snap(t *testing.T) { testHeavyForkedSync(t, eth.ETH67, SnapSync) }
func testHeavyForkedSync(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -660,12 +651,10 @@ func testHeavyForkedSync(t *testing.T, protocol uint, mode SyncMode) {
// Tests that chain forks are contained within a certain interval of the current
// chain head, ensuring that malicious peers cannot waste resources by feeding
// long dead chains.
-func TestBoundedForkedSync68Full(t *testing.T) { testBoundedForkedSync(t, eth.ETH68, FullSync) }
-func TestBoundedForkedSync68Snap(t *testing.T) { testBoundedForkedSync(t, eth.ETH68, SnapSync) }
-func TestBoundedForkedSync68Light(t *testing.T) { testBoundedForkedSync(t, eth.ETH68, LightSync) }
-func TestBoundedForkedSync67Full(t *testing.T) { testBoundedForkedSync(t, eth.ETH67, FullSync) }
-func TestBoundedForkedSync67Snap(t *testing.T) { testBoundedForkedSync(t, eth.ETH67, SnapSync) }
-func TestBoundedForkedSync67Light(t *testing.T) { testBoundedForkedSync(t, eth.ETH67, LightSync) }
+func TestBoundedForkedSync68Full(t *testing.T) { testBoundedForkedSync(t, eth.ETH68, FullSync) }
+func TestBoundedForkedSync68Snap(t *testing.T) { testBoundedForkedSync(t, eth.ETH68, SnapSync) }
+func TestBoundedForkedSync67Full(t *testing.T) { testBoundedForkedSync(t, eth.ETH67, FullSync) }
+func TestBoundedForkedSync67Snap(t *testing.T) { testBoundedForkedSync(t, eth.ETH67, SnapSync) }
func testBoundedForkedSync(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -699,9 +688,7 @@ func TestBoundedHeavyForkedSync68Full(t *testing.T) {
func TestBoundedHeavyForkedSync68Snap(t *testing.T) {
testBoundedHeavyForkedSync(t, eth.ETH68, SnapSync)
}
-func TestBoundedHeavyForkedSync68Light(t *testing.T) {
- testBoundedHeavyForkedSync(t, eth.ETH68, LightSync)
-}
+
func TestBoundedHeavyForkedSync67Full(t *testing.T) {
t.Parallel()
testBoundedHeavyForkedSync(t, eth.ETH67, FullSync)
@@ -710,10 +697,6 @@ func TestBoundedHeavyForkedSync67Snap(t *testing.T) {
t.Parallel()
testBoundedHeavyForkedSync(t, eth.ETH67, SnapSync)
}
-func TestBoundedHeavyForkedSync67Light(t *testing.T) {
- t.Parallel()
- testBoundedHeavyForkedSync(t, eth.ETH67, LightSync)
-}
func testBoundedHeavyForkedSync(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -740,12 +723,10 @@ func testBoundedHeavyForkedSync(t *testing.T, protocol uint, mode SyncMode) {
}
// Tests that a canceled download wipes all previously accumulated state.
-func TestCancel68Full(t *testing.T) { testCancel(t, eth.ETH68, FullSync) }
-func TestCancel68Snap(t *testing.T) { testCancel(t, eth.ETH68, SnapSync) }
-func TestCancel68Light(t *testing.T) { testCancel(t, eth.ETH68, LightSync) }
-func TestCancel67Full(t *testing.T) { testCancel(t, eth.ETH67, FullSync) }
-func TestCancel67Snap(t *testing.T) { testCancel(t, eth.ETH67, SnapSync) }
-func TestCancel67Light(t *testing.T) { testCancel(t, eth.ETH67, LightSync) }
+func TestCancel68Full(t *testing.T) { testCancel(t, eth.ETH68, FullSync) }
+func TestCancel68Snap(t *testing.T) { testCancel(t, eth.ETH68, SnapSync) }
+func TestCancel67Full(t *testing.T) { testCancel(t, eth.ETH67, FullSync) }
+func TestCancel67Snap(t *testing.T) { testCancel(t, eth.ETH67, SnapSync) }
func testCancel(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -773,12 +754,10 @@ func testCancel(t *testing.T, protocol uint, mode SyncMode) {
}
// Tests that synchronisation from multiple peers works as intended (multi thread sanity test).
-func TestMultiSynchronisation68Full(t *testing.T) { testMultiSynchronisation(t, eth.ETH68, FullSync) }
-func TestMultiSynchronisation68Snap(t *testing.T) { testMultiSynchronisation(t, eth.ETH68, SnapSync) }
-func TestMultiSynchronisation68Light(t *testing.T) { testMultiSynchronisation(t, eth.ETH68, LightSync) }
-func TestMultiSynchronisation67Full(t *testing.T) { testMultiSynchronisation(t, eth.ETH67, FullSync) }
-func TestMultiSynchronisation67Snap(t *testing.T) { testMultiSynchronisation(t, eth.ETH67, SnapSync) }
-func TestMultiSynchronisation67Light(t *testing.T) { testMultiSynchronisation(t, eth.ETH67, LightSync) }
+func TestMultiSynchronisation68Full(t *testing.T) { testMultiSynchronisation(t, eth.ETH68, FullSync) }
+func TestMultiSynchronisation68Snap(t *testing.T) { testMultiSynchronisation(t, eth.ETH68, SnapSync) }
+func TestMultiSynchronisation67Full(t *testing.T) { testMultiSynchronisation(t, eth.ETH67, FullSync) }
+func TestMultiSynchronisation67Snap(t *testing.T) { testMultiSynchronisation(t, eth.ETH67, SnapSync) }
func testMultiSynchronisation(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -802,12 +781,10 @@ func testMultiSynchronisation(t *testing.T, protocol uint, mode SyncMode) {
// Tests that synchronisations behave well in multi-version protocol environments
// and not wreak havoc on other nodes in the network.
-func TestMultiProtoSynchronisation68Full(t *testing.T) { testMultiProtoSync(t, eth.ETH68, FullSync) }
-func TestMultiProtoSynchronisation68Snap(t *testing.T) { testMultiProtoSync(t, eth.ETH68, SnapSync) }
-func TestMultiProtoSynchronisation68Light(t *testing.T) { testMultiProtoSync(t, eth.ETH68, LightSync) }
-func TestMultiProtoSynchronisation67Full(t *testing.T) { testMultiProtoSync(t, eth.ETH67, FullSync) }
-func TestMultiProtoSynchronisation67Snap(t *testing.T) { testMultiProtoSync(t, eth.ETH67, SnapSync) }
-func TestMultiProtoSynchronisation67Light(t *testing.T) { testMultiProtoSync(t, eth.ETH67, LightSync) }
+func TestMultiProtoSynchronisation68Full(t *testing.T) { testMultiProtoSync(t, eth.ETH68, FullSync) }
+func TestMultiProtoSynchronisation68Snap(t *testing.T) { testMultiProtoSync(t, eth.ETH68, SnapSync) }
+func TestMultiProtoSynchronisation67Full(t *testing.T) { testMultiProtoSync(t, eth.ETH67, FullSync) }
+func TestMultiProtoSynchronisation67Snap(t *testing.T) { testMultiProtoSync(t, eth.ETH67, SnapSync) }
func testMultiProtoSync(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -838,12 +815,10 @@ func testMultiProtoSync(t *testing.T, protocol uint, mode SyncMode) {
// Tests that if a block is empty (e.g. header only), no body request should be
// made, and instead the header should be assembled into a whole block in itself.
-func TestEmptyShortCircuit68Full(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, FullSync) }
-func TestEmptyShortCircuit68Snap(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, SnapSync) }
-func TestEmptyShortCircuit68Light(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, LightSync) }
-func TestEmptyShortCircuit67Full(t *testing.T) { testEmptyShortCircuit(t, eth.ETH67, FullSync) }
-func TestEmptyShortCircuit67Snap(t *testing.T) { testEmptyShortCircuit(t, eth.ETH67, SnapSync) }
-func TestEmptyShortCircuit67Light(t *testing.T) { testEmptyShortCircuit(t, eth.ETH67, LightSync) }
+func TestEmptyShortCircuit68Full(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, FullSync) }
+func TestEmptyShortCircuit68Snap(t *testing.T) { testEmptyShortCircuit(t, eth.ETH68, SnapSync) }
+func TestEmptyShortCircuit67Full(t *testing.T) { testEmptyShortCircuit(t, eth.ETH67, FullSync) }
+func TestEmptyShortCircuit67Snap(t *testing.T) { testEmptyShortCircuit(t, eth.ETH67, SnapSync) }
func testEmptyShortCircuit(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -873,7 +848,7 @@ func testEmptyShortCircuit(t *testing.T, protocol uint, mode SyncMode) {
bodiesNeeded, receiptsNeeded := 0, 0
for _, block := range chain.blocks[1:] {
- if mode != LightSync && (len(block.Transactions()) > 0 || len(block.Uncles()) > 0) {
+ if len(block.Transactions()) > 0 || len(block.Uncles()) > 0 {
bodiesNeeded++
}
}
@@ -895,12 +870,10 @@ func testEmptyShortCircuit(t *testing.T, protocol uint, mode SyncMode) {
// Tests that headers are enqueued continuously, preventing malicious nodes from
// stalling the downloader by feeding gapped header chains.
-func TestMissingHeaderAttack68Full(t *testing.T) { testMissingHeaderAttack(t, eth.ETH68, FullSync) }
-func TestMissingHeaderAttack68Snap(t *testing.T) { testMissingHeaderAttack(t, eth.ETH68, SnapSync) }
-func TestMissingHeaderAttack68Light(t *testing.T) { testMissingHeaderAttack(t, eth.ETH68, LightSync) }
-func TestMissingHeaderAttack67Full(t *testing.T) { testMissingHeaderAttack(t, eth.ETH67, FullSync) }
-func TestMissingHeaderAttack67Snap(t *testing.T) { testMissingHeaderAttack(t, eth.ETH67, SnapSync) }
-func TestMissingHeaderAttack67Light(t *testing.T) { testMissingHeaderAttack(t, eth.ETH67, LightSync) }
+func TestMissingHeaderAttack68Full(t *testing.T) { testMissingHeaderAttack(t, eth.ETH68, FullSync) }
+func TestMissingHeaderAttack68Snap(t *testing.T) { testMissingHeaderAttack(t, eth.ETH68, SnapSync) }
+func TestMissingHeaderAttack67Full(t *testing.T) { testMissingHeaderAttack(t, eth.ETH67, FullSync) }
+func TestMissingHeaderAttack67Snap(t *testing.T) { testMissingHeaderAttack(t, eth.ETH67, SnapSync) }
func testMissingHeaderAttack(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -926,12 +899,10 @@ func testMissingHeaderAttack(t *testing.T, protocol uint, mode SyncMode) {
// Tests that if requested headers are shifted (i.e. first is missing), the queue
// detects the invalid numbering.
-func TestShiftedHeaderAttack68Full(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH68, FullSync) }
-func TestShiftedHeaderAttack68Snap(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH68, SnapSync) }
-func TestShiftedHeaderAttack68Light(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH68, LightSync) }
-func TestShiftedHeaderAttack67Full(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH67, FullSync) }
-func TestShiftedHeaderAttack67Snap(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH67, SnapSync) }
-func TestShiftedHeaderAttack67Light(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH67, LightSync) }
+func TestShiftedHeaderAttack68Full(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH68, FullSync) }
+func TestShiftedHeaderAttack68Snap(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH68, SnapSync) }
+func TestShiftedHeaderAttack67Full(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH67, FullSync) }
+func TestShiftedHeaderAttack67Snap(t *testing.T) { testShiftedHeaderAttack(t, eth.ETH67, SnapSync) }
func testShiftedHeaderAttack(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -964,9 +935,7 @@ func TestHighTDStarvationAttack68Full(t *testing.T) {
func TestHighTDStarvationAttack68Snap(t *testing.T) {
testHighTDStarvationAttack(t, eth.ETH68, SnapSync)
}
-func TestHighTDStarvationAttack68Light(t *testing.T) {
- testHighTDStarvationAttack(t, eth.ETH68, LightSync)
-}
+
func TestHighTDStarvationAttack67Full(t *testing.T) {
t.Parallel()
testHighTDStarvationAttack(t, eth.ETH67, FullSync)
@@ -975,10 +944,6 @@ func TestHighTDStarvationAttack67Snap(t *testing.T) {
t.Parallel()
testHighTDStarvationAttack(t, eth.ETH67, SnapSync)
}
-func TestHighTDStarvationAttack67Light(t *testing.T) {
- t.Parallel()
- testHighTDStarvationAttack(t, eth.ETH67, LightSync)
-}
func testHighTDStarvationAttack(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -1045,12 +1010,10 @@ func testBlockHeaderAttackerDropping(t *testing.T, protocol uint) {
// Tests that synchronisation progress (origin block number, current block number
// and highest block number) is tracked and updated correctly.
-func TestSyncProgress68Full(t *testing.T) { testSyncProgress(t, eth.ETH68, FullSync) }
-func TestSyncProgress68Snap(t *testing.T) { testSyncProgress(t, eth.ETH68, SnapSync) }
-func TestSyncProgress68Light(t *testing.T) { testSyncProgress(t, eth.ETH68, LightSync) }
-func TestSyncProgress67Full(t *testing.T) { testSyncProgress(t, eth.ETH67, FullSync) }
-func TestSyncProgress67Snap(t *testing.T) { testSyncProgress(t, eth.ETH67, SnapSync) }
-func TestSyncProgress67Light(t *testing.T) { testSyncProgress(t, eth.ETH67, LightSync) }
+func TestSyncProgress68Full(t *testing.T) { testSyncProgress(t, eth.ETH68, FullSync) }
+func TestSyncProgress68Snap(t *testing.T) { testSyncProgress(t, eth.ETH68, SnapSync) }
+func TestSyncProgress67Full(t *testing.T) { testSyncProgress(t, eth.ETH67, FullSync) }
+func TestSyncProgress67Snap(t *testing.T) { testSyncProgress(t, eth.ETH67, SnapSync) }
func testSyncProgress(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -1132,12 +1095,10 @@ func checkProgress(t *testing.T, d *Downloader, stage string, want ethereum.Sync
// Tests that synchronisation progress (origin block number and highest block
// number) is tracked and updated correctly in case of a fork (or manual head
// revertal).
-func TestForkedSyncProgress68Full(t *testing.T) { testForkedSyncProgress(t, eth.ETH68, FullSync) }
-func TestForkedSyncProgress68Snap(t *testing.T) { testForkedSyncProgress(t, eth.ETH68, SnapSync) }
-func TestForkedSyncProgress68Light(t *testing.T) { testForkedSyncProgress(t, eth.ETH68, LightSync) }
-func TestForkedSyncProgress67Full(t *testing.T) { testForkedSyncProgress(t, eth.ETH67, FullSync) }
-func TestForkedSyncProgress67Snap(t *testing.T) { testForkedSyncProgress(t, eth.ETH67, SnapSync) }
-func TestForkedSyncProgress67Light(t *testing.T) { testForkedSyncProgress(t, eth.ETH67, LightSync) }
+func TestForkedSyncProgress68Full(t *testing.T) { testForkedSyncProgress(t, eth.ETH68, FullSync) }
+func TestForkedSyncProgress68Snap(t *testing.T) { testForkedSyncProgress(t, eth.ETH68, SnapSync) }
+func TestForkedSyncProgress67Full(t *testing.T) { testForkedSyncProgress(t, eth.ETH67, FullSync) }
+func TestForkedSyncProgress67Snap(t *testing.T) { testForkedSyncProgress(t, eth.ETH67, SnapSync) }
func testForkedSyncProgress(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -1214,12 +1175,10 @@ func testForkedSyncProgress(t *testing.T, protocol uint, mode SyncMode) {
// Tests that if synchronisation is aborted due to some failure, then the progress
// origin is not updated in the next sync cycle, as it should be considered the
// continuation of the previous sync and not a new instance.
-func TestFailedSyncProgress68Full(t *testing.T) { testFailedSyncProgress(t, eth.ETH68, FullSync) }
-func TestFailedSyncProgress68Snap(t *testing.T) { testFailedSyncProgress(t, eth.ETH68, SnapSync) }
-func TestFailedSyncProgress68Light(t *testing.T) { testFailedSyncProgress(t, eth.ETH68, LightSync) }
-func TestFailedSyncProgress67Full(t *testing.T) { testFailedSyncProgress(t, eth.ETH67, FullSync) }
-func TestFailedSyncProgress67Snap(t *testing.T) { testFailedSyncProgress(t, eth.ETH67, SnapSync) }
-func TestFailedSyncProgress67Light(t *testing.T) { testFailedSyncProgress(t, eth.ETH67, LightSync) }
+func TestFailedSyncProgress68Full(t *testing.T) { testFailedSyncProgress(t, eth.ETH68, FullSync) }
+func TestFailedSyncProgress68Snap(t *testing.T) { testFailedSyncProgress(t, eth.ETH68, SnapSync) }
+func TestFailedSyncProgress67Full(t *testing.T) { testFailedSyncProgress(t, eth.ETH67, FullSync) }
+func TestFailedSyncProgress67Snap(t *testing.T) { testFailedSyncProgress(t, eth.ETH67, SnapSync) }
func testFailedSyncProgress(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
@@ -1291,12 +1250,10 @@ func testFailedSyncProgress(t *testing.T, protocol uint, mode SyncMode) {
// Tests that if an attacker fakes a chain height, after the attack is detected,
// the progress height is successfully reduced at the next sync invocation.
-func TestFakedSyncProgress68Full(t *testing.T) { testFakedSyncProgress(t, eth.ETH68, FullSync) }
-func TestFakedSyncProgress68Snap(t *testing.T) { testFakedSyncProgress(t, eth.ETH68, SnapSync) }
-func TestFakedSyncProgress68Light(t *testing.T) { testFakedSyncProgress(t, eth.ETH68, LightSync) }
-func TestFakedSyncProgress67Full(t *testing.T) { testFakedSyncProgress(t, eth.ETH67, FullSync) }
-func TestFakedSyncProgress67Snap(t *testing.T) { testFakedSyncProgress(t, eth.ETH67, SnapSync) }
-func TestFakedSyncProgress67Light(t *testing.T) { testFakedSyncProgress(t, eth.ETH67, LightSync) }
+func TestFakedSyncProgress68Full(t *testing.T) { testFakedSyncProgress(t, eth.ETH68, FullSync) }
+func TestFakedSyncProgress68Snap(t *testing.T) { testFakedSyncProgress(t, eth.ETH68, SnapSync) }
+func TestFakedSyncProgress67Full(t *testing.T) { testFakedSyncProgress(t, eth.ETH67, FullSync) }
+func TestFakedSyncProgress67Snap(t *testing.T) { testFakedSyncProgress(t, eth.ETH67, SnapSync) }
func testFakedSyncProgress(t *testing.T, protocol uint, mode SyncMode) {
tester := newTester(t)
diff --git a/eth/downloader/fetchers.go b/eth/downloader/bor_fetchers.go
similarity index 100%
rename from eth/downloader/fetchers.go
rename to eth/downloader/bor_fetchers.go
diff --git a/eth/downloader/fetchers_concurrent.go b/eth/downloader/bor_fetchers_concurrent.go
similarity index 100%
rename from eth/downloader/fetchers_concurrent.go
rename to eth/downloader/bor_fetchers_concurrent.go
diff --git a/eth/downloader/fetchers_concurrent_bodies.go b/eth/downloader/bor_fetchers_concurrent_bodies.go
similarity index 99%
rename from eth/downloader/fetchers_concurrent_bodies.go
rename to eth/downloader/bor_fetchers_concurrent_bodies.go
index a9d9e70a12..e7d1732dc2 100644
--- a/eth/downloader/fetchers_concurrent_bodies.go
+++ b/eth/downloader/bor_fetchers_concurrent_bodies.go
@@ -80,7 +80,6 @@ func (q *bodyQueue) request(peer *peerConnection, req *fetchRequest, resCh chan
if q.bodyFetchHook != nil {
q.bodyFetchHook(req.Headers)
}
-
hashes := make([]common.Hash, 0, len(req.Headers))
for _, header := range req.Headers {
hashes = append(hashes, header.Hash())
diff --git a/eth/downloader/fetchers_concurrent_headers.go b/eth/downloader/bor_fetchers_concurrent_headers.go
similarity index 99%
rename from eth/downloader/fetchers_concurrent_headers.go
rename to eth/downloader/bor_fetchers_concurrent_headers.go
index 42df055bcf..e83826e562 100644
--- a/eth/downloader/fetchers_concurrent_headers.go
+++ b/eth/downloader/bor_fetchers_concurrent_headers.go
@@ -11,7 +11,7 @@
// 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
+// You should have received a copy of the GNU Lesser General Public Licenser
// along with the go-ethereum library. If not, see .
package downloader
diff --git a/eth/downloader/fetchers_concurrent_receipts.go b/eth/downloader/bor_fetchers_concurrent_receipts.go
similarity index 100%
rename from eth/downloader/fetchers_concurrent_receipts.go
rename to eth/downloader/bor_fetchers_concurrent_receipts.go
diff --git a/eth/downloader/modes.go b/eth/downloader/modes.go
index 58fd803ed5..65e76f7996 100644
--- a/eth/downloader/modes.go
+++ b/eth/downloader/modes.go
@@ -23,13 +23,12 @@ import "fmt"
type SyncMode uint32
const (
- FullSync SyncMode = iota // Synchronise the entire blockchain history from full blocks
- SnapSync // Download the chain and the state via compact snapshots
- LightSync // Download only the headers and terminate afterwards
+ FullSync SyncMode = iota // Synchronise the entire blockchain history from full blocks
+ SnapSync // Download the chain and the state via compact snapshots
)
func (mode SyncMode) IsValid() bool {
- return mode >= FullSync && mode <= LightSync
+ return mode == FullSync || mode == SnapSync
}
// String implements the stringer interface.
@@ -39,8 +38,6 @@ func (mode SyncMode) String() string {
return "full"
case SnapSync:
return "snap"
- case LightSync:
- return "light"
default:
return "unknown"
}
@@ -52,8 +49,6 @@ func (mode SyncMode) MarshalText() ([]byte, error) {
return []byte("full"), nil
case SnapSync:
return []byte("snap"), nil
- case LightSync:
- return []byte("light"), nil
default:
return nil, fmt.Errorf("unknown sync mode %d", mode)
}
@@ -65,10 +60,8 @@ func (mode *SyncMode) UnmarshalText(text []byte) error {
*mode = FullSync
case "snap":
*mode = SnapSync
- case "light":
- *mode = LightSync
default:
- return fmt.Errorf(`unknown sync mode %q, want "full", "snap" or "light"`, text)
+ return fmt.Errorf(`unknown sync mode %q, want "full" or "snap"`, text)
}
return nil
diff --git a/eth/downloader/queue.go b/eth/downloader/queue.go
index 77045a6f1d..25e7ed84d8 100644
--- a/eth/downloader/queue.go
+++ b/eth/downloader/queue.go
@@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/prque"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/params"
@@ -88,6 +89,16 @@ func newFetchResult(header *types.Header, fastSync bool) *fetchResult {
return item
}
+// body returns a representation of the fetch result as a types.Body object.
+// nolint : unused
+func (f *fetchResult) body() types.Body {
+ return types.Body{
+ Transactions: f.Transactions,
+ Uncles: f.Uncles,
+ Withdrawals: f.Withdrawals,
+ }
+}
+
// SetBodyDone flags the body as finished.
func (f *fetchResult) SetBodyDone() {
if v := f.pending.Load(); (v & (1 << bodyType)) != 0 {
@@ -867,7 +878,7 @@ func (q *queue) DeliverBodies(id string, txLists [][]*types.Transaction, txListH
return errInvalidBody
}
for _, hash := range tx.BlobHashes() {
- if hash[0] != params.BlobTxHashVersion {
+ if !kzg4844.IsValidVersionedHash(hash[:]) {
return errInvalidBody
}
}
diff --git a/eth/downloader/queue_test.go b/eth/downloader/queue_test.go
index d262c122f1..2d2f9984f8 100644
--- a/eth/downloader/queue_test.go
+++ b/eth/downloader/queue_test.go
@@ -18,6 +18,7 @@ package downloader
import (
"fmt"
+ "log/slog"
"math/big"
"math/rand"
"os"
@@ -32,7 +33,6 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
- "golang.org/x/exp/slog"
)
// makeChain creates a chain of n blocks starting at and including parent.
diff --git a/eth/downloader/skeleton.go b/eth/downloader/skeleton.go
index 3a91f1ac7e..04fa5b46b3 100644
--- a/eth/downloader/skeleton.go
+++ b/eth/downloader/skeleton.go
@@ -161,7 +161,7 @@ type backfiller interface {
// on initial startup.
//
// The method should return the last block header that has been successfully
- // backfilled, or nil if the backfiller was not resumed.
+ // backfilled (in the current or a previous run), falling back to the genesis.
suspend() *types.Header
// resume requests the backfiller to start running fill or snap sync based on
@@ -388,14 +388,17 @@ func (s *skeleton) sync(head *types.Header) (*types.Header, error) {
done := make(chan struct{})
go func() {
defer close(done)
- if filled := s.filler.suspend(); filled != nil {
- // If something was filled, try to delete stale sync helpers. If
- // unsuccessful, warn the user, but not much else we can do (it's
- // a programming error, just let users report an issue and don't
- // choke in the meantime).
- if err := s.cleanStales(filled); err != nil {
- log.Error("Failed to clean stale beacon headers", "err", err)
- }
+ filled := s.filler.suspend()
+ if filled == nil {
+ log.Error("Latest filled block is not available")
+ return
+ }
+ // If something was filled, try to delete stale sync helpers. If
+ // unsuccessful, warn the user, but not much else we can do (it's
+ // a programming error, just let users report an issue and don't
+ // choke in the meantime).
+ if err := s.cleanStales(filled); err != nil {
+ log.Error("Failed to clean stale beacon headers", "err", err)
}
}()
// Wait for the suspend to finish, consuming head events in the meantime
@@ -1177,34 +1180,56 @@ func (s *skeleton) cleanStales(filled *types.Header) error {
number := filled.Number.Uint64()
log.Trace("Cleaning stale beacon headers", "filled", number, "hash", filled.Hash())
- // If the filled header is below the linked subchain, something's
- // corrupted internally. Report and error and refuse to do anything.
- if number < s.progress.Subchains[0].Tail {
+ // If the filled header is below the linked subchain, something's corrupted
+ // internally. Report and error and refuse to do anything.
+ if number+1 < s.progress.Subchains[0].Tail {
return fmt.Errorf("filled header below beacon header tail: %d < %d", number, s.progress.Subchains[0].Tail)
}
- // Subchain seems trimmable, push the tail forward up to the last
- // filled header and delete everything before it - if available. In
- // case we filled past the head, recreate the subchain with a new
- // head to keep it consistent with the data on disk.
+ // If nothing in subchain is filled, don't bother to do cleanup.
+ if number+1 == s.progress.Subchains[0].Tail {
+ return nil
+ }
+ // If the latest fill was on a different subchain, it means the backfiller
+ // was interrupted before it got to do any meaningful work, no cleanup
+ header := rawdb.ReadSkeletonHeader(s.db, filled.Number.Uint64())
+ if header == nil {
+ log.Debug("Filled header outside of skeleton range", "number", number, "head", s.progress.Subchains[0].Head, "tail", s.progress.Subchains[0].Tail)
+ return nil
+ } else if header.Hash() != filled.Hash() {
+ log.Debug("Filled header on different sidechain", "number", number, "filled", filled.Hash(), "skeleton", header.Hash())
+ return nil
+ }
var (
- start = s.progress.Subchains[0].Tail // start deleting from the first known header
- end = number // delete until the requested threshold
+ start uint64
+ end uint64
batch = s.db.NewBatch()
)
-
- s.progress.Subchains[0].Tail = number
- s.progress.Subchains[0].Next = filled.ParentHash
-
- if s.progress.Subchains[0].Head < number {
- // If more headers were filled than available, push the entire
- // subchain forward to keep tracking the node's block imports
- end = s.progress.Subchains[0].Head + 1 // delete the entire original range, including the head
- s.progress.Subchains[0].Head = number // assign a new head (tail is already assigned to this)
-
- // The entire original skeleton chain was deleted and a new one
- // defined. Make sure the new single-header chain gets pushed to
- // disk to keep internal state consistent.
- rawdb.WriteSkeletonHeader(batch, filled)
+ if number < s.progress.Subchains[0].Head {
+ // The skeleton chain is partially consumed, set the new tail as filled+1.
+ tail := rawdb.ReadSkeletonHeader(s.db, number+1)
+ if tail.ParentHash != filled.Hash() {
+ return fmt.Errorf("filled header is discontinuous with subchain: %d %s, please file an issue", number, filled.Hash())
+ }
+ start, end = s.progress.Subchains[0].Tail, number+1 // remove headers in [tail, filled]
+ s.progress.Subchains[0].Tail = tail.Number.Uint64()
+ s.progress.Subchains[0].Next = tail.ParentHash
+ } else {
+ // The skeleton chain is fully consumed, set both head and tail as filled.
+ start, end = s.progress.Subchains[0].Tail, filled.Number.Uint64() // remove headers in [tail, filled)
+ s.progress.Subchains[0].Tail = filled.Number.Uint64()
+ s.progress.Subchains[0].Next = filled.ParentHash
+
+ // If more headers were filled than available, push the entire subchain
+ // forward to keep tracking the node's block imports.
+ if number > s.progress.Subchains[0].Head {
+ end = s.progress.Subchains[0].Head + 1 // delete the entire original range, including the head
+ s.progress.Subchains[0].Head = number // assign a new head (tail is already assigned to this)
+
+ // The entire original skeleton chain was deleted and a new one
+ // defined. Make sure the new single-header chain gets pushed to
+ // disk to keep internal state consistent.
+ rawdb.WriteSkeletonHeader(batch, filled)
+ }
}
// Execute the trimming and the potential rewiring of the progress
s.saveSyncStatus(batch)
diff --git a/eth/downloader/testchain_test.go b/eth/downloader/testchain_test.go
index 38bcb2e7fe..303abc4da0 100644
--- a/eth/downloader/testchain_test.go
+++ b/eth/downloader/testchain_test.go
@@ -30,7 +30,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
// Test chain parameters.
@@ -41,10 +41,10 @@ var (
testGspec = &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}},
+ Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}},
BaseFee: big.NewInt(params.InitialBaseFee),
}
- testGenesis = testGspec.MustCommit(testDB, trie.NewDatabase(testDB, trie.HashDefaults))
+ testGenesis = testGspec.MustCommit(testDB, triedb.NewDatabase(testDB, triedb.HashDefaults))
)
// The common prefix of all test chains:
@@ -58,7 +58,6 @@ var pregenerated bool
func init() {
// Reduce some of the parameters to make the tester faster
fullMaxForkAncestry = 10000
- lightMaxForkAncestry = 10000
blockCacheMaxItems = 1024
fsHeaderSafetyNet = 256
fsHeaderContCheck = 500 * time.Millisecond
diff --git a/eth/downloader/whitelist/finality.go b/eth/downloader/whitelist/finality.go
index 7ab684d88a..6d8f981321 100644
--- a/eth/downloader/whitelist/finality.go
+++ b/eth/downloader/whitelist/finality.go
@@ -18,6 +18,7 @@ type finality[T rawdb.BlockFinality[T]] struct {
Number uint64 // Number , populated by reaching out to heimdall
interval uint64 // Interval, until which we can allow importing
doExist bool
+ name string // Name of the service (checkpoint or milestone)
}
type finalityService interface {
@@ -43,21 +44,33 @@ func (f *finality[T]) IsValidPeer(fetchHeadersByNumber func(number uint64, amoun
return isValidPeer(fetchHeadersByNumber, doExist, number, hash)
}
-// IsValidChain checks the validity of chain by comparing it
-// against the local checkpoint entry
-// todo: need changes
+// IsValidChain checks the validity of chain by comparing it against the local
+// whitelisted entry of checkpoint/milestone.
func (f *finality[T]) IsValidChain(currentHeader *types.Header, chain []*types.Header) (bool, error) {
// Return if we've received empty chain
if len(chain) == 0 {
return false, nil
}
- res, err := isValidChain(currentHeader, chain, f.doExist, f.Number, f.Hash)
+ return isValidChain(currentHeader, chain, f.doExist, f.Number, f.Hash)
+}
- return res, err
+// reportWhitelist logs the block number and hash if a new and unique entry is being inserted
+// and it doesn't log for duplicate/redundant entries.
+func (f *finality[T]) reportWhitelist(block uint64, hash common.Hash) {
+ msg := fmt.Sprintf("Whitelisting new %s from heimdall", f.name)
+ if !f.doExist {
+ log.Info(msg, "block", block, "hash", hash)
+ } else {
+ if f.Number != block && f.Hash != hash {
+ log.Info(msg, "block", block, "hash", hash)
+ }
+ }
}
func (f *finality[T]) Process(block uint64, hash common.Hash) {
+ f.reportWhitelist(block, hash)
+
f.doExist = true
f.Hash = hash
f.Number = block
diff --git a/eth/downloader/whitelist/service.go b/eth/downloader/whitelist/service.go
index 3c23e4a268..7e7e1985da 100644
--- a/eth/downloader/whitelist/service.go
+++ b/eth/downloader/whitelist/service.go
@@ -60,6 +60,7 @@ func NewService(db ethdb.Database) *Service {
Hash: checkpointHash,
interval: 256,
db: db,
+ name: "checkpoint",
},
},
@@ -70,6 +71,7 @@ func NewService(db ethdb.Database) *Service {
Hash: milestoneHash,
interval: 256,
db: db,
+ name: "milestone",
},
Locked: locked,
diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go
index 0b172a4db9..b49c6e6079 100644
--- a/eth/ethconfig/config.go
+++ b/eth/ethconfig/config.go
@@ -92,7 +92,7 @@ type Config struct {
SyncMode downloader.SyncMode
// This can be set to list of enrtree:// URLs which will be queried for
- // for nodes to connect to.
+ // nodes to connect to.
EthDiscoveryURLs []string
SnapDiscoveryURLs []string
@@ -157,6 +157,13 @@ type Config struct {
// Enables tracking of SHA3 preimages in the VM
EnablePreimageRecording bool
+ // Enables prefetching trie nodes for read operations too
+ EnableWitnessCollection bool `toml:"-"`
+
+ // Enables VM tracing
+ VMTrace string
+ VMTraceJsonConfig string
+
// Miscellaneous options
DocRoot string `toml:"-"`
diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go
index 4f6a15188b..082e093578 100644
--- a/eth/ethconfig/gen_config.go
+++ b/eth/ethconfig/gen_config.go
@@ -53,6 +53,9 @@ func (c Config) MarshalTOML() (interface{}, error) {
BlobPool blobpool.Config
GPO gasprice.Config
EnablePreimageRecording bool
+ EnableWitnessCollection bool `toml:"-"`
+ VMTrace string
+ VMTraceJsonConfig string
DocRoot string `toml:"-"`
RPCGasCap uint64
RPCReturnDataLimit uint64
@@ -106,6 +109,9 @@ func (c Config) MarshalTOML() (interface{}, error) {
enc.BlobPool = c.BlobPool
enc.GPO = c.GPO
enc.EnablePreimageRecording = c.EnablePreimageRecording
+ enc.EnableWitnessCollection = c.EnableWitnessCollection
+ enc.VMTrace = c.VMTrace
+ enc.VMTraceJsonConfig = c.VMTraceJsonConfig
enc.DocRoot = c.DocRoot
enc.RPCGasCap = c.RPCGasCap
enc.RPCReturnDataLimit = c.RPCReturnDataLimit
@@ -163,6 +169,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
BlobPool *blobpool.Config
GPO *gasprice.Config
EnablePreimageRecording *bool
+ EnableWitnessCollection *bool `toml:"-"`
+ VMTrace *string
+ VMTraceJsonConfig *string
DocRoot *string `toml:"-"`
RPCGasCap *uint64
RPCReturnDataLimit *uint64
@@ -289,6 +298,15 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
if dec.EnablePreimageRecording != nil {
c.EnablePreimageRecording = *dec.EnablePreimageRecording
}
+ if dec.EnableWitnessCollection != nil {
+ c.EnableWitnessCollection = *dec.EnableWitnessCollection
+ }
+ if dec.VMTrace != nil {
+ c.VMTrace = *dec.VMTrace
+ }
+ if dec.VMTraceJsonConfig != nil {
+ c.VMTraceJsonConfig = *dec.VMTraceJsonConfig
+ }
if dec.DocRoot != nil {
c.DocRoot = *dec.DocRoot
}
diff --git a/eth/fetcher/block_fetcher.go b/eth/fetcher/block_fetcher.go
index 171c02e217..84906ff2c9 100644
--- a/eth/fetcher/block_fetcher.go
+++ b/eth/fetcher/block_fetcher.go
@@ -736,7 +736,10 @@ func (f *BlockFetcher) loop() {
matched = true
if f.getBlock(hash) == nil {
- block := types.NewBlockWithHeader(announce.header).WithBody(task.transactions[i], task.uncles[i])
+ block := types.NewBlockWithHeader(announce.header).WithBody(types.Body{
+ Transactions: task.transactions[i],
+ Uncles: task.uncles[i],
+ })
block.ReceivedAt = task.time
block.AnnouncedAt = &task.announcedTime
blocks = append(blocks, block)
diff --git a/eth/fetcher/block_fetcher_test.go b/eth/fetcher/block_fetcher_test.go
index 556fd73dbd..121aa1f67a 100644
--- a/eth/fetcher/block_fetcher_test.go
+++ b/eth/fetcher/block_fetcher_test.go
@@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
var (
@@ -41,11 +42,11 @@ var (
testAddress = crypto.PubkeyToAddress(testKey.PublicKey)
gspec = &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}},
+ Alloc: types.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}},
BaseFee: big.NewInt(params.InitialBaseFee),
}
- genesis = gspec.MustCommit(testdb, trie.NewDatabase(testdb, trie.HashDefaults))
- unknownBlock = types.NewBlock(&types.Header{Root: types.EmptyRootHash, GasLimit: params.GenesisGasLimit, BaseFee: big.NewInt(params.InitialBaseFee)}, nil, nil, nil, trie.NewStackTrie(nil))
+ genesis = gspec.MustCommit(testdb, triedb.NewDatabase(testdb, triedb.HashDefaults))
+ unknownBlock = types.NewBlock(&types.Header{Root: types.EmptyRootHash, GasLimit: params.GenesisGasLimit, BaseFee: big.NewInt(params.InitialBaseFee)}, nil, nil, trie.NewStackTrie(nil))
)
// makeChain creates a chain of n blocks starting at and including parent.
diff --git a/eth/fetcher/tx_fetcher.go b/eth/fetcher/tx_fetcher.go
index c71d0aaf7c..9fa432bacf 100644
--- a/eth/fetcher/tx_fetcher.go
+++ b/eth/fetcher/tx_fetcher.go
@@ -70,10 +70,6 @@ const (
// txGatherSlack is the interval used to collate almost-expired announces
// with network fetches.
txGatherSlack = 100 * time.Millisecond
-
- // maxTxArrivalWait is the longest acceptable duration for the txArrivalWait
- // configuration value. Longer config values will default to this.
- maxTxArrivalWait = 500 * time.Millisecond
)
var (
@@ -200,42 +196,39 @@ type TxFetcher struct {
step chan struct{} // Notification channel when the fetcher loop iterates
clock mclock.Clock // Time wrapper to simulate in tests
rand *mrand.Rand // Randomizer to use in tests instead of map range loops (soft-random)
-
- txArrivalWait time.Duration // txArrivalWait is the time allowance before an announced transaction is explicitly requested.
}
// NewTxFetcher creates a transaction fetcher to retrieve transaction
// based on hash announcements.
-func NewTxFetcher(hasTx func(common.Hash) bool, addTxs func([]*types.Transaction) []error, fetchTxs func(string, []common.Hash) error, txArrivalWait time.Duration, dropPeer func(string)) *TxFetcher {
- return NewTxFetcherForTests(hasTx, addTxs, fetchTxs, txArrivalWait, dropPeer, mclock.System{}, nil)
+func NewTxFetcher(hasTx func(common.Hash) bool, addTxs func([]*types.Transaction) []error, fetchTxs func(string, []common.Hash) error, dropPeer func(string)) *TxFetcher {
+ return NewTxFetcherForTests(hasTx, addTxs, fetchTxs, dropPeer, mclock.System{}, nil)
}
// NewTxFetcherForTests is a testing method to mock out the realtime clock with
// a simulated version and the internal randomness with a deterministic one.
func NewTxFetcherForTests(
- hasTx func(common.Hash) bool, addTxs func([]*types.Transaction) []error, fetchTxs func(string, []common.Hash) error, txArrivalWait time.Duration, dropPeer func(string),
+ hasTx func(common.Hash) bool, addTxs func([]*types.Transaction) []error, fetchTxs func(string, []common.Hash) error, dropPeer func(string),
clock mclock.Clock, rand *mrand.Rand) *TxFetcher {
return &TxFetcher{
- notify: make(chan *txAnnounce),
- cleanup: make(chan *txDelivery),
- drop: make(chan *txDrop),
- quit: make(chan struct{}),
- waitlist: make(map[common.Hash]map[string]struct{}),
- waittime: make(map[common.Hash]mclock.AbsTime),
- waitslots: make(map[string]map[common.Hash]*txMetadata),
- announces: make(map[string]map[common.Hash]*txMetadata),
- announced: make(map[common.Hash]map[string]struct{}),
- fetching: make(map[common.Hash]string),
- requests: make(map[string]*txRequest),
- alternates: make(map[common.Hash]map[string]struct{}),
- underpriced: lru.NewCache[common.Hash, time.Time](maxTxUnderpricedSetSize),
- hasTx: hasTx,
- addTxs: addTxs,
- fetchTxs: fetchTxs,
- txArrivalWait: txArrivalWait,
- dropPeer: dropPeer,
- clock: clock,
- rand: rand,
+ notify: make(chan *txAnnounce),
+ cleanup: make(chan *txDelivery),
+ drop: make(chan *txDrop),
+ quit: make(chan struct{}),
+ waitlist: make(map[common.Hash]map[string]struct{}),
+ waittime: make(map[common.Hash]mclock.AbsTime),
+ waitslots: make(map[string]map[common.Hash]*txMetadata),
+ announces: make(map[string]map[common.Hash]*txMetadata),
+ announced: make(map[common.Hash]map[string]struct{}),
+ fetching: make(map[common.Hash]string),
+ requests: make(map[string]*txRequest),
+ alternates: make(map[common.Hash]map[string]struct{}),
+ underpriced: lru.NewCache[common.Hash, time.Time](maxTxUnderpricedSetSize),
+ hasTx: hasTx,
+ addTxs: addTxs,
+ fetchTxs: fetchTxs,
+ dropPeer: dropPeer,
+ clock: clock,
+ rand: rand,
}
}
@@ -401,16 +394,6 @@ func (f *TxFetcher) Drop(peer string) error {
// Start boots up the announcement based synchroniser, accepting and processing
// hash notifications and block fetches until termination requested.
func (f *TxFetcher) Start() {
- // the txArrivalWait duration should not be less than the txGatherSlack duration
- if f.txArrivalWait < txGatherSlack {
- f.txArrivalWait = txGatherSlack
- }
-
- // the txArrivalWait duration should not be greater than the maxTxArrivalWait duration
- if f.txArrivalWait > maxTxArrivalWait {
- f.txArrivalWait = maxTxArrivalWait
- }
-
go f.loop()
}
@@ -429,8 +412,6 @@ func (f *TxFetcher) loop() {
timeoutTrigger = make(chan struct{}, 1)
)
- log.Info("TxFetcher", "txArrivalWait", f.txArrivalWait.String())
-
for {
select {
case ann := <-f.notify:
@@ -535,7 +516,7 @@ func (f *TxFetcher) loop() {
actives := make(map[string]struct{})
for hash, instance := range f.waittime {
- if time.Duration(f.clock.Now()-instance)+txGatherSlack > f.txArrivalWait {
+ if time.Duration(f.clock.Now()-instance)+txGatherSlack > txArriveTimeout {
// Transaction expired without propagation, schedule for retrieval
if f.announced[hash] != nil {
panic("announce tracker already contains waitlist item")
@@ -846,7 +827,7 @@ func (f *TxFetcher) loop() {
// rescheduleWait iterates over all the transactions currently in the waitlist
// and schedules the movement into the fetcher for the earliest.
//
-// The method has a granularity of 'gatherSlack', since there's not much point in
+// The method has a granularity of 'txGatherSlack', since there's not much point in
// spinning over all the transactions just to maybe find one that should trigger
// a few ms earlier.
func (f *TxFetcher) rescheduleWait(timer *mclock.Timer, trigger chan struct{}) {
@@ -860,22 +841,21 @@ func (f *TxFetcher) rescheduleWait(timer *mclock.Timer, trigger chan struct{}) {
for _, instance := range f.waittime {
if earliest > instance {
earliest = instance
- if f.txArrivalWait-time.Duration(now-earliest) < gatherSlack {
+ if txArriveTimeout-time.Duration(now-earliest) < txGatherSlack {
break
}
}
}
- *timer = f.clock.AfterFunc(
- f.txArrivalWait-time.Duration(now-earliest),
- func() { trigger <- struct{}{} },
- )
+ *timer = f.clock.AfterFunc(txArriveTimeout-time.Duration(now-earliest), func() {
+ trigger <- struct{}{}
+ })
}
// rescheduleTimeout iterates over all the transactions currently in flight and
// schedules a cleanup run when the first would trigger.
//
-// The method has a granularity of 'gatherSlack', since there's not much point in
+// The method has a granularity of 'txGatherSlack', since there's not much point in
// spinning over all the transactions just to maybe find one that should trigger
// a few ms earlier.
//
@@ -903,7 +883,7 @@ func (f *TxFetcher) rescheduleTimeout(timer *mclock.Timer, trigger chan struct{}
if earliest > req.time {
earliest = req.time
- if txFetchTimeout-time.Duration(now-earliest) < gatherSlack {
+ if txFetchTimeout-time.Duration(now-earliest) < txGatherSlack {
break
}
}
diff --git a/eth/fetcher/tx_fetcher_test.go b/eth/fetcher/tx_fetcher_test.go
index c78080e940..11bb1b9558 100644
--- a/eth/fetcher/tx_fetcher_test.go
+++ b/eth/fetcher/tx_fetcher_test.go
@@ -20,6 +20,7 @@ import (
"errors"
"math/big"
"math/rand"
+ "slices"
"testing"
"time"
@@ -101,7 +102,6 @@ func TestTransactionFetcherWaiting(t *testing.T) {
func(common.Hash) bool { return false },
nil,
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -197,7 +197,6 @@ func TestTransactionFetcherWaitingWithMeta(t *testing.T) {
func(common.Hash) bool { return false },
nil,
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -400,7 +399,6 @@ func TestTransactionFetcherSkipWaiting(t *testing.T) {
func(common.Hash) bool { return false },
nil,
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -465,7 +463,6 @@ func TestTransactionFetcherSingletonRequesting(t *testing.T) {
func(common.Hash) bool { return false },
nil,
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -547,7 +544,6 @@ func TestTransactionFetcherFailedRescheduling(t *testing.T) {
<-proceed
return errors.New("peer disconnected")
},
- testTxArrivalWait,
nil,
)
},
@@ -618,7 +614,6 @@ func TestTransactionFetcherCleanup(t *testing.T) {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -659,7 +654,6 @@ func TestTransactionFetcherCleanupEmpty(t *testing.T) {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -699,7 +693,6 @@ func TestTransactionFetcherMissingRescheduling(t *testing.T) {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -747,7 +740,6 @@ func TestTransactionFetcherMissingCleanup(t *testing.T) {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -787,7 +779,6 @@ func TestTransactionFetcherBroadcasts(t *testing.T) {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -837,7 +828,6 @@ func TestTransactionFetcherWaitTimerResets(t *testing.T) {
func(common.Hash) bool { return false },
nil,
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -896,7 +886,6 @@ func TestTransactionFetcherTimeoutRescheduling(t *testing.T) {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -963,7 +952,6 @@ func TestTransactionFetcherTimeoutTimerResets(t *testing.T) {
func(common.Hash) bool { return false },
nil,
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -1023,7 +1011,6 @@ func TestTransactionFetcherRateLimiting(t *testing.T) {
func(common.Hash) bool { return false },
nil,
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -1054,7 +1041,6 @@ func TestTransactionFetcherBandwidthLimiting(t *testing.T) {
func(common.Hash) bool { return false },
nil,
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -1127,7 +1113,6 @@ func TestTransactionFetcherDoSProtection(t *testing.T) {
func(common.Hash) bool { return false },
nil,
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -1196,7 +1181,6 @@ func TestTransactionFetcherUnderpricedDedup(t *testing.T) {
return errs
},
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -1268,7 +1252,6 @@ func TestTransactionFetcherUnderpricedDoSProtection(t *testing.T) {
return errs
},
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -1292,7 +1275,6 @@ func TestTransactionFetcherOutOfBoundDeliveries(t *testing.T) {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -1347,7 +1329,6 @@ func TestTransactionFetcherDrop(t *testing.T) {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -1415,7 +1396,6 @@ func TestTransactionFetcherDropRescheduling(t *testing.T) {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -1462,7 +1442,6 @@ func TestInvalidAnnounceMetadata(t *testing.T) {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
func(peer string) { drop <- peer },
)
},
@@ -1531,7 +1510,6 @@ func TestTransactionFetcherFuzzCrash01(t *testing.T) {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -1560,7 +1538,6 @@ func TestTransactionFetcherFuzzCrash02(t *testing.T) {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -1591,7 +1568,6 @@ func TestTransactionFetcherFuzzCrash03(t *testing.T) {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
)
},
@@ -1629,7 +1605,6 @@ func TestTransactionFetcherFuzzCrash04(t *testing.T) {
<-proceed
return errors.New("peer disconnected")
},
- testTxArrivalWait,
nil,
)
},
@@ -1864,13 +1839,13 @@ func testTransactionFetcher(t *testing.T, tt txFetcherTest) {
}
for _, hash := range hashes {
- if !containsHash(request.hashes, hash) {
+ if !slices.Contains(request.hashes, hash) {
t.Errorf("step %d, peer %s: hash %x missing from requests", i, peer, hash)
}
}
for _, hash := range request.hashes {
- if !containsHash(hashes, hash) {
+ if !slices.Contains(hashes, hash) {
t.Errorf("step %d, peer %s: hash %x extra in requests", i, peer, hash)
}
}
@@ -1896,7 +1871,7 @@ func testTransactionFetcher(t *testing.T, tt txFetcherTest) {
var found bool
for _, req := range fetcher.requests {
- if containsHash(req.hashes, hash) {
+ if slices.Contains(req.hashes, hash) {
found = true
break
}
@@ -1944,13 +1919,13 @@ func testTransactionFetcher(t *testing.T, tt txFetcherTest) {
}
for _, hash := range hashes {
- if !containsHash(request.hashes, hash) {
+ if !slices.Contains(request.hashes, hash) {
t.Errorf("step %d, peer %s: hash %x missing from requests", i, peer, hash)
}
}
for _, hash := range request.hashes {
- if !containsHash(hashes, hash) {
+ if !slices.Contains(hashes, hash) {
t.Errorf("step %d, peer %s: hash %x extra in requests", i, peer, hash)
}
}
@@ -1964,7 +1939,7 @@ func testTransactionFetcher(t *testing.T, tt txFetcherTest) {
var found bool
for _, hs := range step.fetching {
- if containsHash(hs, ann.hash) {
+ if slices.Contains(hs, ann.hash) {
found = true
break
}
@@ -1983,7 +1958,7 @@ func testTransactionFetcher(t *testing.T, tt txFetcherTest) {
}
for hash := range fetcher.announced {
- if !containsHash(queued, hash) {
+ if !slices.Contains(queued, hash) {
t.Errorf("step %d: hash %x extra in announced", i, hash)
}
}
@@ -2042,17 +2017,6 @@ func containsHashInAnnounces(slice []announce, hash common.Hash) bool {
return false
}
-// containsHash returns whether a hash is contained within a hash slice.
-func containsHash(slice []common.Hash, hash common.Hash) bool {
- for _, have := range slice {
- if have == hash {
- return true
- }
- }
-
- return false
-}
-
// Tests that a transaction is forgotten after the timeout.
func TestTransactionForgotten(t *testing.T) {
fetcher := NewTxFetcher(
@@ -2065,7 +2029,6 @@ func TestTransactionForgotten(t *testing.T) {
return errs
},
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
func(string) {},
)
fetcher.Start()
diff --git a/eth/filters/IBackend.go b/eth/filters/IBackend.go
index c04f9b1d16..7dfd509f83 100644
--- a/eth/filters/IBackend.go
+++ b/eth/filters/IBackend.go
@@ -204,21 +204,6 @@ func (mr *MockBackendMockRecorder) HeaderByNumber(arg0, arg1 interface{}) *gomoc
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeaderByNumber", reflect.TypeOf((*MockBackend)(nil).HeaderByNumber), arg0, arg1)
}
-// PendingBlockAndReceipts mocks base method.
-func (m *MockBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) {
- m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "PendingBlockAndReceipts")
- ret0, _ := ret[0].(*types.Block)
- ret1, _ := ret[1].(types.Receipts)
- return ret0, ret1
-}
-
-// PendingBlockAndReceipts indicates an expected call of PendingBlockAndReceipts.
-func (mr *MockBackendMockRecorder) PendingBlockAndReceipts() *gomock.Call {
- mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PendingBlockAndReceipts", reflect.TypeOf((*MockBackend)(nil).PendingBlockAndReceipts))
-}
-
// ServiceFilter mocks base method.
func (m *MockBackend) ServiceFilter(arg0 context.Context, arg1 *bloombits.MatcherSession) {
m.ctrl.T.Helper()
diff --git a/eth/filters/IDatabase.go b/eth/filters/IDatabase.go
index 8b76b6ca00..1334c351e7 100644
--- a/eth/filters/IDatabase.go
+++ b/eth/filters/IDatabase.go
@@ -49,20 +49,6 @@ func (mr *MockDatabaseMockRecorder) Ancient(arg0, arg1 interface{}) *gomock.Call
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Ancient", reflect.TypeOf((*MockDatabase)(nil).Ancient), arg0, arg1)
}
-// AncientOffSet mocks base method.
-func (m *MockDatabase) AncientOffSet() uint64 {
- m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "AncientOffSet")
- ret0, _ := ret[0].(uint64)
- return ret0
-}
-
-// AncientOffSet indicates an expected call of AncientOffSet.
-func (mr *MockDatabaseMockRecorder) AncientOffSet() *gomock.Call {
- mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AncientOffSet", reflect.TypeOf((*MockDatabase)(nil).AncientOffSet))
-}
-
// AncientDatadir mocks base method.
func (m *MockDatabase) AncientDatadir() (string, error) {
m.ctrl.T.Helper()
@@ -78,6 +64,20 @@ func (mr *MockDatabaseMockRecorder) AncientDatadir() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AncientDatadir", reflect.TypeOf((*MockDatabase)(nil).AncientDatadir))
}
+// AncientOffSet mocks base method.
+func (m *MockDatabase) AncientOffSet() uint64 {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "AncientOffSet")
+ ret0, _ := ret[0].(uint64)
+ return ret0
+}
+
+// AncientOffSet indicates an expected call of AncientOffSet.
+func (mr *MockDatabaseMockRecorder) AncientOffSet() *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AncientOffSet", reflect.TypeOf((*MockDatabase)(nil).AncientOffSet))
+}
+
// AncientRange mocks base method.
func (m *MockDatabase) AncientRange(arg0 string, arg1, arg2, arg3 uint64) ([][]byte, error) {
m.ctrl.T.Helper()
@@ -340,18 +340,18 @@ func (mr *MockDatabaseMockRecorder) ReadAncients(arg0 interface{}) *gomock.Call
}
// Stat mocks base method.
-func (m *MockDatabase) Stat(arg0 string) (string, error) {
+func (m *MockDatabase) Stat() (string, error) {
m.ctrl.T.Helper()
- ret := m.ctrl.Call(m, "Stat", arg0)
+ ret := m.ctrl.Call(m, "Stat")
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Stat indicates an expected call of Stat.
-func (mr *MockDatabaseMockRecorder) Stat(arg0 interface{}) *gomock.Call {
+func (mr *MockDatabaseMockRecorder) Stat() *gomock.Call {
mr.mock.ctrl.T.Helper()
- return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stat", reflect.TypeOf((*MockDatabase)(nil).Stat), arg0)
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stat", reflect.TypeOf((*MockDatabase)(nil).Stat))
}
// Sync mocks base method.
diff --git a/eth/filters/api.go b/eth/filters/api.go
index 42a8d303c1..0d561bc83a 100644
--- a/eth/filters/api.go
+++ b/eth/filters/api.go
@@ -35,15 +35,19 @@ import (
)
var (
- errInvalidTopic = errors.New("invalid topic(s)")
- errFilterNotFound = errors.New("filter not found")
- errInvalidBlockRange = errors.New("invalid block range params")
- errExceedMaxTopics = errors.New("exceed max topics")
+ errInvalidTopic = errors.New("invalid topic(s)")
+ errFilterNotFound = errors.New("filter not found")
+ errInvalidBlockRange = errors.New("invalid block range params")
+ errPendingLogsUnsupported = errors.New("pending logs are not supported")
+ errExceedMaxTopics = errors.New("exceed max topics")
)
// The maximum number of topic criteria allowed, vm.LOG4 - vm.LOG0
const maxTopics = 4
+// The maximum number of allowed topics within a topic criteria
+const maxSubTopics = 1000
+
// filter is a helper struct that holds meta information over the filter type
// and associated subscription in the event system.
type filter struct {
@@ -71,10 +75,10 @@ type FilterAPI struct {
}
// NewFilterAPI returns a new FilterAPI instance.
-func NewFilterAPI(system *FilterSystem, lightMode bool, borLogs bool) *FilterAPI {
+func NewFilterAPI(system *FilterSystem, borLogs bool) *FilterAPI {
api := &FilterAPI{
sys: system,
- events: NewEventSystem(system, lightMode),
+ events: NewEventSystem(system),
filters: make(map[rpc.ID]*filter),
timeout: system.cfg.Timeout,
borLogs: borLogs,
@@ -169,6 +173,8 @@ func (api *FilterAPI) NewPendingTransactions(ctx context.Context, fullTx *bool)
go func() {
txs := make(chan []*types.Transaction, 128)
pendingTxSub := api.events.SubscribePendingTxs(txs)
+ defer pendingTxSub.Unsubscribe()
+
chainConfig := api.sys.backend.ChainConfig()
for {
@@ -187,10 +193,6 @@ func (api *FilterAPI) NewPendingTransactions(ctx context.Context, fullTx *bool)
}
}
case <-rpcSub.Err():
- pendingTxSub.Unsubscribe()
- return
- case <-notifier.Closed():
- pendingTxSub.Unsubscribe()
return
}
}
@@ -245,16 +247,13 @@ func (api *FilterAPI) NewHeads(ctx context.Context) (*rpc.Subscription, error) {
go func() {
headers := make(chan *types.Header)
headersSub := api.events.SubscribeNewHeads(headers)
+ defer headersSub.Unsubscribe()
for {
select {
case h := <-headers:
notifier.Notify(rpcSub.ID, h)
case <-rpcSub.Err():
- headersSub.Unsubscribe()
- return
- case <-notifier.Closed():
- headersSub.Unsubscribe()
return
}
}
@@ -281,6 +280,7 @@ func (api *FilterAPI) Logs(ctx context.Context, crit FilterCriteria) (*rpc.Subsc
}
go func() {
+ defer logsSub.Unsubscribe()
for {
select {
case logs := <-matchedLogs:
@@ -289,10 +289,6 @@ func (api *FilterAPI) Logs(ctx context.Context, crit FilterCriteria) (*rpc.Subsc
notifier.Notify(rpcSub.ID, &log)
}
case <-rpcSub.Err(): // client send an unsubscribe request
- logsSub.Unsubscribe()
- return
- case <-notifier.Closed(): // connection dropped
- logsSub.Unsubscribe()
return
}
}
@@ -356,7 +352,7 @@ func (api *FilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*type
return nil, errExceedMaxTopics
}
- borConfig := api.chainConfig.Bor
+ borConfig := api.sys.backend.ChainConfig().Bor
var filter *Filter
@@ -439,7 +435,7 @@ func (api *FilterAPI) GetFilterLogs(ctx context.Context, id rpc.ID) ([]*types.Lo
return nil, errFilterNotFound
}
- borConfig := api.chainConfig.Bor
+ borConfig := api.sys.backend.ChainConfig().Bor
var filter *Filter
@@ -537,7 +533,7 @@ func (api *FilterAPI) GetFilterChanges(id rpc.ID) (interface{}, error) {
return hashes, nil
}
- case LogsSubscription, MinedAndPendingLogsSubscription:
+ case LogsSubscription:
logs := f.logs
f.logs = nil
@@ -629,6 +625,9 @@ func (args *FilterCriteria) UnmarshalJSON(data []byte) error {
return errors.New("invalid addresses in query")
}
}
+ if len(raw.Topics) > maxTopics {
+ return errExceedMaxTopics
+ }
// topics is an array consisting of strings and/or arrays of strings.
// JSON null values are converted to common.Hash{} and ignored by the filter manager.
@@ -651,6 +650,9 @@ func (args *FilterCriteria) UnmarshalJSON(data []byte) error {
case []interface{}:
// or case e.g. [null, "topic0", "topic1"]
+ if len(topic) > maxSubTopics {
+ return errExceedMaxTopics
+ }
for _, rawTopic := range topic {
if rawTopic == nil {
// null component, match all
diff --git a/eth/filters/filter.go b/eth/filters/filter.go
index 4391a43a04..e286450fd5 100644
--- a/eth/filters/filter.go
+++ b/eth/filters/filter.go
@@ -20,6 +20,7 @@ import (
"context"
"errors"
"math/big"
+ "slices"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/bloombits"
@@ -115,19 +116,9 @@ func (f *Filter) Logs(ctx context.Context) ([]*types.Log, error) {
return f.blockLogs(ctx, header)
}
- var (
- beginPending = f.begin == rpc.PendingBlockNumber.Int64()
- endPending = f.end == rpc.PendingBlockNumber.Int64()
- )
-
- // special case for pending logs
- if beginPending && !endPending {
- return nil, errInvalidBlockRange
- }
-
- // Short-cut if all we care about is pending logs
- if beginPending && endPending {
- return f.pendingLogs(), nil
+ // Disallow pending logs.
+ if f.begin == rpc.PendingBlockNumber.Int64() || f.end == rpc.PendingBlockNumber.Int64() {
+ return nil, errPendingLogsUnsupported
}
resolveSpecial := func(number int64) (int64, error) {
@@ -175,16 +166,7 @@ func (f *Filter) Logs(ctx context.Context) ([]*types.Log, error) {
case log := <-logChan:
logs = append(logs, log)
case err := <-errChan:
- if err != nil {
- // if an error occurs during extraction, we do return the extracted data
- return logs, err
- }
- // Append the pending ones
- if endPending {
- pendingLogs := f.pendingLogs()
- logs = append(logs, pendingLogs...)
- }
- return logs, nil
+ return logs, err
}
}
}
@@ -349,32 +331,6 @@ func (f *Filter) checkMatches(ctx context.Context, header *types.Header) ([]*typ
return logs, nil
}
-// pendingLogs returns the logs matching the filter criteria within the pending block.
-func (f *Filter) pendingLogs() []*types.Log {
- block, receipts := f.sys.backend.PendingBlockAndReceipts()
- if block == nil || receipts == nil {
- return nil
- }
- if bloomFilter(block.Bloom(), f.addresses, f.topics) {
- var unfiltered []*types.Log
- for _, r := range receipts {
- unfiltered = append(unfiltered, r.Logs...)
- }
- return filterLogs(unfiltered, nil, nil, f.addresses, f.topics)
- }
- return nil
-}
-
-// includes returns true if the element is present in the list.
-func includes[T comparable](things []T, element T) bool {
- for _, thing := range things {
- if thing == element {
- return true
- }
- }
- return false
-}
-
// filterLogs creates a slice of logs matching the given criteria.
func filterLogs(logs []*types.Log, fromBlock, toBlock *big.Int, addresses []common.Address, topics [][]common.Hash) []*types.Log {
var check = func(log *types.Log) bool {
@@ -384,7 +340,7 @@ func filterLogs(logs []*types.Log, fromBlock, toBlock *big.Int, addresses []comm
if toBlock != nil && toBlock.Int64() >= 0 && toBlock.Uint64() < log.BlockNumber {
return false
}
- if len(addresses) > 0 && !includes(addresses, log.Address) {
+ if len(addresses) > 0 && !slices.Contains(addresses, log.Address) {
return false
}
// If the to filtered topics is greater than the amount of topics in logs, skip.
@@ -395,7 +351,7 @@ func filterLogs(logs []*types.Log, fromBlock, toBlock *big.Int, addresses []comm
if len(sub) == 0 {
continue // empty rule set == wildcard
}
- if !includes(sub, log.Topics[i]) {
+ if !slices.Contains(sub, log.Topics[i]) {
return false
}
}
diff --git a/eth/filters/filter_system.go b/eth/filters/filter_system.go
index 1a543664e9..5fb7b2cbe8 100644
--- a/eth/filters/filter_system.go
+++ b/eth/filters/filter_system.go
@@ -30,7 +30,6 @@ import (
"github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/bloombits"
- "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
@@ -65,7 +64,6 @@ type Backend interface {
GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error)
GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error)
GetLogs(ctx context.Context, blockHash common.Hash, number uint64) ([][]*types.Log, error)
- PendingBlockAndReceipts() (*types.Block, types.Receipts)
GetBorBlockReceipt(ctx context.Context, blockHash common.Hash) (*types.Receipt, error)
GetBorBlockLogs(ctx context.Context, blockHash common.Hash) ([]*types.Log, error)
@@ -102,7 +100,7 @@ func NewFilterSystem(backend Backend, config Config) *FilterSystem {
type logCacheElem struct {
logs []*types.Log
- body atomic.Value
+ body atomic.Pointer[types.Body]
}
// cachedLogElem loads block logs from the backend and caches the result.
@@ -146,7 +144,7 @@ func (sys *FilterSystem) cachedLogElem(ctx context.Context, blockHash common.Has
func (sys *FilterSystem) cachedGetBody(ctx context.Context, elem *logCacheElem, hash common.Hash, number uint64) (*types.Body, error) {
if body := elem.body.Load(); body != nil {
- return body.(*types.Body), nil
+ return body, nil
}
body, err := sys.backend.GetBody(ctx, hash, rpc.BlockNumber(number))
@@ -170,8 +168,6 @@ const (
LogsSubscription
// PendingLogsSubscription queries for logs in pending blocks
PendingLogsSubscription
- // MinedAndPendingLogsSubscription queries for logs in mined and pending blocks.
- MinedAndPendingLogsSubscription
// PendingTransactionsSubscription queries for pending transactions entering
// the pending state
PendingTransactionsSubscription
@@ -190,6 +186,8 @@ const (
// rmLogsChanSize is the size of channel listening to RemovedLogsEvent.
rmLogsChanSize = 10
// logsChanSize is the size of channel listening to LogsEvent.
+ // Updated to fix TestEth2NeBlock testcase, as the feed was unable to send
+ // logs to the channel. todo: @anshalshukla
logsChanSize = 10
// chainEvChanSize is the size of channel listening to ChainEvent.
chainEvChanSize = 10
@@ -214,10 +212,8 @@ type subscription struct {
// EventSystem creates subscriptions, processes events and broadcasts them to the
// subscription which match the subscription criteria.
type EventSystem struct {
- backend Backend
- sys *FilterSystem
- lightMode bool
- lastHead *types.Header
+ backend Backend
+ sys *FilterSystem
// Subscriptions
txsSub event.Subscription // Subscription for new transaction event
@@ -246,11 +242,10 @@ type EventSystem struct {
//
// The returned manager has a loop that needs to be stopped with the Stop function
// or by stopping the given mux.
-func NewEventSystem(sys *FilterSystem, lightMode bool) *EventSystem {
+func NewEventSystem(sys *FilterSystem) *EventSystem {
m := &EventSystem{
sys: sys,
backend: sys.backend,
- lightMode: lightMode,
install: make(chan *subscription),
uninstall: make(chan *subscription),
txsCh: make(chan core.NewTxsEvent, txChanSize),
@@ -345,10 +340,11 @@ func (es *EventSystem) SubscribeLogs(crit ethereum.FilterQuery, logs chan []*typ
to = rpc.BlockNumber(crit.ToBlock.Int64())
}
- // only interested in pending logs
- if from == rpc.PendingBlockNumber && to == rpc.PendingBlockNumber {
- return es.subscribePendingLogs(crit, logs), nil
+ // Pending logs are not supported anymore.
+ if from == rpc.PendingBlockNumber || to == rpc.PendingBlockNumber {
+ return nil, errPendingLogsUnsupported
}
+
// only interested in new mined logs
if from == rpc.LatestBlockNumber && to == rpc.LatestBlockNumber {
return es.subscribeLogs(crit, logs), nil
@@ -357,10 +353,6 @@ func (es *EventSystem) SubscribeLogs(crit ethereum.FilterQuery, logs chan []*typ
if from >= 0 && to >= 0 && to >= from {
return es.subscribeLogs(crit, logs), nil
}
- // interested in mined logs from a specific block number, new logs and pending logs
- if from >= rpc.LatestBlockNumber && to == rpc.PendingBlockNumber {
- return es.subscribeMinedPendingLogs(crit, logs), nil
- }
// interested in logs from a specific block number to new mined blocks
if from >= 0 && to == rpc.LatestBlockNumber {
return es.subscribeLogs(crit, logs), nil
@@ -368,24 +360,6 @@ func (es *EventSystem) SubscribeLogs(crit ethereum.FilterQuery, logs chan []*typ
return nil, errInvalidBlockRange
}
-// subscribeMinedPendingLogs creates a subscription that returned mined and
-// pending logs that match the given criteria.
-func (es *EventSystem) subscribeMinedPendingLogs(crit ethereum.FilterQuery, logs chan []*types.Log) *Subscription {
- sub := &subscription{
- id: rpc.NewID(),
- typ: MinedAndPendingLogsSubscription,
- logsCrit: crit,
- created: time.Now(),
- logs: logs,
- txs: make(chan []*types.Transaction),
- headers: make(chan *types.Header),
- installed: make(chan struct{}),
- err: make(chan error),
- }
-
- return es.subscribe(sub)
-}
-
// subscribeLogs creates a subscription that will write all logs matching the
// given criteria to the given logs channel.
func (es *EventSystem) subscribeLogs(crit ethereum.FilterQuery, logs chan []*types.Log) *Subscription {
@@ -404,24 +378,6 @@ func (es *EventSystem) subscribeLogs(crit ethereum.FilterQuery, logs chan []*typ
return es.subscribe(sub)
}
-// subscribePendingLogs creates a subscription that writes contract event logs for
-// transactions that enter the transaction pool.
-func (es *EventSystem) subscribePendingLogs(crit ethereum.FilterQuery, logs chan []*types.Log) *Subscription {
- sub := &subscription{
- id: rpc.NewID(),
- typ: PendingLogsSubscription,
- logsCrit: crit,
- created: time.Now(),
- logs: logs,
- txs: make(chan []*types.Transaction),
- headers: make(chan *types.Header),
- installed: make(chan struct{}),
- err: make(chan error),
- }
-
- return es.subscribe(sub)
-}
-
// SubscribeNewHeads creates a subscription that writes the header of a block that is
// imported in the chain.
func (es *EventSystem) SubscribeNewHeads(headers chan *types.Header) *Subscription {
@@ -494,104 +450,6 @@ func (es *EventSystem) handleChainEvent(filters filterIndex, ev core.ChainEvent)
for _, f := range filters[BlocksSubscription] {
f.headers <- ev.Block.Header()
}
-
- if es.lightMode && len(filters[LogsSubscription]) > 0 {
- es.lightFilterNewHead(ev.Block.Header(), func(header *types.Header, remove bool) {
- for _, f := range filters[LogsSubscription] {
- if f.logsCrit.FromBlock != nil && header.Number.Cmp(f.logsCrit.FromBlock) < 0 {
- continue
- }
-
- if f.logsCrit.ToBlock != nil && header.Number.Cmp(f.logsCrit.ToBlock) > 0 {
- continue
- }
-
- if matchedLogs := es.lightFilterLogs(header, f.logsCrit.Addresses, f.logsCrit.Topics, remove); len(matchedLogs) > 0 {
- f.logs <- matchedLogs
- }
- }
- })
- }
-}
-
-func (es *EventSystem) lightFilterNewHead(newHeader *types.Header, callBack func(*types.Header, bool)) {
- oldh := es.lastHead
- es.lastHead = newHeader
-
- if oldh == nil {
- return
- }
-
- newh := newHeader
- // find common ancestor, create list of rolled back and new block hashes
- var oldHeaders, newHeaders []*types.Header
-
- for oldh.Hash() != newh.Hash() {
- if oldh.Number.Uint64() >= newh.Number.Uint64() {
- oldHeaders = append(oldHeaders, oldh)
- oldh = rawdb.ReadHeader(es.backend.ChainDb(), oldh.ParentHash, oldh.Number.Uint64()-1)
- }
-
- if oldh.Number.Uint64() < newh.Number.Uint64() {
- newHeaders = append(newHeaders, newh)
-
- newh = rawdb.ReadHeader(es.backend.ChainDb(), newh.ParentHash, newh.Number.Uint64()-1)
- if newh == nil {
- // happens when CHT syncing, nothing to do
- newh = oldh
- }
- }
- }
- // roll back old blocks
- for _, h := range oldHeaders {
- callBack(h, true)
- }
- // check new blocks (array is in reverse order)
- for i := len(newHeaders) - 1; i >= 0; i-- {
- callBack(newHeaders[i], false)
- }
-}
-
-// filter logs of a single header in light client mode
-func (es *EventSystem) lightFilterLogs(header *types.Header, addresses []common.Address, topics [][]common.Hash, remove bool) []*types.Log {
- if !bloomFilter(header.Bloom, addresses, topics) {
- return nil
- }
- // Get the logs of the block
- ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
- defer cancel()
-
- cached, err := es.sys.cachedLogElem(ctx, header.Hash(), header.Number.Uint64())
- if err != nil {
- return nil
- }
-
- unfiltered := append([]*types.Log{}, cached.logs...)
- for i, log := range unfiltered {
- // Don't modify in-cache elements
- logcopy := *log
- logcopy.Removed = remove
- // Swap copy in-place
- unfiltered[i] = &logcopy
- }
-
- logs := filterLogs(unfiltered, nil, nil, addresses, topics)
- // Txhash is already resolved
- if len(logs) > 0 && logs[0].TxHash != (common.Hash{}) {
- return logs
- }
- // Resolve txhash
- body, err := es.sys.cachedGetBody(ctx, cached, header.Hash(), header.Number.Uint64())
- if err != nil {
- return nil
- }
-
- for _, log := range logs {
- // logs are already copied, safe to modify
- log.TxHash = body.Transactions[log.TxIndex].Hash()
- }
-
- return logs
}
// eventLoop (un)installs filters and processes mux events.
@@ -600,8 +458,8 @@ func (es *EventSystem) eventLoop() {
defer func() {
es.txsSub.Unsubscribe()
es.logsSub.Unsubscribe()
- es.rmLogsSub.Unsubscribe()
es.pendingLogsSub.Unsubscribe()
+ es.rmLogsSub.Unsubscribe()
es.chainSub.Unsubscribe()
es.stateSyncSub.Unsubscribe()
}()
@@ -627,25 +485,11 @@ func (es *EventSystem) eventLoop() {
es.handleStateSyncEvent(index, ev)
case f := <-es.install:
- if f.typ == MinedAndPendingLogsSubscription {
- // the type are logs and pending logs subscriptions
- index[LogsSubscription][f.id] = f
- index[PendingLogsSubscription][f.id] = f
- } else {
- index[f.typ][f.id] = f
- }
-
+ index[f.typ][f.id] = f
close(f.installed)
case f := <-es.uninstall:
- if f.typ == MinedAndPendingLogsSubscription {
- // the type are logs and pending logs subscriptions
- delete(index[LogsSubscription], f.id)
- delete(index[PendingLogsSubscription], f.id)
- } else {
- delete(index[f.typ], f.id)
- }
-
+ delete(index[f.typ], f.id)
close(f.err)
// System stopped
diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go
index e92e70b5e7..02592e6afa 100644
--- a/eth/filters/filter_system_test.go
+++ b/eth/filters/filter_system_test.go
@@ -19,7 +19,6 @@ package filters
import (
"context"
"errors"
- "fmt"
"math/big"
"math/rand"
"reflect"
@@ -27,14 +26,12 @@ import (
"testing"
"time"
- "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/internal/ethapi"
@@ -144,10 +141,6 @@ func (b *testBackend) GetLogs(ctx context.Context, hash common.Hash, number uint
return logs, nil
}
-func (b *testBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) {
- return b.pendingBlock, b.pendingReceipts
-}
-
func (b *testBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
return b.txFeed.Subscribe(ch)
}
@@ -226,7 +219,12 @@ func (b *testBackend) ServiceFilter(ctx context.Context, session *bloombits.Matc
}()
}
-func newTestFilterSystem(_ testing.TB, db ethdb.Database, cfg Config) (*testBackend, *FilterSystem) {
+func (b *testBackend) setPending(block *types.Block, receipts types.Receipts) {
+ b.pendingBlock = block
+ b.pendingReceipts = receipts
+}
+
+func newTestFilterSystem(t testing.TB, db ethdb.Database, cfg Config) (*testBackend, *FilterSystem) {
backend := &testBackend{db: db}
sys := NewFilterSystem(backend, cfg)
@@ -244,13 +242,13 @@ func TestBlockSubscription(t *testing.T) {
var (
db = rawdb.NewMemoryDatabase()
backend, sys = newTestFilterSystem(t, db, Config{})
- api = NewFilterAPI(sys, false, true)
+ api = NewFilterAPI(sys, true)
genesis = &core.Genesis{
Config: params.TestChainConfig,
BaseFee: big.NewInt(params.InitialBaseFee),
}
_, chain, _ = core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), 10, func(i int, gen *core.BlockGen) {})
- chainEvents = []core.ChainEvent{}
+ chainEvents []core.ChainEvent
)
for _, blk := range chain {
@@ -302,7 +300,7 @@ func TestPendingTxFilter(t *testing.T) {
var (
db = rawdb.NewMemoryDatabase()
backend, sys = newTestFilterSystem(t, db, Config{})
- api = NewFilterAPI(sys, false, true)
+ api = NewFilterAPI(sys, true)
transactions = []*types.Transaction{
types.NewTransaction(0, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
@@ -361,7 +359,7 @@ func TestPendingTxFilterFullTx(t *testing.T) {
var (
db = rawdb.NewMemoryDatabase()
backend, sys = newTestFilterSystem(t, db, Config{})
- api = NewFilterAPI(sys, false, true)
+ api = NewFilterAPI(sys, true)
transactions = []*types.Transaction{
types.NewTransaction(0, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
@@ -420,7 +418,7 @@ func TestLogFilterCreation(t *testing.T) {
var (
db = rawdb.NewMemoryDatabase()
_, sys = newTestFilterSystem(t, db, Config{})
- api = NewFilterAPI(sys, false, true)
+ api = NewFilterAPI(sys, true)
testCases = []struct {
crit FilterCriteria
@@ -432,8 +430,6 @@ func TestLogFilterCreation(t *testing.T) {
{FilterCriteria{FromBlock: big.NewInt(1), ToBlock: big.NewInt(2)}, true},
// "mined" block range to pending
{FilterCriteria{FromBlock: big.NewInt(1), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, true},
- // new mined and pending blocks
- {FilterCriteria{FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64())}, true},
// from block "higher" than to block
{FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(1)}, false},
// from block "higher" than to block
@@ -442,7 +438,7 @@ func TestLogFilterCreation(t *testing.T) {
{FilterCriteria{FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(100)}, false},
// from block "higher" than to block
{FilterCriteria{FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, false},
- // topics more then 4
+ // topics more than 4
{FilterCriteria{Topics: [][]common.Hash{{}, {}, {}, {}, {}}}, false},
}
)
@@ -471,7 +467,7 @@ func TestInvalidLogFilterCreation(t *testing.T) {
var (
db = rawdb.NewMemoryDatabase()
_, sys = newTestFilterSystem(t, db, Config{})
- api = NewFilterAPI(sys, false, true)
+ api = NewFilterAPI(sys, true)
)
// different situations where log filter creation should fail.
@@ -490,14 +486,14 @@ func TestInvalidLogFilterCreation(t *testing.T) {
}
}
-// TestLogFilterUninstall tests invalid getLogs requests
+// TestInvalidGetLogsRequest tests invalid getLogs requests
func TestInvalidGetLogsRequest(t *testing.T) {
t.Parallel()
var (
db = rawdb.NewMemoryDatabase()
_, sys = newTestFilterSystem(t, db, Config{})
- api = NewFilterAPI(sys, false, true)
+ api = NewFilterAPI(sys, true)
blockHash = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111")
)
@@ -525,7 +521,7 @@ func TestInvalidGetRangeLogsRequest(t *testing.T) {
var (
db = rawdb.NewMemoryDatabase()
_, sys = newTestFilterSystem(t, db, Config{})
- api = NewFilterAPI(sys, false, true)
+ api = NewFilterAPI(sys, true)
)
api.SetChainConfig(params.BorTestChainConfig)
@@ -542,7 +538,7 @@ func TestLogFilter(t *testing.T) {
var (
db = rawdb.NewMemoryDatabase()
backend, sys = newTestFilterSystem(t, db, Config{})
- api = NewFilterAPI(sys, false, true)
+ api = NewFilterAPI(sys, true)
firstAddr = common.HexToAddress("0x1111111111111111111111111111111111111111")
secondAddr = common.HexToAddress("0x2222222222222222222222222222222222222222")
@@ -561,9 +557,6 @@ func TestLogFilter(t *testing.T) {
{Address: thirdAddress, Topics: []common.Hash{secondTopic}, BlockNumber: 3},
}
- expectedCase7 = []*types.Log{allLogs[3], allLogs[4], allLogs[0], allLogs[1], allLogs[2], allLogs[3], allLogs[4]}
- expectedCase11 = []*types.Log{allLogs[1], allLogs[2], allLogs[1], allLogs[2]}
-
testCases = []struct {
crit FilterCriteria
expected []*types.Log
@@ -581,20 +574,14 @@ func TestLogFilter(t *testing.T) {
4: {FilterCriteria{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}}, allLogs[3:5], ""},
// match logs based on multiple addresses and "or" topics
5: {FilterCriteria{Addresses: []common.Address{secondAddr, thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}}, allLogs[2:5], ""},
- // logs in the pending block
- 6: {FilterCriteria{Addresses: []common.Address{firstAddr}, FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64())}, allLogs[:2], ""},
- // mined logs with block num >= 2 or pending logs
- 7: {FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64())}, expectedCase7, ""},
// all "mined" logs with block num >= 2
- 8: {FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, allLogs[3:], ""},
+ 6: {FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, allLogs[3:], ""},
// all "mined" logs
- 9: {FilterCriteria{ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, allLogs, ""},
+ 7: {FilterCriteria{ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, allLogs, ""},
// all "mined" logs with 1>= block num <=2 and topic secondTopic
- 10: {FilterCriteria{FromBlock: big.NewInt(1), ToBlock: big.NewInt(2), Topics: [][]common.Hash{{secondTopic}}}, allLogs[3:4], ""},
- // all "mined" and pending logs with topic firstTopic
- 11: {FilterCriteria{FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), Topics: [][]common.Hash{{firstTopic}}}, expectedCase11, ""},
+ 8: {FilterCriteria{FromBlock: big.NewInt(1), ToBlock: big.NewInt(2), Topics: [][]common.Hash{{secondTopic}}}, allLogs[3:4], ""},
// match all logs due to wildcard topic
- 12: {FilterCriteria{Topics: [][]common.Hash{nil}}, allLogs[1:], ""},
+ 9: {FilterCriteria{Topics: [][]common.Hash{nil}}, allLogs[1:], ""},
}
)
@@ -622,7 +609,7 @@ func TestLogFilter(t *testing.T) {
for { // fetch all expected logs
results, err := api.GetFilterChanges(tt.id)
if err != nil {
- t.Fatalf("Unable to fetch logs: %v", err)
+ t.Fatalf("test %d: unable to fetch logs: %v", i, err)
}
fetched = append(fetched, results.([]*types.Log)...)
@@ -654,338 +641,6 @@ func TestLogFilter(t *testing.T) {
}
}
-// TestPendingLogsSubscription tests if a subscription receives the correct pending logs that are posted to the event feed.
-func TestPendingLogsSubscription(t *testing.T) {
- t.Parallel()
-
- var (
- db = rawdb.NewMemoryDatabase()
- backend, sys = newTestFilterSystem(t, db, Config{})
- api = NewFilterAPI(sys, false, true)
-
- firstAddr = common.HexToAddress("0x1111111111111111111111111111111111111111")
- secondAddr = common.HexToAddress("0x2222222222222222222222222222222222222222")
- thirdAddress = common.HexToAddress("0x3333333333333333333333333333333333333333")
- notUsedAddress = common.HexToAddress("0x9999999999999999999999999999999999999999")
- firstTopic = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111")
- secondTopic = common.HexToHash("0x2222222222222222222222222222222222222222222222222222222222222222")
- thirdTopic = common.HexToHash("0x3333333333333333333333333333333333333333333333333333333333333333")
- fourthTopic = common.HexToHash("0x4444444444444444444444444444444444444444444444444444444444444444")
- notUsedTopic = common.HexToHash("0x9999999999999999999999999999999999999999999999999999999999999999")
-
- allLogs = [][]*types.Log{
- {{Address: firstAddr, Topics: []common.Hash{}, BlockNumber: 0}},
- {{Address: firstAddr, Topics: []common.Hash{firstTopic}, BlockNumber: 1}},
- {{Address: secondAddr, Topics: []common.Hash{firstTopic}, BlockNumber: 2}},
- {{Address: thirdAddress, Topics: []common.Hash{secondTopic}, BlockNumber: 3}},
- {{Address: thirdAddress, Topics: []common.Hash{secondTopic}, BlockNumber: 4}},
- {
- {Address: thirdAddress, Topics: []common.Hash{firstTopic}, BlockNumber: 5},
- {Address: thirdAddress, Topics: []common.Hash{thirdTopic}, BlockNumber: 5},
- {Address: thirdAddress, Topics: []common.Hash{fourthTopic}, BlockNumber: 5},
- {Address: firstAddr, Topics: []common.Hash{firstTopic}, BlockNumber: 5},
- },
- }
-
- pendingBlockNumber = big.NewInt(rpc.PendingBlockNumber.Int64())
-
- testCases = []struct {
- crit ethereum.FilterQuery
- expected []*types.Log
- c chan []*types.Log
- sub *Subscription
- err chan error
- }{
- // match all
- {
- ethereum.FilterQuery{FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
- flattenLogs(allLogs),
- nil, nil, nil,
- },
- // match none due to no matching addresses
- {
- ethereum.FilterQuery{Addresses: []common.Address{{}, notUsedAddress}, Topics: [][]common.Hash{nil}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
- nil,
- nil, nil, nil,
- },
- // match logs based on addresses, ignore topics
- {
- ethereum.FilterQuery{Addresses: []common.Address{firstAddr}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
- append(flattenLogs(allLogs[:2]), allLogs[5][3]),
- nil, nil, nil,
- },
- // match none due to no matching topics (match with address)
- {
- ethereum.FilterQuery{Addresses: []common.Address{secondAddr}, Topics: [][]common.Hash{{notUsedTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
- nil,
- nil, nil, nil,
- },
- // match logs based on addresses and topics
- {
- ethereum.FilterQuery{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
- append(flattenLogs(allLogs[3:5]), allLogs[5][0]),
- nil, nil, nil,
- },
- // match logs based on multiple addresses and "or" topics
- {
- ethereum.FilterQuery{Addresses: []common.Address{secondAddr, thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
- append(flattenLogs(allLogs[2:5]), allLogs[5][0]),
- nil, nil, nil,
- },
- // multiple pending logs, should match only 2 topics from the logs in block 5
- {
- ethereum.FilterQuery{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, fourthTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
- []*types.Log{allLogs[5][0], allLogs[5][2]},
- nil, nil, nil,
- },
- // match none due to only matching new mined logs
- {
- ethereum.FilterQuery{},
- nil,
- nil, nil, nil,
- },
- // match none due to only matching mined logs within a specific block range
- {
- ethereum.FilterQuery{FromBlock: big.NewInt(1), ToBlock: big.NewInt(2)},
- nil,
- nil, nil, nil,
- },
- // match all due to matching mined and pending logs
- {
- ethereum.FilterQuery{FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64())},
- flattenLogs(allLogs),
- nil, nil, nil,
- },
- // match none due to matching logs from a specific block number to new mined blocks
- {
- ethereum.FilterQuery{FromBlock: big.NewInt(1), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())},
- nil,
- nil, nil, nil,
- },
- }
- )
-
- // create all subscriptions, this ensures all subscriptions are created before the events are posted.
- // on slow machines this could otherwise lead to missing events when the subscription is created after
- // (some) events are posted.
- for i := range testCases {
- testCases[i].c = make(chan []*types.Log)
- testCases[i].err = make(chan error, 1)
-
- var err error
-
- testCases[i].sub, err = api.events.SubscribeLogs(testCases[i].crit, testCases[i].c)
- if err != nil {
- t.Fatalf("SubscribeLogs %d failed: %v\n", i, err)
- }
- }
-
- for n, test := range testCases {
- i := n
- tt := test
-
- go func() {
- defer tt.sub.Unsubscribe()
-
- var fetched []*types.Log
-
- timeout := time.After(1 * time.Second)
- fetchLoop:
- for {
- select {
- case logs := <-tt.c:
- // Do not break early if we've fetched greater, or equal,
- // to the number of logs expected. This ensures we do not
- // deadlock the filter system because it will do a blocking
- // send on this channel if another log arrives.
- fetched = append(fetched, logs...)
- case <-timeout:
- break fetchLoop
- }
- }
-
- if len(fetched) != len(tt.expected) {
- tt.err <- fmt.Errorf("invalid number of logs for case %d, want %d log(s), got %d", i, len(tt.expected), len(fetched))
- return
- }
-
- for l := range fetched {
- if fetched[l].Removed {
- tt.err <- fmt.Errorf("expected log not to be removed for log %d in case %d", l, i)
- return
- }
-
- if !reflect.DeepEqual(fetched[l], tt.expected[l]) {
- tt.err <- fmt.Errorf("invalid log on index %d for case %d\n", l, i)
- return
- }
- }
- tt.err <- nil
- }()
- }
-
- // raise events
- for _, ev := range allLogs {
- backend.pendingLogsFeed.Send(ev)
- }
-
- for i := range testCases {
- err := <-testCases[i].err
- if err != nil {
- t.Fatalf("test %d failed: %v", i, err)
- }
-
- <-testCases[i].sub.Err()
- }
-}
-
-// nolint:gocognit
-func TestLightFilterLogs(t *testing.T) {
- t.Parallel()
-
- var (
- db = rawdb.NewMemoryDatabase()
- backend, sys = newTestFilterSystem(t, db, Config{})
- api = NewFilterAPI(sys, true, true)
- signer = types.HomesteadSigner{}
-
- firstAddr = common.HexToAddress("0x1111111111111111111111111111111111111111")
- secondAddr = common.HexToAddress("0x2222222222222222222222222222222222222222")
- thirdAddress = common.HexToAddress("0x3333333333333333333333333333333333333333")
- notUsedAddress = common.HexToAddress("0x9999999999999999999999999999999999999999")
- firstTopic = common.HexToHash("0x1111111111111111111111111111111111111111111111111111111111111111")
- secondTopic = common.HexToHash("0x2222222222222222222222222222222222222222222222222222222222222222")
-
- // posted twice, once as regular logs and once as pending logs.
- allLogs = []*types.Log{
- // Block 1
- {Address: firstAddr, Topics: []common.Hash{}, Data: []byte{}, BlockNumber: 2, Index: 0},
- // Block 2
- {Address: firstAddr, Topics: []common.Hash{firstTopic}, Data: []byte{}, BlockNumber: 3, Index: 0},
- {Address: secondAddr, Topics: []common.Hash{firstTopic}, Data: []byte{}, BlockNumber: 3, Index: 1},
- {Address: thirdAddress, Topics: []common.Hash{secondTopic}, Data: []byte{}, BlockNumber: 3, Index: 2},
- // Block 3
- {Address: thirdAddress, Topics: []common.Hash{secondTopic}, Data: []byte{}, BlockNumber: 4, Index: 0},
- }
-
- testCases = []struct {
- crit FilterCriteria
- expected []*types.Log
- id rpc.ID
- }{
- // match all
- 0: {FilterCriteria{}, allLogs, ""},
- // match none due to no matching addresses
- 1: {FilterCriteria{Addresses: []common.Address{{}, notUsedAddress}, Topics: [][]common.Hash{nil}}, []*types.Log{}, ""},
- // match logs based on addresses, ignore topics
- 2: {FilterCriteria{Addresses: []common.Address{firstAddr}}, allLogs[:2], ""},
- // match logs based on addresses and topics
- 3: {FilterCriteria{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}}, allLogs[3:5], ""},
- // all logs with block num >= 3
- 4: {FilterCriteria{FromBlock: big.NewInt(3), ToBlock: big.NewInt(5)}, allLogs[1:], ""},
- // all logs
- 5: {FilterCriteria{FromBlock: big.NewInt(0), ToBlock: big.NewInt(5)}, allLogs, ""},
- // all logs with 1>= block num <=2 and topic secondTopic
- 6: {FilterCriteria{FromBlock: big.NewInt(2), ToBlock: big.NewInt(3), Topics: [][]common.Hash{{secondTopic}}}, allLogs[3:4], ""},
- }
-
- key, _ = crypto.GenerateKey()
- addr = crypto.PubkeyToAddress(key.PublicKey)
- genesis = &core.Genesis{Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
- addr: {Balance: big.NewInt(params.Ether)},
- },
- }
- receipts = []*types.Receipt{{
- Logs: []*types.Log{allLogs[0]},
- }, {
- Logs: []*types.Log{allLogs[1], allLogs[2], allLogs[3]},
- }, {
- Logs: []*types.Log{allLogs[4]},
- }}
- )
-
- _, blocks, _ := core.GenerateChainWithGenesis(genesis, ethash.NewFaker(), 4, func(i int, b *core.BlockGen) {
- if i == 0 {
- return
- }
-
- receipts[i-1].Bloom = types.CreateBloom(types.Receipts{receipts[i-1]})
- b.AddUncheckedReceipt(receipts[i-1])
- tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i - 1), To: &common.Address{}, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: b.BaseFee(), Data: nil}), signer, key)
- b.AddTx(tx)
- })
- for i, block := range blocks {
- rawdb.WriteBlock(db, block)
- rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64())
- rawdb.WriteHeadBlockHash(db, block.Hash())
-
- if i > 0 {
- rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), []*types.Receipt{receipts[i-1]})
- }
- }
- // create all filters
- for i := range testCases {
- id, err := api.NewFilter(testCases[i].crit)
- if err != nil {
- t.Fatal(err)
- }
-
- testCases[i].id = id
- }
-
- // raise events
- time.Sleep(1 * time.Second)
-
- for _, block := range blocks {
- backend.chainFeed.Send(core.ChainEvent{Block: block, Hash: common.Hash{}, Logs: allLogs})
- }
-
- for i, tt := range testCases {
- var fetched []*types.Log
-
- timeout := time.Now().Add(1 * time.Second)
-
- for { // fetch all expected logs
- results, err := api.GetFilterChanges(tt.id)
- if err != nil {
- t.Fatalf("Unable to fetch logs: %v", err)
- }
-
- fetched = append(fetched, results.([]*types.Log)...)
- if len(fetched) >= len(tt.expected) {
- break
- }
- // check timeout
- if time.Now().After(timeout) {
- break
- }
-
- time.Sleep(100 * time.Millisecond)
- }
-
- if len(fetched) != len(tt.expected) {
- t.Errorf("invalid number of logs for case %d, want %d log(s), got %d", i, len(tt.expected), len(fetched))
- return
- }
-
- for l := range fetched {
- if fetched[l].Removed {
- t.Errorf("expected log not to be removed for log %d in case %d", l, i)
- }
-
- expected := *tt.expected[l]
- blockNum := expected.BlockNumber - 1
- expected.BlockHash = blocks[blockNum].Hash()
- expected.TxHash = blocks[blockNum].Transactions()[0].Hash()
-
- if !reflect.DeepEqual(fetched[l], &expected) {
- t.Errorf("invalid log on index %d for case %d", l, i)
- }
- }
- }
-}
-
// TestPendingTxFilterDeadlock tests if the event loop hangs when pending
// txes arrive at the same time that one of multiple filters is timing out.
// Please refer to #22131 for more details.
@@ -997,7 +652,7 @@ func TestPendingTxFilterDeadlock(t *testing.T) {
var (
db = rawdb.NewMemoryDatabase()
backend, sys = newTestFilterSystem(t, db, Config{Timeout: timeout})
- api = NewFilterAPI(sys, false, true)
+ api = NewFilterAPI(sys, true)
done = make(chan struct{})
)
@@ -1053,12 +708,3 @@ func TestPendingTxFilterDeadlock(t *testing.T) {
}
}
}
-
-func flattenLogs(pl [][]*types.Log) []*types.Log {
- var logs []*types.Log
- for _, l := range pl {
- logs = append(logs, l...)
- }
-
- return logs
-}
diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go
index b61ec3f3a4..be6f82e39d 100644
--- a/eth/filters/filter_test.go
+++ b/eth/filters/filter_test.go
@@ -34,7 +34,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
func makeReceipt(addr common.Address) *types.Receipt {
@@ -58,7 +58,7 @@ func BenchmarkFilters(b *testing.B) {
addr4 = common.BytesToAddress([]byte("random addresses please"))
gspec = &core.Genesis{
- Alloc: core.GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}},
+ Alloc: types.GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}},
BaseFee: big.NewInt(params.InitialBaseFee),
Config: params.TestChainConfig,
}
@@ -89,7 +89,7 @@ func BenchmarkFilters(b *testing.B) {
// The test txs are not properly signed, can't simply create a chain
// and then import blocks. TODO(rjl493456442) try to get rid of the
// manual database writes.
- gspec.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults))
+ gspec.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
for i, block := range chain {
rawdb.WriteBlock(db, block)
@@ -103,6 +103,7 @@ func BenchmarkFilters(b *testing.B) {
filter := sys.NewRangeFilter(0, -1, []common.Address{addr1, addr2, addr3, addr4}, nil)
for i := 0; i < b.N; i++ {
+ filter.begin = 0
logs, _ := filter.Logs(context.Background())
if len(logs) != 4 {
b.Fatal("expected 4 logs, got", len(logs))
@@ -112,8 +113,8 @@ func BenchmarkFilters(b *testing.B) {
func TestFilters(t *testing.T) {
var (
- db, _ = rawdb.NewLevelDBDatabase(t.TempDir(), 0, 0, "", false)
- _, sys = newTestFilterSystem(t, db, Config{})
+ db = rawdb.NewMemoryDatabase()
+ backend, sys = newTestFilterSystem(t, db, Config{})
// Sender account
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
addr = crypto.PubkeyToAddress(key1.PublicKey)
@@ -168,7 +169,7 @@ func TestFilters(t *testing.T) {
gspec = &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
addr: {Balance: big.NewInt(0).Mul(big.NewInt(100), big.NewInt(params.Ether))},
contract: {Balance: big.NewInt(0), Code: bytecode},
contract2: {Balance: big.NewInt(0), Code: bytecode},
@@ -184,7 +185,7 @@ func TestFilters(t *testing.T) {
// Hack: GenerateChainWithGenesis creates a new db.
// Commit the genesis manually and use GenerateChain.
- _, err = gspec.Commit(db, trie.NewDatabase(db, nil))
+ _, err = gspec.Commit(db, triedb.NewDatabase(db, nil))
if err != nil {
t.Fatal(err)
}
@@ -252,8 +253,8 @@ func TestFilters(t *testing.T) {
gen.AddTx(tx)
}
})
- var l uint64
- bc, err := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l, nil)
+
+ bc, err := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
if err != nil {
t.Fatal(err)
}
@@ -280,8 +281,7 @@ func TestFilters(t *testing.T) {
}), signer, key1)
gen.AddTx(tx)
})
- sys.backend.(*testBackend).pendingBlock = pchain[0]
- sys.backend.(*testBackend).pendingReceipts = preceipts[0]
+ backend.setPending(pchain[0], preceipts[0])
for i, tc := range []struct {
f *Filter
@@ -348,16 +348,16 @@ func TestFilters(t *testing.T) {
err: "safe header not found",
},
{
- f: sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.PendingBlockNumber), nil, nil),
- want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696335"],"data":"0x","blockNumber":"0x3e9","transactionHash":"0x4110587c1b8d86edc85dce929a34127f1cb8809515a9f177c91c866de3eb0638","transactionIndex":"0x0","blockHash":"0x98248a1efca0ed49e2d0cbe6b70ff4315e602598fb7ebc46b043b4280e8e0714","logIndex":"0x0","removed":false}]`,
+ f: sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.PendingBlockNumber), nil, nil),
+ err: errPendingLogsUnsupported.Error(),
},
{
- f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.PendingBlockNumber), nil, nil),
- want: `[{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696334"],"data":"0x","blockNumber":"0x3e8","transactionHash":"0x9a87842100a638dfa5da8842b4beda691d2fd77b0c84b57f24ecfa9fb208f747","transactionIndex":"0x0","blockHash":"0xb996b4bf68bbbd9237f495bb1828aa0067b816d47d66b0826de3e27c587ce7d7","logIndex":"0x0","removed":false},{"address":"0xfe00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696335"],"data":"0x","blockNumber":"0x3e9","transactionHash":"0x4110587c1b8d86edc85dce929a34127f1cb8809515a9f177c91c866de3eb0638","transactionIndex":"0x0","blockHash":"0x98248a1efca0ed49e2d0cbe6b70ff4315e602598fb7ebc46b043b4280e8e0714","logIndex":"0x0","removed":false}]`,
+ f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.PendingBlockNumber), nil, nil),
+ err: errPendingLogsUnsupported.Error(),
},
{
f: sys.NewRangeFilter(int64(rpc.PendingBlockNumber), int64(rpc.LatestBlockNumber), nil, nil),
- err: errInvalidBlockRange.Error(),
+ err: errPendingLogsUnsupported.Error(),
},
} {
logs, err := tc.f.Logs(context.Background())
@@ -379,7 +379,7 @@ func TestFilters(t *testing.T) {
}
t.Run("timeout", func(t *testing.T) {
- f := sys.NewRangeFilter(0, -1, nil, nil)
+ f := sys.NewRangeFilter(0, rpc.LatestBlockNumber.Int64(), nil, nil)
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(-time.Hour))
defer cancel()
_, err := f.Logs(ctx)
diff --git a/eth/filters/test_backend.go b/eth/filters/test_backend.go
index 4118979b3c..ca0210b0ca 100644
--- a/eth/filters/test_backend.go
+++ b/eth/filters/test_backend.go
@@ -9,6 +9,7 @@ import (
core "github.com/ethereum/go-ethereum/core"
bloombits "github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/state"
types "github.com/ethereum/go-ethereum/core/types"
ethdb "github.com/ethereum/go-ethereum/ethdb"
event "github.com/ethereum/go-ethereum/event"
@@ -185,6 +186,6 @@ func (b *TestBackend) GetBody(context.Context, common.Hash, rpc.BlockNumber) (*t
panic("not implemented")
}
-func (b *TestBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) {
+func (b *TestBackend) Pending() (*types.Block, types.Receipts, *state.StateDB) {
panic("not implemented")
}
diff --git a/eth/gasestimator/gasestimator.go b/eth/gasestimator/gasestimator.go
index 7e121cad02..7b8f974af7 100644
--- a/eth/gasestimator/gasestimator.go
+++ b/eth/gasestimator/gasestimator.go
@@ -71,15 +71,25 @@ func Estimate(ctx context.Context, call *core.Message, opts *Options, gasCap uin
}
// Recap the highest gas limit with account's available balance.
if feeCap.BitLen() != 0 {
- balance := opts.State.GetBalance(call.From)
+ balance := opts.State.GetBalance(call.From).ToBig()
- available := new(big.Int).Set(balance)
+ available := balance
if call.Value != nil {
if call.Value.Cmp(available) >= 0 {
return 0, nil, core.ErrInsufficientFundsForTransfer
}
available.Sub(available, call.Value)
}
+ if opts.Config.IsCancun(opts.Header.Number) && len(call.BlobHashes) > 0 {
+ blobGasPerBlob := new(big.Int).SetInt64(params.BlobTxBlobGasPerBlob)
+ blobBalanceUsage := new(big.Int).SetInt64(int64(len(call.BlobHashes)))
+ blobBalanceUsage.Mul(blobBalanceUsage, blobGasPerBlob)
+ blobBalanceUsage.Mul(blobBalanceUsage, call.BlobGasFeeCap)
+ if blobBalanceUsage.Cmp(available) >= 0 {
+ return 0, nil, core.ErrInsufficientFunds
+ }
+ available.Sub(available, blobBalanceUsage)
+ }
allowance := new(big.Int).Div(available, feeCap)
// If the allowance is larger than maximum uint64, skip checking
diff --git a/eth/gasprice/feehistory.go b/eth/gasprice/feehistory.go
index 371c9ea545..a40a0b1035 100644
--- a/eth/gasprice/feehistory.go
+++ b/eth/gasprice/feehistory.go
@@ -23,14 +23,16 @@ import (
"fmt"
"math"
"math/big"
+ "slices"
"sync/atomic"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
+ "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
- "golang.org/x/exp/slices"
)
var (
@@ -42,6 +44,8 @@ const (
// maxBlockFetchers is the max number of goroutines to spin up to pull blocks
// for the fee history calculation (mostly relevant for LES).
maxBlockFetchers = 4
+ // maxQueryLimit is the max number of requested percentiles.
+ maxQueryLimit = 100
)
// blockFees represents a single block for processing
@@ -63,9 +67,11 @@ type cacheKey struct {
// processedFees contains the results of a processed block.
type processedFees struct {
- reward []*big.Int
- baseFee, nextBaseFee *big.Int
- gasUsedRatio float64
+ reward []*big.Int
+ baseFee, nextBaseFee *big.Int
+ gasUsedRatio float64
+ blobGasUsedRatio float64
+ blobBaseFee, nextBlobBaseFee *big.Int
}
// txGasAndReward is sorted in ascending order based on reward
@@ -78,19 +84,30 @@ type txGasAndReward struct {
// the block field filled in, retrieves the block from the backend if not present yet and
// fills in the rest of the fields.
func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
- chainconfig := oracle.backend.ChainConfig()
+ config := oracle.backend.ChainConfig()
+ // Fill in base fee and next base fee.
if bf.results.baseFee = bf.header.BaseFee; bf.results.baseFee == nil {
bf.results.baseFee = new(big.Int)
}
-
- if chainconfig.IsLondon(big.NewInt(int64(bf.blockNumber + 1))) {
- bf.results.nextBaseFee = eip1559.CalcBaseFee(chainconfig, bf.header)
+ if config.IsLondon(big.NewInt(int64(bf.blockNumber + 1))) {
+ bf.results.nextBaseFee = eip1559.CalcBaseFee(config, bf.header)
} else {
bf.results.nextBaseFee = new(big.Int)
}
-
+ // Fill in blob base fee and next blob base fee.
+ if excessBlobGas := bf.header.ExcessBlobGas; excessBlobGas != nil {
+ bf.results.blobBaseFee = eip4844.CalcBlobFee(*excessBlobGas)
+ bf.results.nextBlobBaseFee = eip4844.CalcBlobFee(eip4844.CalcExcessBlobGas(*excessBlobGas, *bf.header.BlobGasUsed))
+ } else {
+ bf.results.blobBaseFee = new(big.Int)
+ bf.results.nextBlobBaseFee = new(big.Int)
+ }
+ // Compute gas used ratio for normal and blob gas.
bf.results.gasUsedRatio = float64(bf.header.GasUsed) / float64(bf.header.GasLimit)
+ if blobGasUsed := bf.header.BlobGasUsed; blobGasUsed != nil {
+ bf.results.blobGasUsedRatio = float64(*blobGasUsed) / params.MaxBlobGasPerBlock
+ }
if len(percentiles) == 0 {
// rewards were not requested, return null
@@ -170,7 +187,7 @@ func (oracle *Oracle) resolveBlockRange(ctx context.Context, reqEnd rpc.BlockNum
switch reqEnd {
case rpc.PendingBlockNumber:
- if pendingBlock, pendingReceipts = oracle.backend.PendingBlockAndReceipts(); pendingBlock != nil {
+ if pendingBlock, pendingReceipts, _ = oracle.backend.Pending(); pendingBlock != nil {
resolved = pendingBlock.Header()
} else {
// Pending block not supported by backend, process only until latest block.
@@ -215,25 +232,28 @@ func (oracle *Oracle) resolveBlockRange(ctx context.Context, reqEnd rpc.BlockNum
// or blocks older than a certain age (specified in maxHistory). The first block of the
// actually processed range is returned to avoid ambiguity when parts of the requested range
// are not available or when the head has changed during processing this request.
-// Three arrays are returned based on the processed blocks:
+// Five arrays are returned based on the processed blocks:
// - reward: the requested percentiles of effective priority fees per gas of transactions in each
// block, sorted in ascending order and weighted by gas used.
// - baseFee: base fee per gas in the given block
// - gasUsedRatio: gasUsed/gasLimit in the given block
+// - blobBaseFee: the blob base fee per gas in the given block
+// - blobGasUsedRatio: blobGasUsed/blobGasLimit in the given block
//
-// Note: baseFee includes the next block after the newest of the returned range, because this
-// value can be derived from the newest block.
-// nolint:gocognit
-func (oracle *Oracle) FeeHistory(ctx context.Context, blocks uint64, unresolvedLastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, error) {
+// Note: baseFee and blobBaseFee both include the next block after the newest of the returned range,
+// because this value can be derived from the newest block.
+func (oracle *Oracle) FeeHistory(ctx context.Context, blocks uint64, unresolvedLastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, []*big.Int, []float64, error) {
if blocks < 1 {
- return common.Big0, nil, nil, nil, nil // returning with no data and no error means there are no retrievable blocks
+ return common.Big0, nil, nil, nil, nil, nil, nil // returning with no data and no error means there are no retrievable blocks
}
maxFeeHistory := oracle.maxHeaderHistory
if len(rewardPercentiles) != 0 {
maxFeeHistory = oracle.maxBlockHistory
}
-
+ if len(rewardPercentiles) > maxQueryLimit {
+ return common.Big0, nil, nil, nil, nil, nil, fmt.Errorf("%w: over the query limit %d", errInvalidPercentile, maxQueryLimit)
+ }
if blocks > maxFeeHistory {
log.Warn("Sanitizing fee history length", "requested", blocks, "truncated", maxFeeHistory)
blocks = maxFeeHistory
@@ -241,11 +261,10 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks uint64, unresolvedL
for i, p := range rewardPercentiles {
if p < 0 || p > 100 {
- return common.Big0, nil, nil, nil, fmt.Errorf("%w: %f", errInvalidPercentile, p)
+ return common.Big0, nil, nil, nil, nil, nil, fmt.Errorf("%w: %f", errInvalidPercentile, p)
}
-
if i > 0 && p <= rewardPercentiles[i-1] {
- return common.Big0, nil, nil, nil, fmt.Errorf("%w: #%d:%f >= #%d:%f", errInvalidPercentile, i-1, rewardPercentiles[i-1], i, p)
+ return common.Big0, nil, nil, nil, nil, nil, fmt.Errorf("%w: #%d:%f >= #%d:%f", errInvalidPercentile, i-1, rewardPercentiles[i-1], i, p)
}
}
@@ -257,7 +276,7 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks uint64, unresolvedL
pendingBlock, pendingReceipts, lastBlock, blocks, err := oracle.resolveBlockRange(ctx, unresolvedLastBlock, blocks)
if err != nil || blocks == 0 {
- return common.Big0, nil, nil, nil, err
+ return common.Big0, nil, nil, nil, nil, nil, err
}
oldestBlock := lastBlock + 1 - blocks
@@ -319,22 +338,25 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks uint64, unresolvedL
}
var (
- reward = make([][]*big.Int, blocks)
- baseFee = make([]*big.Int, blocks+1)
- gasUsedRatio = make([]float64, blocks)
- firstMissing = blocks
+ reward = make([][]*big.Int, blocks)
+ baseFee = make([]*big.Int, blocks+1)
+ gasUsedRatio = make([]float64, blocks)
+ blobGasUsedRatio = make([]float64, blocks)
+ blobBaseFee = make([]*big.Int, blocks+1)
+ firstMissing = blocks
)
for ; blocks > 0; blocks-- {
fees := <-results
if fees.err != nil {
- return common.Big0, nil, nil, nil, fees.err
+ return common.Big0, nil, nil, nil, nil, nil, fees.err
}
i := fees.blockNumber - oldestBlock
if fees.results.baseFee != nil {
reward[i], baseFee[i], baseFee[i+1], gasUsedRatio[i] = fees.results.reward, fees.results.baseFee, fees.results.nextBaseFee, fees.results.gasUsedRatio
+ blobGasUsedRatio[i], blobBaseFee[i], blobBaseFee[i+1] = fees.results.blobGasUsedRatio, fees.results.blobBaseFee, fees.results.nextBlobBaseFee
} else {
// getting no block and no error means we are requesting into the future (might happen because of a reorg)
if i < firstMissing {
@@ -344,7 +366,7 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks uint64, unresolvedL
}
if firstMissing == 0 {
- return common.Big0, nil, nil, nil, nil
+ return common.Big0, nil, nil, nil, nil, nil, nil
}
if len(rewardPercentiles) != 0 {
@@ -354,6 +376,6 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks uint64, unresolvedL
}
baseFee, gasUsedRatio = baseFee[:firstMissing+1], gasUsedRatio[:firstMissing]
-
- return new(big.Int).SetUint64(oldestBlock), reward, baseFee, gasUsedRatio, nil
+ blobBaseFee, blobGasUsedRatio = blobBaseFee[:firstMissing+1], blobGasUsedRatio[:firstMissing]
+ return new(big.Int).SetUint64(oldestBlock), reward, baseFee, gasUsedRatio, blobBaseFee, blobGasUsedRatio, nil
}
diff --git a/eth/gasprice/feehistory_test.go b/eth/gasprice/feehistory_test.go
index efa52f08e5..a48297c52e 100644
--- a/eth/gasprice/feehistory_test.go
+++ b/eth/gasprice/feehistory_test.go
@@ -59,11 +59,10 @@ func TestFeeHistory(t *testing.T) {
MaxHeaderHistory: c.maxHeader,
MaxBlockHistory: c.maxBlock,
}
- backend := newTestBackend(t, big.NewInt(16), c.pending)
+ backend := newTestBackend(t, big.NewInt(16), nil, c.pending)
oracle := NewOracle(backend, config)
- first, reward, baseFee, ratio, err := oracle.FeeHistory(context.Background(), c.count, c.last, c.percent)
-
+ first, reward, baseFee, ratio, blobBaseFee, blobRatio, err := oracle.FeeHistory(context.Background(), c.count, c.last, c.percent)
backend.teardown()
expReward := c.expCount
@@ -91,7 +90,12 @@ func TestFeeHistory(t *testing.T) {
if len(ratio) != c.expCount {
t.Fatalf("Test case %d: gasUsedRatio array length mismatch, want %d, got %d", i, c.expCount, len(ratio))
}
-
+ if len(blobRatio) != c.expCount {
+ t.Fatalf("Test case %d: blobGasUsedRatio array length mismatch, want %d, got %d", i, c.expCount, len(blobRatio))
+ }
+ if len(blobBaseFee) != len(baseFee) {
+ t.Fatalf("Test case %d: blobBaseFee array length mismatch, want %d, got %d", i, len(baseFee), len(blobBaseFee))
+ }
if err != c.expErr && !errors.Is(err, c.expErr) {
t.Fatalf("Test case %d: error mismatch, want %v, got %v", i, c.expErr, err)
}
diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go
index 41828b0196..6ffc008669 100644
--- a/eth/gasprice/gasprice.go
+++ b/eth/gasprice/gasprice.go
@@ -19,24 +19,25 @@ package gasprice
import (
"context"
"math/big"
+ "slices"
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
- "golang.org/x/exp/slices"
)
const sampleNumber = 3 // Number of transactions sampled in a block
var (
DefaultMaxPrice = big.NewInt(500 * params.GWei)
- DefaultIgnorePrice = big.NewInt(params.BorDefaultGpoIgnorePrice)
+ DefaultIgnorePrice = big.NewInt(params.BorDefaultGpoIgnorePrice) // bor's default
)
type Config struct {
@@ -54,7 +55,7 @@ type OracleBackend interface {
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
- PendingBlockAndReceipts() (*types.Block, types.Receipts)
+ Pending() (*types.Block, types.Receipts, *state.StateDB)
ChainConfig() *params.ChainConfig
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
}
@@ -100,11 +101,12 @@ func NewOracle(backend OracleBackend, params Config) *Oracle {
log.Warn("Sanitizing invalid gasprice oracle price cap", "provided", params.MaxPrice, "updated", maxPrice)
}
+ // PIP-35: Enforce the ignore price to 25 gwei
ignorePrice := params.IgnorePrice
if ignorePrice == nil || ignorePrice.Int64() != DefaultIgnorePrice.Int64() {
ignorePrice = DefaultIgnorePrice
log.Warn("Sanitizing invalid gasprice oracle ignore price", "provided", params.IgnorePrice, "updated", ignorePrice)
- } else if ignorePrice.Int64() > 0 {
+ } else {
log.Info("Gasprice oracle is ignoring threshold set", "threshold", ignorePrice)
}
diff --git a/eth/gasprice/gasprice_test.go b/eth/gasprice/gasprice_test.go
index 61796355f2..f27f421479 100644
--- a/eth/gasprice/gasprice_test.go
+++ b/eth/gasprice/gasprice_test.go
@@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
@@ -109,13 +110,13 @@ func (b *testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.
return b.chain.GetReceiptsByHash(hash), nil
}
-func (b *testBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) {
+func (b *testBackend) Pending() (*types.Block, types.Receipts, *state.StateDB) {
if b.pending {
block := b.chain.GetBlockByNumber(testHead + 1)
- return block, b.chain.GetReceiptsByHash(block.Hash())
+ state, _ := b.chain.StateAt(block.Root())
+ return block, b.chain.GetReceiptsByHash(block.Hash()), state
}
-
- return nil, nil
+ return nil, nil, nil
}
func (b *testBackend) ChainConfig() *params.ChainConfig {
@@ -132,14 +133,17 @@ func (b *testBackend) teardown() {
// newTestBackend creates a test backend. OBS: don't forget to invoke tearDown
// after use, otherwise the blockchain instance will mem-leak via goroutines.
-func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBackend {
+func newTestBackend(t *testing.T, londonBlock *big.Int, cancunBlock *big.Int, pending bool) *testBackend {
+ if londonBlock != nil && cancunBlock != nil && londonBlock.Cmp(cancunBlock) == 1 {
+ panic("cannot define test backend with cancun before london")
+ }
var (
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
addr = crypto.PubkeyToAddress(key.PublicKey)
config = *params.TestChainConfig // needs copy because it is modified below
gspec = &core.Genesis{
Config: &config,
- Alloc: core.GenesisAlloc{addr: {Balance: big.NewInt(math.MaxInt64)}},
+ Alloc: types.GenesisAlloc{addr: {Balance: big.NewInt(math.MaxInt64)}},
}
signer = types.LatestSigner(gspec.Config)
)
@@ -148,8 +152,17 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBacke
config.ArrowGlacierBlock = londonBlock
config.GrayGlacierBlock = londonBlock
config.TerminalTotalDifficulty = common.Big0
+ // var engine consensus.Engine = beacon.New(ethash.NewFaker())
+ // td := params.GenesisDifficulty.Uint64()
engine := ethash.NewFaker()
+ // if cancunBlock != nil {
+ // ts := gspec.Timestamp + cancunBlock.Uint64()*10 // fixed 10 sec block time in blockgen
+ // config.ShanghaiTime = &ts
+ // config.CancunTime = &ts
+ // signer = types.LatestSigner(gspec.Config)
+ // }
+
// Generate testing blocks
_, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, testHead+1, func(i int, b *core.BlockGen) {
b.SetCoinbase(common.Address{1})
@@ -218,7 +231,7 @@ func TestSuggestTipCap(t *testing.T) {
}
for _, c := range cases {
- backend := newTestBackend(t, c.fork, false)
+ backend := newTestBackend(t, c.fork, nil, false)
oracle := NewOracle(backend, config)
// The gas price sampled is: 32G, 31G, 30G, 29G, 28G, 27G
diff --git a/eth/handler.go b/eth/handler.go
index 1775f2df5c..9707ea4c55 100644
--- a/eth/handler.go
+++ b/eth/handler.go
@@ -26,13 +26,13 @@ import (
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/beacon"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/forkid"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/fetcher"
"github.com/ethereum/go-ethereum/eth/protocols/eth"
@@ -43,7 +43,8 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/p2p"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/ethereum/go-ethereum/p2p/enode"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
)
const (
@@ -75,7 +76,7 @@ type txPool interface {
// Pending should return pending transactions.
// The slice should be modifiable by the caller.
- Pending(enforceTips bool) map[common.Address][]*txpool.LazyTransaction
+ Pending(filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction
// SubscribeTransactions subscribes to new transaction events. The subscriber
// can decide whether to receive notifications only for newly seen transactions
@@ -86,15 +87,14 @@ type txPool interface {
// handlerConfig is the collection of initialization parameters to create a full
// node network handler.
type handlerConfig struct {
+ NodeID enode.ID // P2P node ID used for tx propagation topology
Database ethdb.Database // Database for direct sync insertions
Chain *core.BlockChain // Blockchain to serve data from
TxPool txPool // Transaction pool to propagate from
- Merger *consensus.Merger // The manager for eth1/2 transition
- Network uint64 // Network identifier to adfvertise
+ Network uint64 // Network identifier to advertise
Sync downloader.SyncMode // Whether to snap or full sync
BloomCache uint64 // Megabytes to alloc for snap sync bloom
EventMux *event.TypeMux // Legacy event mux, deprecate for `feed`
- txArrivalWait time.Duration // Maximum duration to wait for an announced tx before requesting it
checker ethereum.ChainValidator
RequiredBlocks map[uint64]common.Hash // Hard coded map of required block hashes for sync challenges
EthAPI *ethapi.BlockChainAPI // EthAPI to interact
@@ -102,6 +102,7 @@ type handlerConfig struct {
}
type handler struct {
+ nodeID enode.ID
networkID uint64
forkFilter forkid.Filter // Fork ID filter, constant across the lifetime of the node
@@ -117,7 +118,6 @@ type handler struct {
blockFetcher *fetcher.BlockFetcher
txFetcher *fetcher.TxFetcher
peers *peerSet
- merger *consensus.Merger
ethAPI *ethapi.BlockChainAPI // EthAPI to interact
@@ -148,6 +148,7 @@ func newHandler(config *handlerConfig) (*handler, error) {
}
h := &handler{
+ nodeID: config.NodeID,
networkID: config.Network,
forkFilter: forkid.NewFilter(config.Chain),
eventMux: config.EventMux,
@@ -155,7 +156,6 @@ func newHandler(config *handlerConfig) (*handler, error) {
txpool: config.TxPool,
chain: config.Chain,
peers: newPeerSet(),
- merger: config.Merger,
ethAPI: config.EthAPI,
requiredBlocks: config.RequiredBlocks,
enableBlockTracking: config.enableBlockTracking,
@@ -218,12 +218,6 @@ func newHandler(config *handlerConfig) (*handler, error) {
}
// Construct the fetcher (short sync)
validator := func(header *types.Header) error {
- // All the block fetcher activities should be disabled
- // after the transition. Print the warning log.
- if h.merger.PoSFinalized() {
- log.Warn("Unexpected validation activity", "hash", header.Hash(), "number", header.Number)
- return errors.New("unexpected behavior after transition")
- }
// Reject all the PoS style headers in the first place. No matter
// the chain has finished the transition or not, the PoS headers
// should only come from the trusted consensus layer instead of
@@ -239,23 +233,6 @@ func newHandler(config *handlerConfig) (*handler, error) {
return h.chain.CurrentBlock().Number.Uint64()
}
inserter := func(blocks types.Blocks) (int, error) {
- // All the block fetcher activities should be disabled
- // after the transition. Print the warning log.
- if h.merger.PoSFinalized() {
- var ctx []interface{}
-
- ctx = append(ctx, "blocks", len(blocks))
- if len(blocks) > 0 {
- ctx = append(ctx, "firsthash", blocks[0].Hash())
- ctx = append(ctx, "firstnumber", blocks[0].Number())
- ctx = append(ctx, "lasthash", blocks[len(blocks)-1].Hash())
- ctx = append(ctx, "lastnumber", blocks[len(blocks)-1].Number())
- }
-
- log.Warn("Unexpected insertion activity", ctx...)
-
- return 0, errors.New("unexpected behavior after transition")
- }
// If snap sync is running, deny importing weird blocks. This is a problematic
// clause when starting up a new network, because snap-syncing miners might not
// accept each others' blocks until a restart. Unfortunately we haven't figured
@@ -266,34 +243,14 @@ func newHandler(config *handlerConfig) (*handler, error) {
return 0, nil
}
- if h.merger.TDDReached() {
- // The blocks from the p2p network is regarded as untrusted
- // after the transition. In theory block gossip should be disabled
- // entirely whenever the transition is started. But in order to
- // handle the transition boundary reorg in the consensus-layer,
- // the legacy blocks are still accepted, but only for the terminal
- // pow blocks. Spec: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3675.md#halt-the-importing-of-pow-blocks
- for i, block := range blocks {
- ptd := h.chain.GetTd(block.ParentHash(), block.NumberU64()-1)
- if ptd == nil {
- return 0, nil
- }
-
- td := new(big.Int).Add(ptd, block.Difficulty())
- if !h.chain.Config().IsTerminalPoWBlock(ptd, td) {
- log.Info("Filtered out non-terminal pow block", "number", block.NumberU64(), "hash", block.Hash())
- return 0, nil
- }
-
- if err := h.chain.InsertBlockWithoutSetHead(block); err != nil {
- return i, err
- }
- }
-
- return 0, nil
- }
return h.chain.InsertChain(blocks)
}
+
+ // If snap sync is requested but snapshots are disabled, fail loudly
+ if h.snapSync.Load() && config.Chain.Snapshots() == nil {
+ return nil, errors.New("snap sync not supported with snapshots disabled")
+ }
+
h.blockFetcher = fetcher.NewBlockFetcher(false, nil, h.chain.GetBlockByHash, validator, h.BroadcastBlock, heighter, nil, inserter, h.removePeer, h.enableBlockTracking)
fetchTx := func(peer string, hashes []common.Hash) error {
@@ -307,7 +264,7 @@ func newHandler(config *handlerConfig) (*handler, error) {
addTxs := func(txs []*types.Transaction) []error {
return h.txpool.Add(txs, false, false)
}
- h.txFetcher = fetcher.NewTxFetcher(h.txpool.Has, addTxs, fetchTx, config.txArrivalWait, h.removePeer)
+ h.txFetcher = fetcher.NewTxFetcher(h.txpool.Has, addTxs, fetchTx, h.removePeer)
h.chainSync = newChainSyncer(h)
return h, nil
@@ -555,7 +512,6 @@ func (h *handler) Start(maxPeers int) {
h.minedBlockSub = h.eventMux.Subscribe(core.NewMinedBlockEvent{})
go h.minedBroadcastLoop()
- // start sync handlers
h.wg.Add(1)
go h.chainSync.loop()
@@ -565,8 +521,8 @@ func (h *handler) Start(maxPeers int) {
}
func (h *handler) Stop() {
- h.txsSub.Unsubscribe() // quits txBroadcastLoop
- h.minedBlockSub.Unsubscribe() // quits blockBroadcastLoop
+ h.txsSub.Unsubscribe() // quits txBroadcastLoop
+ h.minedBlockSub.Unsubscribe()
// Quit chainSync and txsync64.
// After this is done, no new peers will be accepted.
@@ -585,11 +541,6 @@ func (h *handler) Stop() {
// BroadcastBlock will either propagate a block to a subset of its peers, or
// will only announce its availability (depending what's requested).
func (h *handler) BroadcastBlock(block *types.Block, propagate bool) {
- // Disable the block propagation if the chain has already entered the PoS
- // stage. The block propagation is delegated to the consensus layer.
- if h.merger.PoSFinalized() {
- return
- }
// Disable the block propagation if it's the post-merge block.
if beacon, ok := h.chain.Engine().(*beacon.Beacon); ok {
if beacon.IsPoSHeader(block.Header()) {
@@ -657,49 +608,74 @@ func (h *handler) BroadcastTransactions(txs types.Transactions) {
largeTxs int // Number of large transactions to announce only
directCount int // Number of transactions sent directly to peers (duplicates included)
- directPeers int // Number of peers that were sent transactions directly
annCount int // Number of transactions announced across all peers (duplicates included)
- annPeers int // Number of peers announced about transactions
txset = make(map[*ethPeer][]common.Hash) // Set peer->hash to transfer directly
annos = make(map[*ethPeer][]common.Hash) // Set peer->hash to announce
)
// Broadcast transactions to a batch of peers not knowing about it
- for _, tx := range txs {
- peers := h.peers.peersWithoutTransaction(tx.Hash())
+ direct := big.NewInt(int64(math.Sqrt(float64(h.peers.len())))) // Approximate number of peers to broadcast to
+ if direct.BitLen() == 0 {
+ direct = big.NewInt(1)
+ }
+ total := new(big.Int).Exp(direct, big.NewInt(2), nil) // Stabilise total peer count a bit based on sqrt peers
- var numDirect int
+ var (
+ signer = types.LatestSignerForChainID(h.chain.Config().ChainID) // Don't care about chain status, we just need *a* sender
+ hasher = crypto.NewKeccakState()
+ hash = make([]byte, 32)
+ )
+ for _, tx := range txs {
+ var maybeDirect bool
switch {
case tx.Type() == types.BlobTxType:
blobTxs++
case tx.Size() > txMaxBroadcastSize:
largeTxs++
default:
- numDirect = int(math.Sqrt(float64(len(peers))))
- }
- // Send the tx unconditionally to a subset of our peers
- for _, peer := range peers[:numDirect] {
- txset[peer] = append(txset[peer], tx.Hash())
+ maybeDirect = true
}
- // For the remaining peers, send announcement only
- for _, peer := range peers[numDirect:] {
- annos[peer] = append(annos[peer], tx.Hash())
+ // Send the transaction (if it's small enough) directly to a subset of
+ // the peers that have not received it yet, ensuring that the flow of
+ // transactions is grouped by account to (try and) avoid nonce gaps.
+ //
+ // To do this, we hash the local enode IW with together with a peer's
+ // enode ID together with the transaction sender and broadcast if
+ // `sha(self, peer, sender) mod peers < sqrt(peers)`.
+ for _, peer := range h.peers.peersWithoutTransaction(tx.Hash()) {
+ var broadcast bool
+ if maybeDirect {
+ hasher.Reset()
+ hasher.Write(h.nodeID.Bytes())
+ hasher.Write(peer.Node().ID().Bytes())
+
+ from, _ := types.Sender(signer, tx) // Ignore error, we only use the addr as a propagation target splitter
+ hasher.Write(from.Bytes())
+
+ hasher.Read(hash)
+ if new(big.Int).Mod(new(big.Int).SetBytes(hash), total).Cmp(direct) < 0 {
+ broadcast = true
+ }
+ }
+ if broadcast {
+ txset[peer] = append(txset[peer], tx.Hash())
+ } else {
+ annos[peer] = append(annos[peer], tx.Hash())
+ }
}
}
for peer, hashes := range txset {
- directPeers++
directCount += len(hashes)
peer.AsyncSendTransactions(hashes)
}
for peer, hashes := range annos {
- annPeers++
annCount += len(hashes)
peer.AsyncSendPooledTransactionHashes(hashes)
}
log.Debug("Distributed transactions", "plaintxs", len(txs)-blobTxs-largeTxs, "blobtxs", blobTxs, "largetxs", largeTxs,
- "bcastpeers", directPeers, "bcastcount", directCount, "annpeers", annPeers, "anncount", annCount)
+ "bcastcount", directCount, "anncount", annCount)
}
// minedBroadcastLoop sends mined blocks to connected peers.
diff --git a/eth/handler_bor.go b/eth/handler_bor.go
index 9fbc096d3d..be06165b11 100644
--- a/eth/handler_bor.go
+++ b/eth/handler_bor.go
@@ -3,6 +3,8 @@ package eth
import (
"context"
"errors"
+ "fmt"
+ "strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/bor"
@@ -18,8 +20,6 @@ var (
// errMilestone is returned when we are unable to fetch the
// latest milestone from the local heimdall.
errMilestone = errors.New("failed to fetch latest milestone")
-
- ErrNotInRejectedList = errors.New("MilestoneID not in rejected list")
)
// fetchWhitelistCheckpoint fetches the latest checkpoint from it's local heimdall
@@ -32,19 +32,23 @@ func (h *ethHandler) fetchWhitelistCheckpoint(ctx context.Context, bor *bor.Bor,
// fetch the latest checkpoint from Heimdall
checkpoint, err := bor.HeimdallClient.FetchCheckpoint(ctx, -1)
+ err = reportCommonErrors("latest checkpoint", err, errCheckpoint)
if err != nil {
- log.Debug("Failed to fetch latest checkpoint for whitelisting", "err", err)
- return blockNum, blockHash, errCheckpoint
+ return blockNum, blockHash, err
}
- log.Info("Got new checkpoint from heimdall", "start", checkpoint.StartBlock.Uint64(), "end", checkpoint.EndBlock.Uint64(), "rootHash", checkpoint.RootHash.String())
+ log.Debug("Got new checkpoint from heimdall", "start", checkpoint.StartBlock.Uint64(), "end", checkpoint.EndBlock.Uint64(), "rootHash", checkpoint.RootHash.String())
// Verify if the checkpoint fetched can be added to the local whitelist entry or not
// If verified, it returns the hash of the end block of the checkpoint. If not,
// it will return appropriate error.
hash, err := verifier.verify(ctx, eth, h, checkpoint.StartBlock.Uint64(), checkpoint.EndBlock.Uint64(), checkpoint.RootHash.String()[2:], true)
if err != nil {
- log.Warn("Failed to whitelist checkpoint", "err", err)
+ if errors.Is(err, errChainOutOfSync) {
+ log.Info("Whitelisting checkpoint deferred", "err", err)
+ } else {
+ log.Warn("Failed to whitelist checkpoint", "err", err)
+ }
return blockNum, blockHash, err
}
@@ -64,72 +68,68 @@ func (h *ethHandler) fetchWhitelistMilestone(ctx context.Context, bor *bor.Bor,
// fetch latest milestone
milestone, err := bor.HeimdallClient.FetchMilestone(ctx)
- if errors.Is(err, heimdall.ErrServiceUnavailable) {
- log.Debug("Failed to fetch latest milestone for whitelisting", "err", err)
- return num, hash, err
- }
-
+ err = reportCommonErrors("latest milestone", err, errMilestone)
if err != nil {
- log.Error("Failed to fetch latest milestone for whitelisting", "err", err)
- return num, hash, errMilestone
+ return num, hash, err
}
num = milestone.EndBlock.Uint64()
hash = milestone.Hash
- log.Info("Got new milestone from heimdall", "start", milestone.StartBlock.Uint64(), "end", milestone.EndBlock.Uint64(), "hash", milestone.Hash.String())
+ log.Debug("Got new milestone from heimdall", "start", milestone.StartBlock.Uint64(), "end", milestone.EndBlock.Uint64(), "hash", milestone.Hash.String())
- // Verify if the milestone fetched can be added to the local whitelist entry or not
- // If verified, it returns the hash of the end block of the milestone. If not,
- // it will return appropriate error.
+ // Verify if the milestone fetched can be added to the local whitelist entry or not. If verified,
+ // the hash of the end block of the milestone is returned else appropriate error is returned.
_, err = verifier.verify(ctx, eth, h, milestone.StartBlock.Uint64(), milestone.EndBlock.Uint64(), milestone.Hash.String()[2:], false)
if err != nil {
+ if errors.Is(err, errChainOutOfSync) {
+ log.Info("Whitelisting milestone deferred", "err", err)
+ } else {
+ log.Warn("Failed to whitelist milestone", "err", err)
+ }
h.downloader.UnlockSprint(milestone.EndBlock.Uint64())
- return num, hash, err
}
- return num, hash, nil
+ return num, hash, err
}
func (h *ethHandler) fetchNoAckMilestone(ctx context.Context, bor *bor.Bor) (string, error) {
- var (
- milestoneID string
- )
-
- // fetch latest milestone
milestoneID, err := bor.HeimdallClient.FetchLastNoAckMilestone(ctx)
- if errors.Is(err, heimdall.ErrServiceUnavailable) {
- log.Debug("Failed to fetch latest no-ack milestone", "err", err)
- return milestoneID, err
- }
-
- if err != nil {
- log.Error("Failed to fetch latest no-ack milestone", "err", err)
- return milestoneID, errMilestone
- }
+ err = reportCommonErrors("latest no-ack milestone", err, nil)
- return milestoneID, nil
+ return milestoneID, err
}
func (h *ethHandler) fetchNoAckMilestoneByID(ctx context.Context, bor *bor.Bor, milestoneID string) error {
- // fetch latest milestone
err := bor.HeimdallClient.FetchNoAckMilestone(ctx, milestoneID)
- if errors.Is(err, heimdall.ErrServiceUnavailable) {
- log.Debug("Failed to fetch no-ack milestone by ID", "milestoneID", milestoneID, "err", err)
- return err
+ if errors.Is(err, heimdall.ErrNotInRejectedList) {
+ log.Debug("MilestoneID not in rejected list", "milestoneID", milestoneID)
}
+ err = reportCommonErrors("no-ack milestone by ID", err, nil, "milestoneID", milestoneID)
+ return err
+}
- // fixme: handle different types of errors
- if errors.Is(err, ErrNotInRejectedList) {
- log.Warn("MilestoneID not in rejected list", "milestoneID", milestoneID, "err", err)
+// reportCommonErrors reports common errors which can occur while fetching data from heimdall. It also
+// returns back the wrapped erorr if required to the caller.
+func reportCommonErrors(msg string, err error, wrapError error, ctx ...interface{}) error {
+ if err == nil {
return err
}
- if err != nil {
- log.Error("Failed to fetch no-ack milestone by ID ", "milestoneID", milestoneID, "err", err)
+ // We're skipping extra check to the `heimdall.ErrServiceUnavailable` error as it should not
+ // occur post HF (in heimdall). If it does, we'll anyways warn below as a normal error.
+
+ ctx = append(ctx, "err", err)
+
+ if strings.Contains(err.Error(), "context deadline exceeded") {
+ log.Warn(fmt.Sprintf("Failed to fetch %s, please check the heimdall endpoint and status of your heimdall node", msg), ctx...)
+ } else {
+ log.Warn(fmt.Sprintf("Failed to fetch %s", msg), ctx...)
+ }
- return errMilestone
+ if wrapError != nil {
+ return fmt.Errorf("%w: %v", wrapError, err)
}
- return nil
+ return err
}
diff --git a/eth/handler_bor_test.go b/eth/handler_bor_test.go
index 7ceab1fc64..b062c9cdc7 100644
--- a/eth/handler_bor_test.go
+++ b/eth/handler_bor_test.go
@@ -103,7 +103,7 @@ func fetchCheckpointTest(t *testing.T, heimdall *mockHeimdall, bor *bor.Bor, han
ctx := context.Background()
_, _, err := handler.fetchWhitelistCheckpoint(ctx, bor, nil, verifier)
- require.Equal(t, err, errCheckpoint)
+ require.ErrorIs(t, err, errCheckpoint)
// create 4 mock checkpoints
checkpoints = createMockCheckpoints(4)
@@ -133,7 +133,7 @@ func fetchMilestoneTest(t *testing.T, heimdall *mockHeimdall, bor *bor.Bor, hand
ctx := context.Background()
_, _, err := handler.fetchWhitelistMilestone(ctx, bor, nil, verifier)
- require.Equal(t, err, errMilestone)
+ require.ErrorIs(t, err, errMilestone)
// create 4 mock checkpoints
milestones = createMockMilestones(4)
diff --git a/eth/handler_eth.go b/eth/handler_eth.go
index 625010de89..27a4d3876f 100644
--- a/eth/handler_eth.go
+++ b/eth/handler_eth.go
@@ -93,12 +93,6 @@ func (h *ethHandler) Handle(peer *eth.Peer, packet eth.Packet) error {
// handleBlockAnnounces is invoked from a peer's message handler when it transmits a
// batch of block announcements for the local node to process.
func (h *ethHandler) handleBlockAnnounces(peer *eth.Peer, hashes []common.Hash, numbers []uint64) error {
- // Drop all incoming block announces from the p2p network if
- // the chain already entered the pos stage and disconnect the
- // remote peer.
- if h.merger.PoSFinalized() {
- return errors.New("disallowed block announcement")
- }
// Schedule all the unknown hashes for retrieval
var (
unknownHashes = make([]common.Hash, 0, len(hashes))
@@ -122,12 +116,6 @@ func (h *ethHandler) handleBlockAnnounces(peer *eth.Peer, hashes []common.Hash,
// handleBlockBroadcast is invoked from a peer's message handler when it transmits a
// block broadcast for the local node to process.
func (h *ethHandler) handleBlockBroadcast(peer *eth.Peer, block *types.Block, td *big.Int) error {
- // Drop all incoming block announces from the p2p network if
- // the chain already entered the pos stage and disconnect the
- // remote peer.
- if h.merger.PoSFinalized() {
- return errors.New("disallowed block broadcast")
- }
// Schedule the block for import
h.blockFetcher.Enqueue(peer.ID(), block)
diff --git a/eth/handler_eth_test.go b/eth/handler_eth_test.go
index c44b4c9a33..a5affaa310 100644
--- a/eth/handler_eth_test.go
+++ b/eth/handler_eth_test.go
@@ -23,7 +23,6 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/forkid"
@@ -114,7 +113,6 @@ func testForkIDSplit(t *testing.T, protocol uint) {
Database: dbNoFork,
Chain: chainNoFork,
TxPool: newTestTxPool(),
- Merger: consensus.NewMerger(rawdb.NewMemoryDatabase()),
Network: 1,
Sync: downloader.FullSync,
BloomCache: 1,
@@ -123,7 +121,6 @@ func testForkIDSplit(t *testing.T, protocol uint) {
Database: dbProFork,
Chain: chainProFork,
TxPool: newTestTxPool(),
- Merger: consensus.NewMerger(rawdb.NewMemoryDatabase()),
Network: 1,
Sync: downloader.FullSync,
BloomCache: 1,
@@ -615,7 +612,10 @@ func testBroadcastMalformedBlock(t *testing.T, protocol uint) {
// Try to broadcast all malformations and ensure they all get discarded
for _, header := range []*types.Header{malformedUncles, malformedTransactions, malformedEverything} {
- block := types.NewBlockWithHeader(header).WithBody(block.Transactions(), block.Uncles())
+ block := types.NewBlockWithHeader(header).WithBody(types.Body{
+ Transactions: block.Transactions(),
+ Uncles: block.Uncles(),
+ })
if err := src.SendNewBlock(block, big.NewInt(131136)); err != nil {
t.Fatalf("failed to broadcast block: %v", err)
}
diff --git a/eth/handler_test.go b/eth/handler_test.go
index 2625b4d138..bb52786bde 100644
--- a/eth/handler_test.go
+++ b/eth/handler_test.go
@@ -22,7 +22,6 @@ import (
"sync"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
@@ -34,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
var (
@@ -92,7 +92,7 @@ func (p *testTxPool) Add(txs []*types.Transaction, local bool, sync bool) []erro
}
// Pending returns all the transactions known to the pool
-func (p *testTxPool) Pending(enforceTips bool) map[common.Address][]*txpool.LazyTransaction {
+func (p *testTxPool) Pending(filter txpool.PendingFilter) map[common.Address][]*txpool.LazyTransaction {
p.lock.RLock()
defer p.lock.RUnlock()
@@ -112,8 +112,8 @@ func (p *testTxPool) Pending(enforceTips bool) map[common.Address][]*txpool.Lazy
Hash: tx.Hash(),
Tx: tx,
Time: tx.Time(),
- GasFeeCap: tx.GasFeeCap(),
- GasTipCap: tx.GasTipCap(),
+ GasFeeCap: uint256.MustFromBig(tx.GasFeeCap()),
+ GasTipCap: uint256.MustFromBig(tx.GasTipCap()),
Gas: tx.Gas(),
BlobGas: tx.BlobGas(),
})
@@ -150,7 +150,7 @@ func newTestHandlerWithBlocks(blocks int) *testHandler {
db := rawdb.NewMemoryDatabase()
gspec := &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{testAddr: {Balance: big.NewInt(1000000)}},
+ Alloc: types.GenesisAlloc{testAddr: {Balance: big.NewInt(1000000)}},
}
chain, _ := core.NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
@@ -165,7 +165,6 @@ func newTestHandlerWithBlocks(blocks int) *testHandler {
Database: db,
Chain: chain,
TxPool: txpool,
- Merger: consensus.NewMerger(rawdb.NewMemoryDatabase()),
Network: 1,
Sync: downloader.SnapSync,
BloomCache: 1,
diff --git a/eth/peerset.go b/eth/peerset.go
index 369432e914..8a7e379025 100644
--- a/eth/peerset.go
+++ b/eth/peerset.go
@@ -57,6 +57,7 @@ type peerSet struct {
lock sync.RWMutex
closed bool
+ quitCh chan struct{} // Quit channel to signal termination
}
// newPeerSet creates a new peer set to track the active participants.
@@ -65,6 +66,7 @@ func newPeerSet() *peerSet {
peers: make(map[string]*ethPeer),
snapWait: make(map[string]chan *snap.Peer),
snapPend: make(map[string]*snap.Peer),
+ quitCh: make(chan struct{}),
}
}
@@ -102,7 +104,7 @@ func (ps *peerSet) registerSnapExtension(peer *snap.Peer) error {
return nil
}
-// waitExtensions blocks until all satellite protocols are connected and tracked
+// waitSnapExtension blocks until all satellite protocols are connected and tracked
// by the peerset.
func (ps *peerSet) waitSnapExtension(peer *eth.Peer) (*snap.Peer, error) {
// If the peer does not support a compatible `snap`, don't wait
@@ -135,7 +137,15 @@ func (ps *peerSet) waitSnapExtension(peer *eth.Peer) (*snap.Peer, error) {
ps.snapWait[id] = wait
ps.lock.Unlock()
- return <-wait, nil
+ select {
+ case p := <-wait:
+ return p, nil
+ case <-ps.quitCh:
+ ps.lock.Lock()
+ delete(ps.snapWait, id)
+ ps.lock.Unlock()
+ return nil, errPeerSetClosed
+ }
}
// registerPeer injects a new `eth` peer into the working set, or returns an error
@@ -275,6 +285,8 @@ func (ps *peerSet) close() {
for _, p := range ps.peers {
p.Disconnect(p2p.DiscQuitting)
}
-
+ if !ps.closed {
+ close(ps.quitCh)
+ }
ps.closed = true
}
diff --git a/eth/protocols/eth/broadcast.go b/eth/protocols/eth/broadcast.go
index 646a3c9163..f3826497e0 100644
--- a/eth/protocols/eth/broadcast.go
+++ b/eth/protocols/eth/broadcast.go
@@ -80,7 +80,11 @@ func (p *Peer) broadcastTransactions() {
size common.StorageSize
)
for i := 0; i < len(queue) && size < maxTxPacketSize; i++ {
- if tx := p.txpool.Get(queue[i]); tx != nil {
+ tx := p.txpool.Get(queue[i])
+
+ // BOR specific - DO NOT REMOVE
+ // Skip PIP-15 bundled transactions
+ if tx != nil && tx.GetOptions() == nil {
txs = append(txs, tx)
size += common.StorageSize(tx.Size())
}
@@ -151,7 +155,8 @@ func (p *Peer) announceTransactions() {
)
for count = 0; count < len(queue) && size < maxTxPacketSize; count++ {
tx := p.txpool.Get(queue[count])
- // Skip EIP-4337 bundled transactions
+ // BOR specific - DO NOT REMOVE
+ // Skip PIP-15 bundled transactions
if tx != nil && tx.GetOptions() == nil {
pending = append(pending, queue[count])
pendingTypes = append(pendingTypes, tx.Type())
diff --git a/eth/protocols/eth/dispatcher.go b/eth/protocols/eth/dispatcher.go
index 23fd05157c..108159fe71 100644
--- a/eth/protocols/eth/dispatcher.go
+++ b/eth/protocols/eth/dispatcher.go
@@ -139,7 +139,7 @@ func (p *Peer) dispatchRequest(req *Request) error {
}
}
-// dispatchRequest fulfils a pending request and delivers it to the requested
+// dispatchResponse fulfils a pending request and delivers it to the requested
// sink.
func (p *Peer) dispatchResponse(res *Response, metadata func() interface{}) error {
resOp := &response{
diff --git a/eth/protocols/eth/handler_test.go b/eth/protocols/eth/handler_test.go
index 3c30df6b2e..8670ea6ba0 100644
--- a/eth/protocols/eth/handler_test.go
+++ b/eth/protocols/eth/handler_test.go
@@ -102,7 +102,7 @@ func newTestBackendWithGenerator(blocks int, shanghai bool, generator func(int,
gspec := &core.Genesis{
Config: config,
- Alloc: core.GenesisAlloc{testAddr: {Balance: big.NewInt(100_000_000_000_000_000)}},
+ Alloc: types.GenesisAlloc{testAddr: {Balance: big.NewInt(100_000_000_000_000_000)}},
}
chain, _ := core.NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil, nil, nil)
@@ -118,7 +118,7 @@ func newTestBackendWithGenerator(blocks int, shanghai bool, generator func(int,
txconfig.Journal = "" // Don't litter the disk with test journals
pool := legacypool.New(txconfig, chain)
- txpool, _ := txpool.New(new(big.Int).SetUint64(txconfig.PriceLimit), chain, []txpool.SubPool{pool})
+ txpool, _ := txpool.New(txconfig.PriceLimit, chain, []txpool.SubPool{pool})
return &testBackend{
db: db,
diff --git a/eth/protocols/snap/gentrie.go b/eth/protocols/snap/gentrie.go
new file mode 100644
index 0000000000..6255fb221d
--- /dev/null
+++ b/eth/protocols/snap/gentrie.go
@@ -0,0 +1,287 @@
+// Copyright 2024 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 snap
+
+import (
+ "bytes"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/trie"
+)
+
+// genTrie interface is used by the snap syncer to generate merkle tree nodes
+// based on a received batch of states.
+type genTrie interface {
+ // update inserts the state item into generator trie.
+ update(key, value []byte) error
+
+ // commit flushes the right boundary nodes if complete flag is true. This
+ // function must be called before flushing the associated database batch.
+ commit(complete bool) common.Hash
+}
+
+// pathTrie is a wrapper over the stackTrie, incorporating numerous additional
+// logics to handle the semi-completed trie and potential leftover dangling
+// nodes in the database. It is utilized for constructing the merkle tree nodes
+// in path mode during the snap sync process.
+type pathTrie struct {
+ owner common.Hash // identifier of trie owner, empty for account trie
+ tr *trie.StackTrie // underlying raw stack trie
+ first []byte // the path of first committed node by stackTrie
+ last []byte // the path of last committed node by stackTrie
+
+ // This flag indicates whether nodes on the left boundary are skipped for
+ // committing. If set, the left boundary nodes are considered incomplete
+ // due to potentially missing left children.
+ skipLeftBoundary bool
+ db ethdb.KeyValueReader
+ batch ethdb.Batch
+}
+
+// newPathTrie initializes the path trie.
+func newPathTrie(owner common.Hash, skipLeftBoundary bool, db ethdb.KeyValueReader, batch ethdb.Batch) *pathTrie {
+ tr := &pathTrie{
+ owner: owner,
+ skipLeftBoundary: skipLeftBoundary,
+ db: db,
+ batch: batch,
+ }
+ tr.tr = trie.NewStackTrie(tr.onTrieNode)
+ return tr
+}
+
+// onTrieNode is invoked whenever a new node is committed by the stackTrie.
+//
+// As the committed nodes might be incomplete if they are on the boundaries
+// (left or right), this function has the ability to detect the incomplete
+// ones and filter them out for committing.
+//
+// Additionally, the assumption is made that there may exist leftover dangling
+// nodes in the database. This function has the ability to detect the dangling
+// nodes that fall within the path space of committed nodes (specifically on
+// the path covered by internal extension nodes) and remove them from the
+// database. This property ensures that the entire path space is uniquely
+// occupied by committed nodes.
+//
+// Furthermore, all leftover dangling nodes along the path from committed nodes
+// to the trie root (left and right boundaries) should be removed as well;
+// otherwise, they might potentially disrupt the state healing process.
+func (t *pathTrie) onTrieNode(path []byte, hash common.Hash, blob []byte) {
+ // Filter out the nodes on the left boundary if skipLeftBoundary is
+ // configured. Nodes are considered to be on the left boundary if
+ // it's the first one to be committed, or the parent/ancestor of the
+ // first committed node.
+ if t.skipLeftBoundary && (t.first == nil || bytes.HasPrefix(t.first, path)) {
+ if t.first == nil {
+ // Memorize the path of first committed node, which is regarded
+ // as left boundary. Deep-copy is necessary as the path given
+ // is volatile.
+ t.first = append([]byte{}, path...)
+
+ // The left boundary can be uniquely determined by the first committed node
+ // from stackTrie (e.g., N_1), as the shared path prefix between the first
+ // two inserted state items is deterministic (the path of N_3). The path
+ // from trie root towards the first committed node is considered the left
+ // boundary. The potential leftover dangling nodes on left boundary should
+ // be cleaned out.
+ //
+ // +-----+
+ // | N_3 | shared path prefix of state_1 and state_2
+ // +-----+
+ // /- -\
+ // +-----+ +-----+
+ // First committed node | N_1 | | N_2 | latest inserted node (contain state_2)
+ // +-----+ +-----+
+ //
+ // The node with the path of the first committed one (e.g, N_1) is not
+ // removed because it's a sibling of the nodes we want to commit, not
+ // the parent or ancestor.
+ for i := 0; i < len(path); i++ {
+ t.delete(path[:i], false)
+ }
+ }
+ return
+ }
+ // If boundary filtering is not configured, or the node is not on the left
+ // boundary, commit it to database.
+ //
+ // Note: If the current committed node is an extension node, then the nodes
+ // falling within the path between itself and its standalone (not embedded
+ // in parent) child should be cleaned out for exclusively occupy the inner
+ // path.
+ //
+ // This is essential in snap sync to avoid leaving dangling nodes within
+ // this range covered by extension node which could potentially break the
+ // state healing.
+ //
+ // The extension node is detected if its path is the prefix of last committed
+ // one and path gap is larger than one. If the path gap is only one byte,
+ // the current node could either be a full node, or an extension with single
+ // byte key. In either case, no gaps will be left in the path.
+ if t.last != nil && bytes.HasPrefix(t.last, path) && len(t.last)-len(path) > 1 {
+ for i := len(path) + 1; i < len(t.last); i++ {
+ t.delete(t.last[:i], true)
+ }
+ }
+ t.write(path, blob)
+
+ // Update the last flag. Deep-copy is necessary as the provided path is volatile.
+ if t.last == nil {
+ t.last = append([]byte{}, path...)
+ } else {
+ t.last = append(t.last[:0], path...)
+ }
+}
+
+// write commits the node write to provided database batch in path mode.
+func (t *pathTrie) write(path []byte, blob []byte) {
+ if t.owner == (common.Hash{}) {
+ rawdb.WriteAccountTrieNode(t.batch, path, blob)
+ } else {
+ rawdb.WriteStorageTrieNode(t.batch, t.owner, path, blob)
+ }
+}
+
+func (t *pathTrie) deleteAccountNode(path []byte, inner bool) {
+ if inner {
+ accountInnerLookupGauge.Inc(1)
+ } else {
+ accountOuterLookupGauge.Inc(1)
+ }
+ if !rawdb.HasAccountTrieNode(t.db, path) {
+ return
+ }
+ if inner {
+ accountInnerDeleteGauge.Inc(1)
+ } else {
+ accountOuterDeleteGauge.Inc(1)
+ }
+ rawdb.DeleteAccountTrieNode(t.batch, path)
+}
+
+func (t *pathTrie) deleteStorageNode(path []byte, inner bool) {
+ if inner {
+ storageInnerLookupGauge.Inc(1)
+ } else {
+ storageOuterLookupGauge.Inc(1)
+ }
+ if !rawdb.HasStorageTrieNode(t.db, t.owner, path) {
+ return
+ }
+ if inner {
+ storageInnerDeleteGauge.Inc(1)
+ } else {
+ storageOuterDeleteGauge.Inc(1)
+ }
+ rawdb.DeleteStorageTrieNode(t.batch, t.owner, path)
+}
+
+// delete commits the node deletion to provided database batch in path mode.
+func (t *pathTrie) delete(path []byte, inner bool) {
+ if t.owner == (common.Hash{}) {
+ t.deleteAccountNode(path, inner)
+ } else {
+ t.deleteStorageNode(path, inner)
+ }
+}
+
+// update implements genTrie interface, inserting a (key, value) pair into the
+// stack trie.
+func (t *pathTrie) update(key, value []byte) error {
+ return t.tr.Update(key, value)
+}
+
+// commit implements genTrie interface, flushing the right boundary if it's
+// considered as complete. Otherwise, the nodes on the right boundary are
+// discarded and cleaned up.
+//
+// Note, this function must be called before flushing database batch, otherwise,
+// dangling nodes might be left in database.
+func (t *pathTrie) commit(complete bool) common.Hash {
+ // If the right boundary is claimed as complete, flush them out.
+ // The nodes on both left and right boundary will still be filtered
+ // out if left boundary filtering is configured.
+ if complete {
+ // Commit all inserted but not yet committed nodes(on the right
+ // boundary) in the stackTrie.
+ hash := t.tr.Hash()
+ if t.skipLeftBoundary {
+ return common.Hash{} // hash is meaningless if left side is incomplete
+ }
+ return hash
+ }
+ // Discard nodes on the right boundary as it's claimed as incomplete. These
+ // nodes might be incomplete due to missing children on the right side.
+ // Furthermore, the potential leftover nodes on right boundary should also
+ // be cleaned out.
+ //
+ // The right boundary can be uniquely determined by the last committed node
+ // from stackTrie (e.g., N_1), as the shared path prefix between the last
+ // two inserted state items is deterministic (the path of N_3). The path
+ // from trie root towards the last committed node is considered the right
+ // boundary (root to N_3).
+ //
+ // +-----+
+ // | N_3 | shared path prefix of last two states
+ // +-----+
+ // /- -\
+ // +-----+ +-----+
+ // Last committed node | N_1 | | N_2 | latest inserted node (contain last state)
+ // +-----+ +-----+
+ //
+ // Another interesting scenario occurs when the trie is committed due to
+ // too many items being accumulated in the batch. To flush them out to
+ // the database, the path of the last inserted node (N_2) is temporarily
+ // treated as an incomplete right boundary, and nodes on this path are
+ // removed (e.g. from root to N_3).
+ // However, this path will be reclaimed as an internal path by inserting
+ // more items after the batch flush. New nodes on this path can be committed
+ // with no issues as they are actually complete. Also, from a database
+ // perspective, first deleting and then rewriting is a valid data update.
+ for i := 0; i < len(t.last); i++ {
+ t.delete(t.last[:i], false)
+ }
+ return common.Hash{} // the hash is meaningless for incomplete commit
+}
+
+// hashTrie is a wrapper over the stackTrie for implementing genTrie interface.
+type hashTrie struct {
+ tr *trie.StackTrie
+}
+
+// newHashTrie initializes the hash trie.
+func newHashTrie(batch ethdb.Batch) *hashTrie {
+ return &hashTrie{tr: trie.NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
+ rawdb.WriteLegacyTrieNode(batch, hash, blob)
+ })}
+}
+
+// update implements genTrie interface, inserting a (key, value) pair into
+// the stack trie.
+func (t *hashTrie) update(key, value []byte) error {
+ return t.tr.Update(key, value)
+}
+
+// commit implements genTrie interface, committing the nodes on right boundary.
+func (t *hashTrie) commit(complete bool) common.Hash {
+ if !complete {
+ return common.Hash{} // the hash is meaningless for incomplete commit
+ }
+ return t.tr.Hash() // return hash only if it's claimed as complete
+}
diff --git a/eth/protocols/snap/gentrie_test.go b/eth/protocols/snap/gentrie_test.go
new file mode 100644
index 0000000000..1fb2dbce75
--- /dev/null
+++ b/eth/protocols/snap/gentrie_test.go
@@ -0,0 +1,553 @@
+// Copyright 2024 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 snap
+
+import (
+ "bytes"
+ "math/rand"
+ "slices"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/internal/testrand"
+ "github.com/ethereum/go-ethereum/trie"
+)
+
+type replayer struct {
+ paths []string // sort in fifo order
+ hashes []common.Hash // empty for deletion
+ unknowns int // counter for unknown write
+}
+
+func newBatchReplay() *replayer {
+ return &replayer{}
+}
+
+func (r *replayer) decode(key []byte, value []byte) {
+ account := rawdb.IsAccountTrieNode(key)
+ storage := rawdb.IsStorageTrieNode(key)
+ if !account && !storage {
+ r.unknowns += 1
+ return
+ }
+ var path []byte
+ if account {
+ _, path = rawdb.ResolveAccountTrieNodeKey(key)
+ } else {
+ _, owner, inner := rawdb.ResolveStorageTrieNode(key)
+ path = append(owner.Bytes(), inner...)
+ }
+ r.paths = append(r.paths, string(path))
+
+ if len(value) == 0 {
+ r.hashes = append(r.hashes, common.Hash{})
+ } else {
+ r.hashes = append(r.hashes, crypto.Keccak256Hash(value))
+ }
+}
+
+// updates returns a set of effective mutations. Multiple mutations targeting
+// the same node path will be merged in FIFO order.
+func (r *replayer) modifies() map[string]common.Hash {
+ set := make(map[string]common.Hash)
+ for i, path := range r.paths {
+ set[path] = r.hashes[i]
+ }
+ return set
+}
+
+// updates returns the number of updates.
+func (r *replayer) updates() int {
+ var count int
+ for _, hash := range r.modifies() {
+ if hash == (common.Hash{}) {
+ continue
+ }
+ count++
+ }
+ return count
+}
+
+// Put inserts the given value into the key-value data store.
+func (r *replayer) Put(key []byte, value []byte) error {
+ r.decode(key, value)
+ return nil
+}
+
+// Delete removes the key from the key-value data store.
+func (r *replayer) Delete(key []byte) error {
+ r.decode(key, nil)
+ return nil
+}
+
+func byteToHex(str []byte) []byte {
+ l := len(str) * 2
+ var nibbles = make([]byte, l)
+ for i, b := range str {
+ nibbles[i*2] = b / 16
+ nibbles[i*2+1] = b % 16
+ }
+ return nibbles
+}
+
+// innerNodes returns the internal nodes narrowed by two boundaries along with
+// the leftmost and rightmost sub-trie roots.
+func innerNodes(first, last []byte, includeLeft, includeRight bool, nodes map[string]common.Hash, t *testing.T) (map[string]common.Hash, []byte, []byte) {
+ var (
+ leftRoot []byte
+ rightRoot []byte
+ firstHex = byteToHex(first)
+ lastHex = byteToHex(last)
+ inner = make(map[string]common.Hash)
+ )
+ for path, hash := range nodes {
+ if hash == (common.Hash{}) {
+ t.Fatalf("Unexpected deletion, %v", []byte(path))
+ }
+ // Filter out the siblings on the left side or the left boundary nodes.
+ if !includeLeft && (bytes.Compare(firstHex, []byte(path)) > 0 || bytes.HasPrefix(firstHex, []byte(path))) {
+ continue
+ }
+ // Filter out the siblings on the right side or the right boundary nodes.
+ if !includeRight && (bytes.Compare(lastHex, []byte(path)) < 0 || bytes.HasPrefix(lastHex, []byte(path))) {
+ continue
+ }
+ inner[path] = hash
+
+ // Track the path of the leftmost sub trie root
+ if leftRoot == nil || bytes.Compare(leftRoot, []byte(path)) > 0 {
+ leftRoot = []byte(path)
+ }
+ // Track the path of the rightmost sub trie root
+ if rightRoot == nil ||
+ (bytes.Compare(rightRoot, []byte(path)) < 0) ||
+ (bytes.Compare(rightRoot, []byte(path)) > 0 && bytes.HasPrefix(rightRoot, []byte(path))) {
+ rightRoot = []byte(path)
+ }
+ }
+ return inner, leftRoot, rightRoot
+}
+
+func buildPartial(owner common.Hash, db ethdb.KeyValueReader, batch ethdb.Batch, entries []*kv, first, last int) *replayer {
+ tr := newPathTrie(owner, first != 0, db, batch)
+ for i := first; i <= last; i++ {
+ tr.update(entries[i].k, entries[i].v)
+ }
+ tr.commit(last == len(entries)-1)
+
+ replay := newBatchReplay()
+ batch.Replay(replay)
+
+ return replay
+}
+
+// TestPartialGentree verifies if the trie constructed with partial states can
+// generate consistent trie nodes that match those of the full trie.
+func TestPartialGentree(t *testing.T) {
+ for round := 0; round < 100; round++ {
+ var (
+ n = rand.Intn(1024) + 10
+ entries []*kv
+ )
+ for i := 0; i < n; i++ {
+ var val []byte
+ if rand.Intn(3) == 0 {
+ val = testrand.Bytes(3)
+ } else {
+ val = testrand.Bytes(32)
+ }
+ entries = append(entries, &kv{
+ k: testrand.Bytes(32),
+ v: val,
+ })
+ }
+ slices.SortFunc(entries, (*kv).cmp)
+
+ nodes := make(map[string]common.Hash)
+ tr := trie.NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
+ nodes[string(path)] = hash
+ })
+ for i := 0; i < len(entries); i++ {
+ tr.Update(entries[i].k, entries[i].v)
+ }
+ tr.Hash()
+
+ check := func(first, last int) {
+ var (
+ db = rawdb.NewMemoryDatabase()
+ batch = db.NewBatch()
+ )
+ // Build the partial tree with specific boundaries
+ r := buildPartial(common.Hash{}, db, batch, entries, first, last)
+ if r.unknowns > 0 {
+ t.Fatalf("Unknown database write: %d", r.unknowns)
+ }
+
+ // Ensure all the internal nodes are produced
+ var (
+ set = r.modifies()
+ inner, _, _ = innerNodes(entries[first].k, entries[last].k, first == 0, last == len(entries)-1, nodes, t)
+ )
+ for path, hash := range inner {
+ if _, ok := set[path]; !ok {
+ t.Fatalf("Missing nodes %v", []byte(path))
+ }
+ if hash != set[path] {
+ t.Fatalf("Inconsistent node, want %x, got: %x", hash, set[path])
+ }
+ }
+ if r.updates() != len(inner) {
+ t.Fatalf("Unexpected node write detected, want: %d, got: %d", len(inner), r.updates())
+ }
+ }
+ for j := 0; j < 100; j++ {
+ var (
+ first int
+ last int
+ )
+ for {
+ first = rand.Intn(len(entries))
+ last = rand.Intn(len(entries))
+ if first <= last {
+ break
+ }
+ }
+ check(first, last)
+ }
+ var cases = []struct {
+ first int
+ last int
+ }{
+ {0, len(entries) - 1}, // full
+ {1, len(entries) - 1}, // no left
+ {2, len(entries) - 1}, // no left
+ {2, len(entries) - 2}, // no left and right
+ {2, len(entries) - 2}, // no left and right
+ {len(entries) / 2, len(entries) / 2}, // single
+ {0, 0}, // single first
+ {len(entries) - 1, len(entries) - 1}, // single last
+ }
+ for _, c := range cases {
+ check(c.first, c.last)
+ }
+ }
+}
+
+// TestGentreeDanglingClearing tests if the dangling nodes falling within the
+// path space of constructed tree can be correctly removed.
+func TestGentreeDanglingClearing(t *testing.T) {
+ for round := 0; round < 100; round++ {
+ var (
+ n = rand.Intn(1024) + 10
+ entries []*kv
+ )
+ for i := 0; i < n; i++ {
+ var val []byte
+ if rand.Intn(3) == 0 {
+ val = testrand.Bytes(3)
+ } else {
+ val = testrand.Bytes(32)
+ }
+ entries = append(entries, &kv{
+ k: testrand.Bytes(32),
+ v: val,
+ })
+ }
+ slices.SortFunc(entries, (*kv).cmp)
+
+ nodes := make(map[string]common.Hash)
+ tr := trie.NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
+ nodes[string(path)] = hash
+ })
+ for i := 0; i < len(entries); i++ {
+ tr.Update(entries[i].k, entries[i].v)
+ }
+ tr.Hash()
+
+ check := func(first, last int) {
+ var (
+ db = rawdb.NewMemoryDatabase()
+ batch = db.NewBatch()
+ )
+ // Write the junk nodes as the dangling
+ var injects []string
+ for path := range nodes {
+ for i := 0; i < len(path); i++ {
+ _, ok := nodes[path[:i]]
+ if ok {
+ continue
+ }
+ injects = append(injects, path[:i])
+ }
+ }
+ if len(injects) == 0 {
+ return
+ }
+ for _, path := range injects {
+ rawdb.WriteAccountTrieNode(db, []byte(path), testrand.Bytes(32))
+ }
+
+ // Build the partial tree with specific range
+ replay := buildPartial(common.Hash{}, db, batch, entries, first, last)
+ if replay.unknowns > 0 {
+ t.Fatalf("Unknown database write: %d", replay.unknowns)
+ }
+ set := replay.modifies()
+
+ // Make sure the injected junks falling within the path space of
+ // committed trie nodes are correctly deleted.
+ _, leftRoot, rightRoot := innerNodes(entries[first].k, entries[last].k, first == 0, last == len(entries)-1, nodes, t)
+ for _, path := range injects {
+ if bytes.Compare([]byte(path), leftRoot) < 0 && !bytes.HasPrefix(leftRoot, []byte(path)) {
+ continue
+ }
+ if bytes.Compare([]byte(path), rightRoot) > 0 {
+ continue
+ }
+ if hash, ok := set[path]; !ok || hash != (common.Hash{}) {
+ t.Fatalf("Missing delete, %v", []byte(path))
+ }
+ }
+ }
+ for j := 0; j < 100; j++ {
+ var (
+ first int
+ last int
+ )
+ for {
+ first = rand.Intn(len(entries))
+ last = rand.Intn(len(entries))
+ if first <= last {
+ break
+ }
+ }
+ check(first, last)
+ }
+ var cases = []struct {
+ first int
+ last int
+ }{
+ {0, len(entries) - 1}, // full
+ {1, len(entries) - 1}, // no left
+ {2, len(entries) - 1}, // no left
+ {2, len(entries) - 2}, // no left and right
+ {2, len(entries) - 2}, // no left and right
+ {len(entries) / 2, len(entries) / 2}, // single
+ {0, 0}, // single first
+ {len(entries) - 1, len(entries) - 1}, // single last
+ }
+ for _, c := range cases {
+ check(c.first, c.last)
+ }
+ }
+}
+
+// TestFlushPartialTree tests the gentrie can produce complete inner trie nodes
+// even with lots of batch flushes.
+func TestFlushPartialTree(t *testing.T) {
+ var entries []*kv
+ for i := 0; i < 1024; i++ {
+ var val []byte
+ if rand.Intn(3) == 0 {
+ val = testrand.Bytes(3)
+ } else {
+ val = testrand.Bytes(32)
+ }
+ entries = append(entries, &kv{
+ k: testrand.Bytes(32),
+ v: val,
+ })
+ }
+ slices.SortFunc(entries, (*kv).cmp)
+
+ nodes := make(map[string]common.Hash)
+ tr := trie.NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
+ nodes[string(path)] = hash
+ })
+ for i := 0; i < len(entries); i++ {
+ tr.Update(entries[i].k, entries[i].v)
+ }
+ tr.Hash()
+
+ var cases = []struct {
+ first int
+ last int
+ }{
+ {0, len(entries) - 1}, // full
+ {1, len(entries) - 1}, // no left
+ {10, len(entries) - 1}, // no left
+ {10, len(entries) - 2}, // no left and right
+ {10, len(entries) - 10}, // no left and right
+ {11, 11}, // single
+ {0, 0}, // single first
+ {len(entries) - 1, len(entries) - 1}, // single last
+ }
+ for _, c := range cases {
+ var (
+ db = rawdb.NewMemoryDatabase()
+ batch = db.NewBatch()
+ combined = db.NewBatch()
+ )
+ inner, _, _ := innerNodes(entries[c.first].k, entries[c.last].k, c.first == 0, c.last == len(entries)-1, nodes, t)
+
+ tr := newPathTrie(common.Hash{}, c.first != 0, db, batch)
+ for i := c.first; i <= c.last; i++ {
+ tr.update(entries[i].k, entries[i].v)
+ if rand.Intn(2) == 0 {
+ tr.commit(false)
+
+ batch.Replay(combined)
+ batch.Write()
+ batch.Reset()
+ }
+ }
+ tr.commit(c.last == len(entries)-1)
+
+ batch.Replay(combined)
+ batch.Write()
+ batch.Reset()
+
+ r := newBatchReplay()
+ combined.Replay(r)
+
+ // Ensure all the internal nodes are produced
+ set := r.modifies()
+ for path, hash := range inner {
+ if _, ok := set[path]; !ok {
+ t.Fatalf("Missing nodes %v", []byte(path))
+ }
+ if hash != set[path] {
+ t.Fatalf("Inconsistent node, want %x, got: %x", hash, set[path])
+ }
+ }
+ if r.updates() != len(inner) {
+ t.Fatalf("Unexpected node write detected, want: %d, got: %d", len(inner), r.updates())
+ }
+ }
+}
+
+// TestBoundSplit ensures two consecutive trie chunks are not overlapped with
+// each other.
+func TestBoundSplit(t *testing.T) {
+ var entries []*kv
+ for i := 0; i < 1024; i++ {
+ var val []byte
+ if rand.Intn(3) == 0 {
+ val = testrand.Bytes(3)
+ } else {
+ val = testrand.Bytes(32)
+ }
+ entries = append(entries, &kv{
+ k: testrand.Bytes(32),
+ v: val,
+ })
+ }
+ slices.SortFunc(entries, (*kv).cmp)
+
+ for j := 0; j < 100; j++ {
+ var (
+ next int
+ last int
+ db = rawdb.NewMemoryDatabase()
+
+ lastRightRoot []byte
+ )
+ for {
+ if next == len(entries) {
+ break
+ }
+ last = rand.Intn(len(entries)-next) + next
+
+ r := buildPartial(common.Hash{}, db, db.NewBatch(), entries, next, last)
+ set := r.modifies()
+
+ // Skip if the chunk is zero-size
+ if r.updates() == 0 {
+ next = last + 1
+ continue
+ }
+
+ // Ensure the updates in two consecutive chunks are not overlapped.
+ // The only overlapping part should be deletion.
+ if lastRightRoot != nil && len(set) > 0 {
+ // Derive the path of left-most node in this chunk
+ var leftRoot []byte
+ for path, hash := range r.modifies() {
+ if hash == (common.Hash{}) {
+ t.Fatalf("Unexpected deletion %v", []byte(path))
+ }
+ if leftRoot == nil || bytes.Compare(leftRoot, []byte(path)) > 0 {
+ leftRoot = []byte(path)
+ }
+ }
+ if bytes.HasPrefix(lastRightRoot, leftRoot) || bytes.HasPrefix(leftRoot, lastRightRoot) {
+ t.Fatalf("Two chunks are not correctly separated, lastRight: %v, left: %v", lastRightRoot, leftRoot)
+ }
+ }
+
+ // Track the updates as the last chunk
+ var rightRoot []byte
+ for path := range set {
+ if rightRoot == nil ||
+ (bytes.Compare(rightRoot, []byte(path)) < 0) ||
+ (bytes.Compare(rightRoot, []byte(path)) > 0 && bytes.HasPrefix(rightRoot, []byte(path))) {
+ rightRoot = []byte(path)
+ }
+ }
+ lastRightRoot = rightRoot
+ next = last + 1
+ }
+ }
+}
+
+// TestTinyPartialTree tests if the partial tree is too tiny(has less than two
+// states), then nothing should be committed.
+func TestTinyPartialTree(t *testing.T) {
+ var entries []*kv
+ for i := 0; i < 1024; i++ {
+ var val []byte
+ if rand.Intn(3) == 0 {
+ val = testrand.Bytes(3)
+ } else {
+ val = testrand.Bytes(32)
+ }
+ entries = append(entries, &kv{
+ k: testrand.Bytes(32),
+ v: val,
+ })
+ }
+ slices.SortFunc(entries, (*kv).cmp)
+
+ for i := 0; i < len(entries); i++ {
+ next := i
+ last := i + 1
+ if last >= len(entries) {
+ last = len(entries) - 1
+ }
+ db := rawdb.NewMemoryDatabase()
+ r := buildPartial(common.Hash{}, db, db.NewBatch(), entries, next, last)
+
+ if next != 0 && last != len(entries)-1 {
+ if r.updates() != 0 {
+ t.Fatalf("Unexpected data writes, got: %d", r.updates())
+ }
+ }
+ }
+}
diff --git a/eth/protocols/snap/handler.go b/eth/protocols/snap/handler.go
index 41039d7779..8ba3209510 100644
--- a/eth/protocols/snap/handler.go
+++ b/eth/protocols/snap/handler.go
@@ -344,13 +344,7 @@ func ServiceGetAccountRangeQuery(chain *core.BlockChain, req *GetAccountRangePac
return nil, nil
}
}
-
- var proofs [][]byte
- for _, blob := range proof.List() {
- proofs = append(proofs, blob)
- }
-
- return accounts, proofs
+ return accounts, proof.List()
}
func ServiceGetStorageRangesQuery(chain *core.BlockChain, req *GetStorageRangesPacket) ([][]*StorageData, [][]byte) {
@@ -461,9 +455,7 @@ func ServiceGetStorageRangesQuery(chain *core.BlockChain, req *GetStorageRangesP
return nil, nil
}
}
- for _, blob := range proof.List() {
- proofs = append(proofs, blob)
- }
+ proofs = append(proofs, proof.List()...)
// Proof terminates the reply as proofs are only added if a node
// refuses to serve more data (exception when a contract fetch is
// finishing, but that's that).
diff --git a/eth/protocols/snap/handler_fuzzing_test.go b/eth/protocols/snap/handler_fuzzing_test.go
index cec185075d..b40cb8b971 100644
--- a/eth/protocols/snap/handler_fuzzing_test.go
+++ b/eth/protocols/snap/handler_fuzzing_test.go
@@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode"
@@ -89,7 +90,7 @@ func doFuzz(input []byte, obj interface{}, code int) {
var trieRoot common.Hash
func getChain() *core.BlockChain {
- ga := make(core.GenesisAlloc, 1000)
+ ga := make(types.GenesisAlloc, 1000)
var a = make([]byte, 20)
@@ -111,7 +112,7 @@ func getChain() *core.BlockChain {
for i := 0; i < 1000; i++ {
binary.LittleEndian.PutUint64(a, uint64(i+0xff))
- acc := core.GenesisAccount{Balance: big.NewInt(int64(i))}
+ acc := types.Account{Balance: big.NewInt(int64(i))}
if i%2 == 1 {
acc.Storage = storage
}
diff --git a/eth/protocols/snap/metrics.go b/eth/protocols/snap/metrics.go
index a7d071953f..6878e5b280 100644
--- a/eth/protocols/snap/metrics.go
+++ b/eth/protocols/snap/metrics.go
@@ -17,7 +17,7 @@
package snap
import (
- metrics "github.com/ethereum/go-ethereum/metrics"
+ "github.com/ethereum/go-ethereum/metrics"
)
var (
@@ -27,21 +27,28 @@ var (
IngressRegistrationErrorMeter = metrics.NewRegisteredMeter(ingressRegistrationErrorName, nil)
EgressRegistrationErrorMeter = metrics.NewRegisteredMeter(egressRegistrationErrorName, nil)
- // deletionGauge is the metric to track how many trie node deletions
- // are performed in total during the sync process.
- deletionGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/delete", nil)
+ // accountInnerDeleteGauge is the metric to track how many dangling trie nodes
+ // covered by extension node in account trie are deleted during the sync.
+ accountInnerDeleteGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/delete/account/inner", nil)
- // lookupGauge is the metric to track how many trie node lookups are
- // performed to determine if node needs to be deleted.
- lookupGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/lookup", nil)
+ // storageInnerDeleteGauge is the metric to track how many dangling trie nodes
+ // covered by extension node in storage trie are deleted during the sync.
+ storageInnerDeleteGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/delete/storage/inner", nil)
+
+ // accountOuterDeleteGauge is the metric to track how many dangling trie nodes
+ // above the committed nodes in account trie are deleted during the sync.
+ accountOuterDeleteGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/delete/account/outer", nil)
- // boundaryAccountNodesGauge is the metric to track how many boundary trie
- // nodes in account trie are met.
- boundaryAccountNodesGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/boundary/account", nil)
+ // storageOuterDeleteGauge is the metric to track how many dangling trie nodes
+ // above the committed nodes in storage trie are deleted during the sync.
+ storageOuterDeleteGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/delete/storage/outer", nil)
- // boundaryAccountNodesGauge is the metric to track how many boundary trie
- // nodes in storage tries are met.
- boundaryStorageNodesGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/boundary/storage", nil)
+ // lookupGauge is the metric to track how many trie node lookups are
+ // performed to determine if node needs to be deleted.
+ accountInnerLookupGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/account/lookup/inner", nil)
+ accountOuterLookupGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/account/lookup/outer", nil)
+ storageInnerLookupGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/lookup/inner", nil)
+ storageOuterLookupGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/lookup/outer", nil)
// smallStorageGauge is the metric to track how many storages are small enough
// to retrieved in one or two request.
@@ -54,4 +61,9 @@ var (
// skipStorageHealingGauge is the metric to track how many storages are retrieved
// in multiple requests but healing is not necessary.
skipStorageHealingGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/noheal", nil)
+
+ // largeStorageDiscardGauge is the metric to track how many chunked storages are
+ // discarded during the snap sync.
+ largeStorageDiscardGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/chunk/discard", nil)
+ largeStorageResumedGauge = metrics.NewRegisteredGauge("eth/protocols/snap/sync/storage/chunk/resume", nil)
)
diff --git a/eth/protocols/snap/peer.go b/eth/protocols/snap/peer.go
index 3e397c0f92..d336c34a58 100644
--- a/eth/protocols/snap/peer.go
+++ b/eth/protocols/snap/peer.go
@@ -33,7 +33,7 @@ type Peer struct {
logger log.Logger // Contextual logger with the peer id injected
}
-// NewPeer create a wrapper for a network connection and negotiated protocol
+// NewPeer creates a wrapper for a network connection and negotiated protocol
// version.
func NewPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) *Peer {
id := p.ID().String()
@@ -47,7 +47,7 @@ func NewPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) *Peer {
}
}
-// NewFakePeer create a fake snap peer without a backing p2p peer, for testing purposes.
+// NewFakePeer creates a fake snap peer without a backing p2p peer, for testing purposes.
func NewFakePeer(version uint, id string, rw p2p.MsgReadWriter) *Peer {
return &Peer{
id: id,
diff --git a/eth/protocols/snap/progress_test.go b/eth/protocols/snap/progress_test.go
new file mode 100644
index 0000000000..1d9a6b8474
--- /dev/null
+++ b/eth/protocols/snap/progress_test.go
@@ -0,0 +1,154 @@
+// Copyright 2024 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 snap
+
+import (
+ "encoding/json"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+// Legacy sync progress definitions
+type legacyStorageTask struct {
+ Next common.Hash // Next account to sync in this interval
+ Last common.Hash // Last account to sync in this interval
+}
+
+type legacyAccountTask struct {
+ Next common.Hash // Next account to sync in this interval
+ Last common.Hash // Last account to sync in this interval
+ SubTasks map[common.Hash][]*legacyStorageTask // Storage intervals needing fetching for large contracts
+}
+
+type legacyProgress struct {
+ Tasks []*legacyAccountTask // The suspended account tasks (contract tasks within)
+}
+
+func compareProgress(a legacyProgress, b SyncProgress) bool {
+ if len(a.Tasks) != len(b.Tasks) {
+ return false
+ }
+ for i := 0; i < len(a.Tasks); i++ {
+ if a.Tasks[i].Next != b.Tasks[i].Next {
+ return false
+ }
+ if a.Tasks[i].Last != b.Tasks[i].Last {
+ return false
+ }
+ // new fields are not checked here
+
+ if len(a.Tasks[i].SubTasks) != len(b.Tasks[i].SubTasks) {
+ return false
+ }
+ for addrHash, subTasksA := range a.Tasks[i].SubTasks {
+ subTasksB, ok := b.Tasks[i].SubTasks[addrHash]
+ if !ok || len(subTasksB) != len(subTasksA) {
+ return false
+ }
+ for j := 0; j < len(subTasksA); j++ {
+ if subTasksA[j].Next != subTasksB[j].Next {
+ return false
+ }
+ if subTasksA[j].Last != subTasksB[j].Last {
+ return false
+ }
+ }
+ }
+ }
+ return true
+}
+
+func makeLegacyProgress() legacyProgress {
+ return legacyProgress{
+ Tasks: []*legacyAccountTask{
+ {
+ Next: common.Hash{},
+ Last: common.Hash{0x77},
+ SubTasks: map[common.Hash][]*legacyStorageTask{
+ {0x1}: {
+ {
+ Next: common.Hash{},
+ Last: common.Hash{0xff},
+ },
+ },
+ },
+ },
+ {
+ Next: common.Hash{0x88},
+ Last: common.Hash{0xff},
+ },
+ },
+ }
+}
+
+func convertLegacy(legacy legacyProgress) SyncProgress {
+ var progress SyncProgress
+ for i, task := range legacy.Tasks {
+ subTasks := make(map[common.Hash][]*storageTask)
+ for owner, list := range task.SubTasks {
+ var cpy []*storageTask
+ for i := 0; i < len(list); i++ {
+ cpy = append(cpy, &storageTask{
+ Next: list[i].Next,
+ Last: list[i].Last,
+ })
+ }
+ subTasks[owner] = cpy
+ }
+ accountTask := &accountTask{
+ Next: task.Next,
+ Last: task.Last,
+ SubTasks: subTasks,
+ }
+ if i == 0 {
+ accountTask.StorageCompleted = []common.Hash{{0xaa}, {0xbb}} // fulfill new fields
+ }
+ progress.Tasks = append(progress.Tasks, accountTask)
+ }
+ return progress
+}
+
+func TestSyncProgressCompatibility(t *testing.T) {
+ // Decode serialized bytes of legacy progress, backward compatibility
+ legacy := makeLegacyProgress()
+ blob, err := json.Marshal(legacy)
+ if err != nil {
+ t.Fatalf("Failed to marshal progress %v", err)
+ }
+ var dec SyncProgress
+ if err := json.Unmarshal(blob, &dec); err != nil {
+ t.Fatalf("Failed to unmarshal progress %v", err)
+ }
+ if !compareProgress(legacy, dec) {
+ t.Fatal("sync progress is not backward compatible")
+ }
+
+ // Decode serialized bytes of new format progress
+ progress := convertLegacy(legacy)
+ blob, err = json.Marshal(progress)
+ if err != nil {
+ t.Fatalf("Failed to marshal progress %v", err)
+ }
+ var legacyDec legacyProgress
+ if err := json.Unmarshal(blob, &legacyDec); err != nil {
+ t.Fatalf("Failed to unmarshal progress %v", err)
+ }
+ if !compareProgress(legacyDec, progress) {
+ t.Fatal("sync progress is not forward compatible")
+ }
+}
diff --git a/eth/protocols/snap/sync.go b/eth/protocols/snap/sync.go
index d3b27b7c66..6377576565 100644
--- a/eth/protocols/snap/sync.go
+++ b/eth/protocols/snap/sync.go
@@ -95,6 +95,9 @@ const (
// trienodeHealThrottleDecrease is the divisor for the throttle when the
// rate of arriving data is lower than the rate of processing it.
trienodeHealThrottleDecrease = 1.25
+
+ // batchSizeThreshold is the maximum size allowed for gentrie batch.
+ batchSizeThreshold = 8 * 1024 * 1024
)
var (
@@ -296,11 +299,19 @@ type bytecodeHealResponse struct {
// accountTask represents the sync task for a chunk of the account snapshot.
type accountTask struct {
- // These fields get serialized to leveldb on shutdown
+ // These fields get serialized to key-value store on shutdown
Next common.Hash // Next account to sync in this interval
Last common.Hash // Last account to sync in this interval
SubTasks map[common.Hash][]*storageTask // Storage intervals needing fetching for large contracts
+ // This is a list of account hashes whose storage are already completed
+ // in this cycle. This field is newly introduced in v1.14 and will be
+ // empty if the task is resolved from legacy progress data. Furthermore,
+ // this additional field will be ignored by legacy Geth. The only side
+ // effect is that these contracts might be resynced in the new cycle,
+ // retaining the legacy behavior.
+ StorageCompleted []common.Hash `json:",omitempty"`
+
// These fields are internals used during runtime
req *accountRequest // Pending request to fill this task
res *accountResponse // Validate response filling this task
@@ -310,15 +321,40 @@ type accountTask struct {
needState []bool // Flags whether the filling accounts need storage retrieval
needHeal []bool // Flags whether the filling accounts's state was chunked and need healing
- codeTasks map[common.Hash]struct{} // Code hashes that need retrieval
- stateTasks map[common.Hash]common.Hash // Account hashes->roots that need full state retrieval
+ codeTasks map[common.Hash]struct{} // Code hashes that need retrieval
+ stateTasks map[common.Hash]common.Hash // Account hashes->roots that need full state retrieval
+ stateCompleted map[common.Hash]struct{} // Account hashes whose storage have been completed
- genBatch ethdb.Batch // Batch used by the node generator
- genTrie *trie.StackTrie // Node generator from storage slots
+ genBatch ethdb.Batch // Batch used by the node generator
+ genTrie genTrie // Node generator from storage slots
done bool // Flag whether the task can be removed
}
+// activeSubTasks returns the set of storage tasks covered by the current account
+// range. Normally this would be the entire subTask set, but on a sync interrupt
+// and later resume it can happen that a shorter account range is retrieved. This
+// method ensures that we only start up the subtasks covered by the latest account
+// response.
+//
+// Nil is returned if the account range is empty.
+func (task *accountTask) activeSubTasks() map[common.Hash][]*storageTask {
+ if len(task.res.hashes) == 0 {
+ return nil
+ }
+ var (
+ tasks = make(map[common.Hash][]*storageTask)
+ last = task.res.hashes[len(task.res.hashes)-1]
+ )
+ for hash, subTasks := range task.SubTasks {
+ subTasks := subTasks // closure
+ if hash.Cmp(last) <= 0 {
+ tasks[hash] = subTasks
+ }
+ }
+ return tasks
+}
+
// storageTask represents the sync task for a chunk of the storage snapshot.
type storageTask struct {
Next common.Hash // Next account to sync in this interval
@@ -328,8 +364,8 @@ type storageTask struct {
root common.Hash // Storage root hash for this instance
req *storageRequest // Pending request to fill this task
- genBatch ethdb.Batch // Batch used by the node generator
- genTrie *trie.StackTrie // Node generator from storage slots
+ genBatch ethdb.Batch // Batch used by the node generator
+ genTrie genTrie // Node generator from storage slots
done bool // Flag whether the task can be removed
}
@@ -730,19 +766,6 @@ func (s *Syncer) Sync(root common.Hash, cancel chan struct{}) error {
}
}
-// cleanPath is used to remove the dangling nodes in the stackTrie.
-func (s *Syncer) cleanPath(batch ethdb.Batch, owner common.Hash, path []byte) {
- if owner == (common.Hash{}) && rawdb.ExistsAccountTrieNode(s.db, path) {
- rawdb.DeleteAccountTrieNode(batch, path)
- deletionGauge.Inc(1)
- }
- if owner != (common.Hash{}) && rawdb.ExistsStorageTrieNode(s.db, owner, path) {
- rawdb.DeleteStorageTrieNode(batch, owner, path)
- deletionGauge.Inc(1)
- }
- lookupGauge.Inc(1)
-}
-
// loadSyncStatus retrieves a previously aborted sync status from the database,
// or generates a fresh one if none is available.
func (s *Syncer) loadSyncStatus() {
@@ -760,28 +783,27 @@ func (s *Syncer) loadSyncStatus() {
for _, task := range s.tasks {
task := task // closure for task.genBatch in the stacktrie writer callback
+ // Restore the completed storages
+ task.stateCompleted = make(map[common.Hash]struct{})
+ for _, hash := range task.StorageCompleted {
+ task.stateCompleted[hash] = struct{}{}
+ }
+ task.StorageCompleted = nil
+
+ // Allocate batch for account trie generation
task.genBatch = ethdb.HookedBatch{
Batch: s.db.NewBatch(),
OnPut: func(key []byte, value []byte) {
s.accountBytes += common.StorageSize(len(key) + len(value))
},
}
- options := trie.NewStackTrieOptions()
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
- rawdb.WriteTrieNode(task.genBatch, common.Hash{}, path, hash, blob, s.scheme)
- })
+ if s.scheme == rawdb.HashScheme {
+ task.genTrie = newHashTrie(task.genBatch)
+ }
if s.scheme == rawdb.PathScheme {
- // Configure the dangling node cleaner and also filter out boundary nodes
- // only in the context of the path scheme. Deletion is forbidden in the
- // hash scheme, as it can disrupt state completeness.
- options = options.WithCleaner(func(path []byte) {
- s.cleanPath(task.genBatch, common.Hash{}, path)
- })
- // Skip the left boundary if it's not the first range.
- // Skip the right boundary if it's not the last range.
- options = options.WithSkipBoundary(task.Next != (common.Hash{}), task.Last != common.MaxHash, boundaryAccountNodesGauge)
+ task.genTrie = newPathTrie(common.Hash{}, task.Next != common.Hash{}, s.db, task.genBatch)
}
- task.genTrie = trie.NewStackTrie(options)
+ // Restore leftover storage tasks
for accountHash, subtasks := range task.SubTasks {
for _, subtask := range subtasks {
subtask := subtask // closure for subtask.genBatch in the stacktrie writer callback
@@ -792,23 +814,12 @@ func (s *Syncer) loadSyncStatus() {
s.storageBytes += common.StorageSize(len(key) + len(value))
},
}
- owner := accountHash // local assignment for stacktrie writer closure
- options := trie.NewStackTrieOptions()
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
- rawdb.WriteTrieNode(subtask.genBatch, owner, path, hash, blob, s.scheme)
- })
+ if s.scheme == rawdb.HashScheme {
+ subtask.genTrie = newHashTrie(subtask.genBatch)
+ }
if s.scheme == rawdb.PathScheme {
- // Configure the dangling node cleaner and also filter out boundary nodes
- // only in the context of the path scheme. Deletion is forbidden in the
- // hash scheme, as it can disrupt state completeness.
- options = options.WithCleaner(func(path []byte) {
- s.cleanPath(subtask.genBatch, owner, path)
- })
- // Skip the left boundary if it's not the first range.
- // Skip the right boundary if it's not the last range.
- options = options.WithSkipBoundary(subtask.Next != common.Hash{}, subtask.Last != common.MaxHash, boundaryStorageNodesGauge)
+ subtask.genTrie = newPathTrie(accountHash, subtask.Next != common.Hash{}, s.db, subtask.genBatch)
}
- subtask.genTrie = trie.NewStackTrie(options)
}
}
}
@@ -864,27 +875,20 @@ func (s *Syncer) loadSyncStatus() {
s.accountBytes += common.StorageSize(len(key) + len(value))
},
}
- options := trie.NewStackTrieOptions()
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
- rawdb.WriteTrieNode(batch, common.Hash{}, path, hash, blob, s.scheme)
- })
+ var tr genTrie
+ if s.scheme == rawdb.HashScheme {
+ tr = newHashTrie(batch)
+ }
if s.scheme == rawdb.PathScheme {
- // Configure the dangling node cleaner and also filter out boundary nodes
- // only in the context of the path scheme. Deletion is forbidden in the
- // hash scheme, as it can disrupt state completeness.
- options = options.WithCleaner(func(path []byte) {
- s.cleanPath(batch, common.Hash{}, path)
- })
- // Skip the left boundary if it's not the first range.
- // Skip the right boundary if it's not the last range.
- options = options.WithSkipBoundary(next != common.Hash{}, last != common.MaxHash, boundaryAccountNodesGauge)
+ tr = newPathTrie(common.Hash{}, next != common.Hash{}, s.db, batch)
}
s.tasks = append(s.tasks, &accountTask{
- Next: next,
- Last: last,
- SubTasks: make(map[common.Hash][]*storageTask),
- genBatch: batch,
- genTrie: trie.NewStackTrie(options),
+ Next: next,
+ Last: last,
+ SubTasks: make(map[common.Hash][]*storageTask),
+ genBatch: batch,
+ stateCompleted: make(map[common.Hash]struct{}),
+ genTrie: tr,
})
log.Debug("Created account sync task", "from", next, "last", last)
@@ -896,17 +900,32 @@ func (s *Syncer) loadSyncStatus() {
func (s *Syncer) saveSyncStatus() {
// Serialize any partial progress to disk before spinning down
for _, task := range s.tasks {
+ // Claim the right boundary as incomplete before flushing the
+ // accumulated nodes in batch, the nodes on right boundary
+ // will be discarded and cleaned up by this call.
+ task.genTrie.commit(false)
if err := task.genBatch.Write(); err != nil {
log.Error("Failed to persist account slots", "err", err)
}
for _, subtasks := range task.SubTasks {
for _, subtask := range subtasks {
+ // Same for account trie, discard and cleanup the
+ // incomplete right boundary.
+ subtask.genTrie.commit(false)
if err := subtask.genBatch.Write(); err != nil {
log.Error("Failed to persist storage slots", "err", err)
}
}
}
+ // Save the account hashes of completed storage.
+ task.StorageCompleted = make([]common.Hash, 0, len(task.stateCompleted))
+ for hash := range task.stateCompleted {
+ task.StorageCompleted = append(task.StorageCompleted, hash)
+ }
+ if len(task.StorageCompleted) > 0 {
+ log.Debug("Leftover completed storages", "number", len(task.StorageCompleted), "next", task.Next, "last", task.Last)
+ }
}
// Store the actual progress markers
progress := &SyncProgress{
@@ -998,6 +1017,10 @@ func (s *Syncer) cleanStorageTasks() {
task.pend--
+ // Mark the state as complete to prevent resyncing, regardless
+ // if state healing is necessary.
+ task.stateCompleted[account] = struct{}{}
+
// If this was the last pending task, forward the account task
if task.pend == 0 {
s.forwardAccountTask(task)
@@ -1267,7 +1290,8 @@ func (s *Syncer) assignStorageTasks(success chan *storageResponse, fail chan *st
continue
}
// Skip tasks that are already retrieving (or done with) all small states
- if len(task.SubTasks) == 0 && len(task.stateTasks) == 0 {
+ storageTasks := task.activeSubTasks()
+ if len(storageTasks) == 0 && len(task.stateTasks) == 0 {
continue
}
// Task pending retrieval, try to find an idle peer. If no such peer
@@ -1318,7 +1342,6 @@ func (s *Syncer) assignStorageTasks(success chan *storageResponse, fail chan *st
roots = make([]common.Hash, 0, storageSets)
subtask *storageTask
)
-
for account, subtasks := range task.SubTasks {
for _, st := range subtasks {
// Skip any subtasks already filling
@@ -1968,11 +1991,11 @@ func (s *Syncer) processAccountResponse(res *accountResponse) {
res.task.res = res
// Ensure that the response doesn't overflow into the subsequent task
- last := res.task.Last.Big()
+ lastBig := res.task.Last.Big()
for i, hash := range res.hashes {
// Mark the range complete if the last is already included.
// Keep iteration to delete the extra states if exists.
- cmp := hash.Big().Cmp(last)
+ cmp := hash.Big().Cmp(lastBig)
if cmp == 0 {
res.cont = false
continue
@@ -2010,7 +2033,21 @@ func (s *Syncer) processAccountResponse(res *accountResponse) {
}
// Check if the account is a contract with an unknown storage trie
if account.Root != types.EmptyRootHash {
- if !rawdb.HasTrieNode(s.db, res.hashes[i], nil, account.Root, s.scheme) {
+ // If the storage was already retrieved in the last cycle, there's no need
+ // to resync it again, regardless of whether the storage root is consistent
+ // or not.
+ if _, exist := res.task.stateCompleted[res.hashes[i]]; exist {
+ // The leftover storage tasks are not expected, unless system is
+ // very wrong.
+ if _, ok := res.task.SubTasks[res.hashes[i]]; ok {
+ panic(fmt.Errorf("unexpected leftover storage tasks, owner: %x", res.hashes[i]))
+ }
+ // Mark the healing tag if storage root node is inconsistent, or
+ // it's non-existent due to storage chunking.
+ if !rawdb.HasTrieNode(s.db, res.hashes[i], nil, account.Root, s.scheme) {
+ res.task.needHeal[i] = true
+ }
+ } else {
// If there was a previous large state retrieval in progress,
// don't restart it from scratch. This happens if a sync cycle
// is interrupted and resumed later. However, *do* update the
@@ -2024,7 +2061,12 @@ func (s *Syncer) processAccountResponse(res *accountResponse) {
res.task.needHeal[i] = true
resumed[res.hashes[i]] = struct{}{}
+ largeStorageResumedGauge.Inc(1)
} else {
+ // It's possible that in the hash scheme, the storage, along
+ // with the trie nodes of the given root, is already present
+ // in the database. Schedule the storage task anyway to simplify
+ // the logic here.
res.task.stateTasks[res.hashes[i]] = account.Root
}
@@ -2033,13 +2075,29 @@ func (s *Syncer) processAccountResponse(res *accountResponse) {
}
}
}
- // Delete any subtasks that have been aborted but not resumed. This may undo
- // some progress if a new peer gives us less accounts than an old one, but for
- // now we have to live with that.
- for hash := range res.task.SubTasks {
- if _, ok := resumed[hash]; !ok {
- log.Debug("Aborting suspended storage retrieval", "account", hash)
- delete(res.task.SubTasks, hash)
+ // Delete any subtasks that have been aborted but not resumed. It's essential
+ // as the corresponding contract might be self-destructed in this cycle(it's
+ // no longer possible in ethereum as self-destruction is disabled in Cancun
+ // Fork, but the condition is still necessary for other networks).
+ //
+ // Keep the leftover storage tasks if they are not covered by the responded
+ // account range which should be picked up in next account wave.
+ if len(res.hashes) > 0 {
+ // The hash of last delivered account in the response
+ last := res.hashes[len(res.hashes)-1]
+ for hash := range res.task.SubTasks {
+ // TODO(rjl493456442) degrade the log level before merging.
+ if hash.Cmp(last) > 0 {
+ log.Info("Keeping suspended storage retrieval", "account", hash)
+ continue
+ }
+ // TODO(rjl493456442) degrade the log level before merging.
+ // It should never happen in ethereum.
+ if _, ok := resumed[hash]; !ok {
+ log.Error("Aborting suspended storage retrieval", "account", hash)
+ delete(res.task.SubTasks, hash)
+ largeStorageDiscardGauge.Inc(1)
+ }
}
}
// If the account range contained no contracts, or all have been fully filled
@@ -2145,6 +2203,7 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
if res.subTask == nil && res.mainTask.needState[j] && (i < len(res.hashes)-1 || !res.cont) {
res.mainTask.needState[j] = false
res.mainTask.pend--
+ res.mainTask.stateCompleted[account] = struct{}{} // mark it as completed
smallStorageGauge.Inc(1)
}
// If the last contract was chunked, mark it as needing healing
@@ -2196,25 +2255,20 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
s.storageBytes += common.StorageSize(len(key) + len(value))
},
}
- owner := account // local assignment for stacktrie writer closure
- options := trie.NewStackTrieOptions()
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
- rawdb.WriteTrieNode(batch, owner, path, hash, blob, s.scheme)
- })
+ var tr genTrie
+ if s.scheme == rawdb.HashScheme {
+ tr = newHashTrie(batch)
+ }
if s.scheme == rawdb.PathScheme {
- options = options.WithCleaner(func(path []byte) {
- s.cleanPath(batch, owner, path)
- })
// Keep the left boundary as it's the first range.
- // Skip the right boundary if it's not the last range.
- options = options.WithSkipBoundary(false, r.End() != common.MaxHash, boundaryStorageNodesGauge)
+ tr = newPathTrie(account, false, s.db, batch)
}
tasks = append(tasks, &storageTask{
Next: common.Hash{},
Last: r.End(),
root: acc.Root,
genBatch: batch,
- genTrie: trie.NewStackTrie(options),
+ genTrie: tr,
})
for r.Next() {
@@ -2224,27 +2278,19 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
s.storageBytes += common.StorageSize(len(key) + len(value))
},
}
- options := trie.NewStackTrieOptions()
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
- rawdb.WriteTrieNode(batch, owner, path, hash, blob, s.scheme)
- })
+ var tr genTrie
+ if s.scheme == rawdb.HashScheme {
+ tr = newHashTrie(batch)
+ }
if s.scheme == rawdb.PathScheme {
- // Configure the dangling node cleaner and also filter out boundary nodes
- // only in the context of the path scheme. Deletion is forbidden in the
- // hash scheme, as it can disrupt state completeness.
- options = options.WithCleaner(func(path []byte) {
- s.cleanPath(batch, owner, path)
- })
- // Skip the left boundary as it's not the first range
- // Skip the right boundary if it's not the last range.
- options = options.WithSkipBoundary(true, r.End() != common.MaxHash, boundaryStorageNodesGauge)
+ tr = newPathTrie(account, true, s.db, batch)
}
tasks = append(tasks, &storageTask{
Next: r.Start(),
Last: r.End(),
root: acc.Root,
genBatch: batch,
- genTrie: trie.NewStackTrie(options),
+ genTrie: tr,
})
}
@@ -2293,26 +2339,18 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
if i < len(res.hashes)-1 || res.subTask == nil {
// no need to make local reassignment of account: this closure does not outlive the loop
- options := trie.NewStackTrieOptions()
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
- rawdb.WriteTrieNode(batch, account, path, hash, blob, s.scheme)
- })
+ var tr genTrie
+ if s.scheme == rawdb.HashScheme {
+ tr = newHashTrie(batch)
+ }
if s.scheme == rawdb.PathScheme {
- // Configure the dangling node cleaner only in the context of the
- // path scheme. Deletion is forbidden in the hash scheme, as it can
- // disrupt state completeness.
- //
- // Notably, boundary nodes can be also kept because the whole storage
- // trie is complete.
- options = options.WithCleaner(func(path []byte) {
- s.cleanPath(batch, account, path)
- })
+ // Keep the left boundary as it's complete
+ tr = newPathTrie(account, false, s.db, batch)
}
- tr := trie.NewStackTrie(options)
for j := 0; j < len(res.hashes[i]); j++ {
- tr.Update(res.hashes[i][j][:], res.slots[i][j])
+ tr.update(res.hashes[i][j][:], res.slots[i][j])
}
- tr.Commit()
+ tr.commit(true)
}
// Persist the received storage segments. These flat state maybe
// outdated during the sync, but it can be fixed later during the
@@ -2323,14 +2361,14 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
// If we're storing large contracts, generate the trie nodes
// on the fly to not trash the gluing points
if i == len(res.hashes)-1 && res.subTask != nil {
- res.subTask.genTrie.Update(res.hashes[i][j][:], res.slots[i][j])
+ res.subTask.genTrie.update(res.hashes[i][j][:], res.slots[i][j])
}
}
}
// Large contracts could have generated new trie nodes, flush them to disk
if res.subTask != nil {
if res.subTask.done {
- root := res.subTask.genTrie.Commit()
+ root := res.subTask.genTrie.commit(res.subTask.Last == common.MaxHash)
if err := res.subTask.genBatch.Write(); err != nil {
log.Error("Failed to persist stack slots", "err", err)
}
@@ -2339,7 +2377,7 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
// If the chunk's root is an overflown but full delivery,
// clear the heal request.
accountHash := res.accounts[len(res.accounts)-1]
- if root == res.subTask.root && rawdb.HasStorageTrieNode(s.db, accountHash, nil, root) {
+ if root == res.subTask.root && rawdb.HasStorageTrieNode(s.db, accountHash, nil) {
for i, account := range res.mainTask.res.hashes {
if account == accountHash {
res.mainTask.needHeal[i] = false
@@ -2347,8 +2385,8 @@ func (s *Syncer) processStorageResponse(res *storageResponse) {
}
}
}
- }
- if res.subTask.genBatch.ValueSize() > ethdb.IdealBatchSize {
+ } else if res.subTask.genBatch.ValueSize() > batchSizeThreshold {
+ res.subTask.genTrie.commit(false)
if err := res.subTask.genBatch.Write(); err != nil {
log.Error("Failed to persist stack slots", "err", err)
}
@@ -2544,8 +2582,7 @@ func (s *Syncer) forwardAccountTask(task *accountTask) {
if err != nil {
panic(err) // Really shouldn't ever happen
}
-
- task.genTrie.Update(hash[:], full)
+ task.genTrie.update(hash[:], full)
}
}
// Flush anything written just now and update the stats
@@ -2563,17 +2600,25 @@ func (s *Syncer) forwardAccountTask(task *accountTask) {
}
task.Next = incHash(hash)
+
+ // Remove the completion flag once the account range is pushed
+ // forward. The leftover accounts will be skipped in the next
+ // cycle.
+ delete(task.stateCompleted, hash)
}
// All accounts marked as complete, track if the entire task is done
task.done = !res.cont
+ // Error out if there is any leftover completion flag.
+ if task.done && len(task.stateCompleted) != 0 {
+ panic(fmt.Errorf("storage completion flags should be emptied, %d left", len(task.stateCompleted)))
+ }
// Stack trie could have generated trie nodes, push them to disk (we need to
// flush after finalizing task.done. It's fine even if we crash and lose this
// write as it will only cause more data to be downloaded during heal.
if task.done {
- task.genTrie.Commit()
+ task.genTrie.commit(false)
}
-
if task.genBatch.ValueSize() > ethdb.IdealBatchSize || task.done {
if err := task.genBatch.Write(); err != nil {
log.Error("Failed to persist stack account", "err", err)
diff --git a/eth/protocols/snap/sync_test.go b/eth/protocols/snap/sync_test.go
index 0c43ff7473..4843ba8bb1 100644
--- a/eth/protocols/snap/sync_test.go
+++ b/eth/protocols/snap/sync_test.go
@@ -23,6 +23,7 @@ import (
"fmt"
"math/big"
mrand "math/rand"
+ "slices"
"sync"
"testing"
"time"
@@ -32,14 +33,15 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/internal/testrand"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
- "github.com/ethereum/go-ethereum/trie/testutil"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
"github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
+ "github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
- "golang.org/x/exp/slices"
)
func TestHashing(t *testing.T) {
@@ -65,7 +67,7 @@ func TestHashing(t *testing.T) {
}
var new = func() {
- hasher := sha3.NewLegacyKeccak256().(crypto.KeccakState)
+ hasher := crypto.NewKeccakState()
var hash = make([]byte, 32)
for i := 0; i < len(bytecodes); i++ {
hasher.Reset()
@@ -101,7 +103,7 @@ func BenchmarkHashing(b *testing.B) {
}
var new = func() {
- hasher := sha3.NewLegacyKeccak256().(crypto.KeccakState)
+ hasher := crypto.NewKeccakState()
var hash = make([]byte, 32)
for i := 0; i < len(bytecodes); i++ {
hasher.Reset()
@@ -313,11 +315,7 @@ func createAccountRequestResponse(t *testPeer, root common.Hash, origin common.H
t.logger.Error("Could not prove last item", "error", err)
}
}
- for _, blob := range proof.List() {
- proofs = append(proofs, blob)
- }
-
- return keys, vals, proofs
+ return keys, vals, proof.List()
}
// defaultStorageRequestHandler is a well-behaving storage request handler
@@ -410,10 +408,7 @@ func createStorageRequestResponse(t *testPeer, root common.Hash, accounts []comm
t.logger.Error("Could not prove last item", "error", err)
}
}
- for _, blob := range proof.List() {
- proofs = append(proofs, blob)
- }
-
+ proofs = append(proofs, proof.List()...)
break
}
}
@@ -481,10 +476,7 @@ func createStorageRequestResponseAlwaysProve(t *testPeer, root common.Hash, acco
t.logger.Error("Could not prove last item", "error", err)
}
}
- for _, blob := range proof.List() {
- proofs = append(proofs, blob)
- }
-
+ proofs = append(proofs, proof.List()...)
break
}
}
@@ -648,9 +640,8 @@ func testSyncBloatedProof(t *testing.T, scheme string) {
source.accountRequestHandler = func(t *testPeer, requestId uint64, root common.Hash, origin common.Hash, limit common.Hash, cap uint64) error {
var (
- proofs [][]byte
- keys []common.Hash
- vals [][]byte
+ keys []common.Hash
+ vals [][]byte
)
// The values
for _, entry := range t.accountValues {
@@ -682,11 +673,7 @@ func testSyncBloatedProof(t *testing.T, scheme string) {
keys = append(keys[:1], keys[2:]...)
vals = append(vals[:1], vals[2:]...)
}
- for _, blob := range proof.List() {
- proofs = append(proofs, blob)
- }
-
- if err := t.remote.OnAccounts(t, requestId, keys, vals, proofs); err != nil {
+ if err := t.remote.OnAccounts(t, requestId, keys, vals, proof.List()); err != nil {
t.logger.Info("remote error on delivery (as expected)", "error", err)
t.term()
// This is actually correct, signal to exit the test successfully
@@ -924,7 +911,7 @@ func testMultiSyncManyUseless(t *testing.T, scheme string) {
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
}
-// TestMultiSyncManyUseless contains one good peer, and many which doesn't return anything valuable at all
+// TestMultiSyncManyUselessWithLowTimeout contains one good peer, and many which doesn't return anything valuable at all
func TestMultiSyncManyUselessWithLowTimeout(t *testing.T) {
t.Parallel()
@@ -1503,7 +1490,7 @@ func testSyncWithStorageAndNonProvingPeer(t *testing.T, scheme string) {
verifyTrie(scheme, syncer.db, sourceAccountTrie.Hash(), t)
}
-// TestSyncWithStorage tests basic sync using accounts + storage + code, against
+// TestSyncWithStorageMisbehavingProve tests basic sync using accounts + storage + code, against
// a peer who insists on delivering full storage sets _and_ proofs. This triggered
// an error, where the recipient erroneously clipped the boundary nodes, but
// did not mark the account for healing.
@@ -1632,10 +1619,10 @@ func getCodeByHash(hash common.Hash) []byte {
return nil
}
-// makeAccountTrieNoStorage spits out a trie, along with the leafs
+// makeAccountTrieNoStorage spits out a trie, along with the leaves
func makeAccountTrieNoStorage(n int, scheme string) (string, *trie.Trie, []*kv) {
var (
- db = trie.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
+ db = triedb.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
accTrie = trie.NewEmpty(db)
entries []*kv
)
@@ -1643,7 +1630,7 @@ func makeAccountTrieNoStorage(n int, scheme string) (string, *trie.Trie, []*kv)
for i := uint64(1); i <= uint64(n); i++ {
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i,
- Balance: big.NewInt(int64(i)),
+ Balance: uint256.NewInt(i),
Root: types.EmptyRootHash,
CodeHash: getCodeHash(i),
})
@@ -1656,7 +1643,7 @@ func makeAccountTrieNoStorage(n int, scheme string) (string, *trie.Trie, []*kv)
// Commit the state changes into db and re-create the trie
// for accessing later.
- root, nodes, _ := accTrie.Commit(false)
+ root, nodes := accTrie.Commit(false)
db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
accTrie, _ = trie.New(trie.StateTrieID(root), db)
@@ -1672,7 +1659,7 @@ func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) {
entries []*kv
boundaries []common.Hash
- db = trie.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
+ db = triedb.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
accTrie = trie.NewEmpty(db)
)
// Initialize boundaries
@@ -1697,7 +1684,7 @@ func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) {
for i := 0; i < len(boundaries); i++ {
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: uint64(0),
- Balance: big.NewInt(int64(i)),
+ Balance: uint256.NewInt(uint64(i)),
Root: types.EmptyRootHash,
CodeHash: getCodeHash(uint64(i)),
})
@@ -1709,7 +1696,7 @@ func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) {
for i := uint64(1); i <= uint64(n); i++ {
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i,
- Balance: big.NewInt(int64(i)),
+ Balance: uint256.NewInt(i),
Root: types.EmptyRootHash,
CodeHash: getCodeHash(i),
})
@@ -1721,7 +1708,7 @@ func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) {
// Commit the state changes into db and re-create the trie
// for accessing later.
- root, nodes, _ := accTrie.Commit(false)
+ root, nodes := accTrie.Commit(false)
db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
accTrie, _ = trie.New(trie.StateTrieID(root), db)
@@ -1733,7 +1720,7 @@ func makeBoundaryAccountTrie(scheme string, n int) (string, *trie.Trie, []*kv) {
// has a unique storage set.
func makeAccountTrieWithStorageWithUniqueStorage(scheme string, accounts, slots int, code bool) (string, *trie.Trie, []*kv, map[common.Hash]*trie.Trie, map[common.Hash][]*kv) {
var (
- db = trie.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
+ db = triedb.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
accTrie = trie.NewEmpty(db)
entries []*kv
storageRoots = make(map[common.Hash]common.Hash)
@@ -1755,7 +1742,7 @@ func makeAccountTrieWithStorageWithUniqueStorage(scheme string, accounts, slots
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i,
- Balance: big.NewInt(int64(i)),
+ Balance: uint256.NewInt(i),
Root: stRoot,
CodeHash: codehash,
})
@@ -1769,7 +1756,7 @@ func makeAccountTrieWithStorageWithUniqueStorage(scheme string, accounts, slots
slices.SortFunc(entries, (*kv).cmp)
// Commit account trie
- root, set, _ := accTrie.Commit(true)
+ root, set := accTrie.Commit(true)
nodes.Merge(set)
// Commit gathered dirty nodes into database
@@ -1788,10 +1775,10 @@ func makeAccountTrieWithStorageWithUniqueStorage(scheme string, accounts, slots
return db.Scheme(), accTrie, entries, storageTries, storageEntries
}
-// makeAccountTrieWithStorage spits out a trie, along with the leafs
+// makeAccountTrieWithStorage spits out a trie, along with the leaves
func makeAccountTrieWithStorage(scheme string, accounts, slots int, code, boundary bool, uneven bool) (*trie.Trie, []*kv, map[common.Hash]*trie.Trie, map[common.Hash][]*kv) {
var (
- db = trie.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
+ db = triedb.NewDatabase(rawdb.NewMemoryDatabase(), newDbConfig(scheme))
accTrie = trie.NewEmpty(db)
entries []*kv
storageRoots = make(map[common.Hash]common.Hash)
@@ -1826,7 +1813,7 @@ func makeAccountTrieWithStorage(scheme string, accounts, slots int, code, bounda
value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i,
- Balance: big.NewInt(int64(i)),
+ Balance: uint256.NewInt(i),
Root: stRoot,
CodeHash: codehash,
})
@@ -1841,7 +1828,7 @@ func makeAccountTrieWithStorage(scheme string, accounts, slots int, code, bounda
slices.SortFunc(entries, (*kv).cmp)
// Commit account trie
- root, set, _ := accTrie.Commit(true)
+ root, set := accTrie.Commit(true)
nodes.Merge(set)
// Commit gathered dirty nodes into database
@@ -1870,7 +1857,7 @@ func makeAccountTrieWithStorage(scheme string, accounts, slots int, code, bounda
// makeStorageTrieWithSeed fills a storage trie with n items, returning the
// not-yet-committed trie and the sorted entries. The seeds can be used to ensure
// that tries are unique.
-func makeStorageTrieWithSeed(owner common.Hash, n, seed uint64, db *trie.Database) (common.Hash, *trienode.NodeSet, []*kv) {
+func makeStorageTrieWithSeed(owner common.Hash, n, seed uint64, db *triedb.Database) (common.Hash, *trienode.NodeSet, []*kv) {
trie, _ := trie.New(trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash), db)
var entries []*kv
for i := uint64(1); i <= n; i++ {
@@ -1886,14 +1873,14 @@ func makeStorageTrieWithSeed(owner common.Hash, n, seed uint64, db *trie.Databas
entries = append(entries, elem)
}
slices.SortFunc(entries, (*kv).cmp)
- root, nodes, _ := trie.Commit(false)
+ root, nodes := trie.Commit(false)
return root, nodes, entries
}
// makeBoundaryStorageTrie constructs a storage trie. Instead of filling
// storage slots normally, this function will fill a few slots which have
// boundary hash.
-func makeBoundaryStorageTrie(owner common.Hash, n int, db *trie.Database) (common.Hash, *trienode.NodeSet, []*kv) {
+func makeBoundaryStorageTrie(owner common.Hash, n int, db *triedb.Database) (common.Hash, *trienode.NodeSet, []*kv) {
var (
entries []*kv
boundaries []common.Hash
@@ -1939,13 +1926,13 @@ func makeBoundaryStorageTrie(owner common.Hash, n int, db *trie.Database) (commo
entries = append(entries, elem)
}
slices.SortFunc(entries, (*kv).cmp)
- root, nodes, _ := trie.Commit(false)
+ root, nodes := trie.Commit(false)
return root, nodes, entries
}
// makeUnevenStorageTrie constructs a storage tries will states distributed in
// different range unevenly.
-func makeUnevenStorageTrie(owner common.Hash, slots int, db *trie.Database) (common.Hash, *trienode.NodeSet, []*kv) {
+func makeUnevenStorageTrie(owner common.Hash, slots int, db *triedb.Database) (common.Hash, *trienode.NodeSet, []*kv) {
var (
entries []*kv
tr, _ = trie.New(trie.StorageTrieID(types.EmptyRootHash, owner, types.EmptyRootHash), db)
@@ -1962,8 +1949,8 @@ func makeUnevenStorageTrie(owner common.Hash, slots int, db *trie.Database) (com
break
}
for j := 0; j < slots/3; j++ {
- key := append([]byte{byte(n)}, testutil.RandBytes(31)...)
- val, _ := rlp.EncodeToBytes(testutil.RandBytes(32))
+ key := append([]byte{byte(n)}, testrand.Bytes(31)...)
+ val, _ := rlp.EncodeToBytes(testrand.Bytes(32))
elem := &kv{key, val}
tr.MustUpdate(elem.k, elem.v)
@@ -1971,13 +1958,13 @@ func makeUnevenStorageTrie(owner common.Hash, slots int, db *trie.Database) (com
}
}
slices.SortFunc(entries, (*kv).cmp)
- root, nodes, _ := tr.Commit(false)
+ root, nodes := tr.Commit(false)
return root, nodes, entries
}
func verifyTrie(scheme string, db ethdb.KeyValueStore, root common.Hash, t *testing.T) {
t.Helper()
- triedb := trie.NewDatabase(rawdb.NewDatabase(db), newDbConfig(scheme))
+ triedb := triedb.NewDatabase(rawdb.NewDatabase(db), newDbConfig(scheme))
accTrie, err := trie.New(trie.StateTrieID(root), triedb)
if err != nil {
t.Fatal(err)
@@ -2027,7 +2014,9 @@ func verifyTrie(scheme string, db ethdb.KeyValueStore, root common.Hash, t *test
// TestSyncAccountPerformance tests how efficient the snap algo is at minimizing
// state healing
func TestSyncAccountPerformance(t *testing.T) {
- t.Parallel()
+ // These tests must not run in parallel: they modify the
+ // global var accountConcurrency
+ t.Skip("TODO: Does not return expected results, needs to be fixed")
testSyncAccountPerformance(t, rawdb.HashScheme)
testSyncAccountPerformance(t, rawdb.PathScheme)
@@ -2124,9 +2113,9 @@ func TestSlotEstimation(t *testing.T) {
}
}
-func newDbConfig(scheme string) *trie.Config {
+func newDbConfig(scheme string) *triedb.Config {
if scheme == rawdb.HashScheme {
- return &trie.Config{}
+ return &triedb.Config{}
}
- return &trie.Config{PathDB: pathdb.Defaults}
+ return &triedb.Config{PathDB: pathdb.Defaults}
}
diff --git a/eth/state_accessor.go b/eth/state_accessor.go
index b4180ef8c3..73c4332321 100644
--- a/eth/state_accessor.go
+++ b/eth/state_accessor.go
@@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
// noopReleaser is returned in case there is no operation expected
@@ -41,7 +42,7 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
var (
current *types.Block
database state.Database
- triedb *trie.Database
+ tdb *triedb.Database
report = true
origin = block.NumberU64()
)
@@ -67,14 +68,14 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
// the internal junks created by tracing will be persisted into the disk.
// TODO(rjl493456442), clean cache is disabled to prevent memory leak,
// please re-enable it for better performance.
- database = state.NewDatabaseWithConfig(eth.chainDb, trie.HashDefaults)
+ database = state.NewDatabaseWithConfig(eth.chainDb, triedb.HashDefaults)
if statedb, err = state.New(block.Root(), database, nil); err == nil {
log.Info("Found disk backend for state trie", "root", block.Root(), "number", block.Number())
return statedb, noopReleaser, nil
}
}
// The optional base statedb is given, mark the start point as parent block
- statedb, database, triedb, report = base, base.Database(), base.Database().TrieDB(), false
+ statedb, database, tdb, report = base, base.Database(), base.Database().TrieDB(), false
current = eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1)
if current == nil {
@@ -88,8 +89,8 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
// the internal junks created by tracing will be persisted into the disk.
// TODO(rjl493456442), clean cache is disabled to prevent memory leak,
// please re-enable it for better performance.
- triedb = trie.NewDatabase(eth.chainDb, trie.HashDefaults)
- database = state.NewDatabaseWithNodeDB(eth.chainDb, triedb)
+ tdb = triedb.NewDatabase(eth.chainDb, triedb.HashDefaults)
+ database = state.NewDatabaseWithNodeDB(eth.chainDb, tdb)
// If we didn't check the live database, do check state over ephemeral database,
// otherwise we would rewind past a persisted block (specific corner case is
@@ -174,19 +175,19 @@ func (eth *Ethereum) hashState(ctx context.Context, block *types.Block, reexec u
}
// Hold the state reference and also drop the parent state
// to prevent accumulating too many nodes in memory.
- triedb.Reference(root, common.Hash{})
+ tdb.Reference(root, common.Hash{})
if parent != (common.Hash{}) {
- triedb.Dereference(parent)
+ tdb.Dereference(parent)
}
parent = root
}
if report {
- _, nodes, imgs := triedb.Size() // all memory is contained within the nodes return in hashdb
+ _, nodes, imgs := tdb.Size() // all memory is contained within the nodes return in hashdb
log.Info("Historical state regenerated", "block", current.NumberU64(), "elapsed", time.Since(start), "nodes", nodes, "preimages", imgs)
}
- return statedb, func() { triedb.Dereference(block.Root()) }, nil
+ return statedb, func() { tdb.Dereference(block.Root()) }, nil
}
func (eth *Ethereum) pathState(block *types.Block) (*state.StateDB, func(), error) {
@@ -231,7 +232,7 @@ func (eth *Ethereum) stateAtBlock(ctx context.Context, block *types.Block, reexe
}
// stateAtTransaction returns the execution environment of a certain transaction.
-func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) {
+func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) {
// Short circuit if it's genesis block.
if block.NumberU64() == 0 {
return nil, vm.BlockContext{}, nil, nil, errors.New("no transaction in genesis")
@@ -247,7 +248,12 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
if err != nil {
return nil, vm.BlockContext{}, nil, nil, err
}
-
+ // Insert parent beacon block root in the state as per EIP-4788.
+ if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
+ context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil)
+ vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, eth.blockchain.Config(), vm.Config{})
+ core.ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
+ }
if txIndex == 0 && len(block.Transactions()) == 0 {
return nil, vm.BlockContext{}, statedb, release, nil
}
@@ -260,7 +266,7 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil)
if idx == txIndex {
- return msg, context, statedb, release, nil
+ return tx, context, statedb, release, nil
}
// Not yet the searched for transaction, execute on top of the current state
vmenv := vm.NewEVM(context, txContext, statedb, eth.blockchain.Config(), vm.Config{})
diff --git a/eth/sync.go b/eth/sync.go
index 44c0ff6d38..6475b80f9f 100644
--- a/eth/sync.go
+++ b/eth/sync.go
@@ -23,6 +23,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/log"
@@ -36,7 +37,7 @@ const (
// syncTransactions starts sending all currently pending transactions to the given peer.
func (h *handler) syncTransactions(p *eth.Peer) {
var hashes []common.Hash
- for _, batch := range h.txpool.Pending(false) {
+ for _, batch := range h.txpool.Pending(txpool.PendingFilter{OnlyPlainTxs: true}) {
for _, tx := range batch {
hashes = append(hashes, tx.Hash)
}
@@ -153,7 +154,7 @@ func (cs *chainSyncer) nextSyncOp() *chainSyncOp {
// An alternative would be to check the local chain for exceeding the TTD and
// avoid triggering a sync in that case, but that could also miss sibling or
// other family TTD block being accepted.
- if cs.handler.chain.Config().TerminalTotalDifficultyPassed || cs.handler.merger.TDDReached() {
+ if cs.handler.chain.Config().TerminalTotalDifficultyPassed {
return nil
}
// Ensure we're at minimum peer count.
diff --git a/eth/tracers/api.go b/eth/tracers/api.go
index 49246c61a2..375dacb07a 100644
--- a/eth/tracers/api.go
+++ b/eth/tracers/api.go
@@ -38,6 +38,7 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
@@ -47,6 +48,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
+ "github.com/holiman/uint256"
)
const (
@@ -93,13 +95,13 @@ type Backend interface {
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error)
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
- GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
+ GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error)
RPCGasCap() uint64
ChainConfig() *params.ChainConfig
Engine() consensus.Engine
ChainDb() ethdb.Database
StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, StateReleaseFunc, error)
- StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, StateReleaseFunc, error)
+ StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, StateReleaseFunc, error)
// Bor related APIs
GetBorBlockTransactionWithBlockHash(ctx context.Context, txHash common.Hash, blockHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
@@ -279,7 +281,7 @@ func (api *API) TraceChain(ctx context.Context, start, end rpc.BlockNumber, conf
sub := notifier.CreateSubscription()
// nolint : contextcheck
- resCh := api.traceChain(from, to, config, notifier.Closed())
+ resCh := api.traceChain(from, to, config, sub.Err())
go func() {
for result := range resCh {
@@ -296,7 +298,7 @@ func (api *API) TraceChain(ctx context.Context, start, end rpc.BlockNumber, conf
// transaction, dependent on the requested tracer.
// The tracing procedure should be aborted in case the closed signal is received.
// nolint:gocognit
-func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed <-chan interface{}) chan *blockTraceResult {
+func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed <-chan error) chan *blockTraceResult {
if config == nil {
config = &TraceConfig{
BorTraceEnabled: defaultBorTraceEnabled,
@@ -370,15 +372,13 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
}
}
- res, err = api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config)
+ res, err = api.traceTx(ctx, tx, msg, txctx, blockCtx, task.statedb, config)
if err != nil {
task.results[i] = &txTraceResult{TxHash: txHash, Error: err.Error()}
log.Warn("Tracing failed", "hash", txHash, "block", task.block.NumberU64(), "err", err)
break
}
- // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
- task.statedb.Finalise(api.backend.ChainConfig().IsEIP158(task.block.Number()))
task.results[i] = &txTraceResult{TxHash: txHash, Result: res}
}
// Tracing state is used up, queue it for de-referencing. Note the
@@ -475,6 +475,13 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
failed = err
break
}
+ // Insert block's parent beacon block root in the state
+ // as per EIP-4788.
+ if beaconRoot := next.BeaconRoot(); beaconRoot != nil {
+ context := core.NewEVMBlockContext(next.Header(), api.chainContext(ctx), nil)
+ vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, api.backend.ChainConfig(), vm.Config{})
+ core.ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
+ }
// Clean out any pending release functions of trace state. Note this
// step must be done after constructing tracing state, because the
// tracing state of block next depends on the parent state and construction
@@ -665,7 +672,6 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
}
defer release()
-
var (
roots []common.Hash
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
@@ -674,6 +680,11 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
)
+ if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
+ vmenv := vm.NewEVM(vmctx, vm.TxContext{}, statedb, chainConfig, vm.Config{})
+ core.ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
+ }
+
txs, stateSyncPresent, stateSyncHash := api.getAllBlockTransactions(ctx, block)
for i, tx := range txs {
if err := ctx.Err(); err != nil {
@@ -797,7 +808,6 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
var (
txs, stateSyncPresent, stateSyncHash = api.getAllBlockTransactions(ctx, block)
blockHash = block.Hash()
- blockCtx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
results = make([]*txTraceResult, len(txs))
pend sync.WaitGroup
@@ -836,16 +846,16 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
if stateSyncPresent && task.index == len(txs)-1 {
if *config.BorTraceEnabled {
// avoid data race
- newConfig := *config
- newConfig.BorTx = newBoolPtr(true)
- res, err = api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, &newConfig)
- } else {
- break
+ config.BorTx = newBoolPtr(true)
}
- } else {
- res, err = api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config)
}
+ // Reconstruct the block context for each transaction
+ // as the GetHash function of BlockContext is not safe for
+ // concurrent use.
+ // See: https://github.com/ethereum/go-ethereum/issues/29114
+ blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
+ res, err = api.traceTx(ctx, txs[task.index], msg, txctx, blockCtx, task.statedb, config)
if err != nil {
results[task.index] = &txTraceResult{TxHash: txHash, Error: err.Error()}
continue
@@ -872,6 +882,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
london = api.backend.ChainConfig().IsLondon(block.Number())
}
+ blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
txloop:
for i, tx := range txs {
if ioflag {
@@ -918,7 +929,7 @@ txloop:
statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
}
} else {
- coinbaseBalance := statedb.GetBalance(blockCtx.Coinbase)
+ coinbaseBalance := big.NewInt(statedb.GetBalance(blockCtx.Coinbase).ToBig().Int64())
// nolint : contextcheck
result, err := core.ApplyMessageNoFeeBurnOrTip(vmenv, *msg, new(core.GasPool).AddGas(msg.GasLimit), context.Background())
@@ -928,10 +939,10 @@ txloop:
}
if london {
- statedb.AddBalance(result.BurntContractAddress, result.FeeBurnt)
+ statedb.AddBalance(result.BurntContractAddress, uint256.NewInt(result.FeeBurnt.Uint64()), tracing.BalanceChangeTransfer)
}
- statedb.AddBalance(blockCtx.Coinbase, result.FeeTipped)
+ statedb.AddBalance(blockCtx.Coinbase, uint256.NewInt(result.FeeTipped.Uint64()), tracing.BalanceChangeTransfer)
output1 := new(big.Int).SetBytes(result.SenderInitBalance.Bytes())
output2 := new(big.Int).SetBytes(coinbaseBalance.Bytes())
@@ -1030,7 +1041,6 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
}
defer release()
-
// Retrieve the tracing configurations, or use default values
var (
logConfig logger.Config
@@ -1068,7 +1078,11 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
stateSyncPresent = false
}
- for i, tx := range txs {
+ if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
+ vmenv := vm.NewEVM(vmctx, vm.TxContext{}, statedb, chainConfig, vm.Config{})
+ core.ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
+ }
+ for i, tx := range block.Transactions() {
// Prepare the transaction for un-traced execution
var (
msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee())
@@ -1116,9 +1130,15 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
}
} else {
statedb.SetTxContext(tx.Hash(), i)
- // nolint : contextcheck
- _, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit), context.Background())
+ if vmConf.Tracer.OnTxStart != nil {
+ vmConf.Tracer.OnTxStart(vmenv.GetVMContext(), tx, msg.From)
+ }
+ // nolint : contextcheck
+ vmRet, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit), context.Background())
+ if vmConf.Tracer.OnTxEnd != nil {
+ vmConf.Tracer.OnTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas}, err)
+ }
if writer != nil {
writer.Flush()
}
@@ -1172,10 +1192,10 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
config.BorTraceEnabled = defaultBorTraceEnabled
}
- tx, blockHash, blockNumber, index, err := api.backend.GetTransaction(ctx, hash)
- if tx == nil {
+ found, _, blockHash, blockNumber, index, err := api.backend.GetTransaction(ctx, hash)
+ if !found {
// For BorTransaction, there will be no trace available
- tx, _, _, _ = rawdb.ReadBorTransaction(api.backend.ChainDb(), hash)
+ tx, _, _, _ := rawdb.ReadBorTransaction(api.backend.ChainDb(), hash)
if tx != nil {
return ðapi.ExecutionResult{
StructLogs: make([]ethapi.StructLogRes, 0),
@@ -1186,8 +1206,9 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
}
if err != nil {
- return nil, err
+ return nil, ethapi.NewTxIndexingError()
}
+
// It shouldn't happen in practice.
if blockNumber == 0 {
return nil, errors.New("genesis is not traceable")
@@ -1202,13 +1223,16 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
if err != nil {
return nil, err
}
-
- msg, vmctx, statedb, release, err := api.backend.StateAtTransaction(ctx, block, int(index), reexec)
+ tx, vmctx, statedb, release, err := api.backend.StateAtTransaction(ctx, block, int(index), reexec)
if err != nil {
return nil, err
}
defer release()
+ msg, err := core.TransactionToMessage(tx, types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()), block.BaseFee())
+ if err != nil {
+ return nil, err
+ }
txctx := &Context{
BlockHash: blockHash,
@@ -1216,8 +1240,7 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
TxIndex: int(index),
TxHash: hash,
}
-
- return api.traceTx(ctx, msg, txctx, vmctx, statedb, config)
+ return api.traceTx(ctx, tx, msg, txctx, vmctx, statedb, config)
}
// TraceCall lets you trace a given eth_call. It collects the structured logs
@@ -1284,23 +1307,24 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
config.BlockOverrides.Apply(&vmctx)
}
// Execute the trace
- msg, err := args.ToMessage(api.backend.RPCGasCap(), block.BaseFee())
- if err != nil {
+ if err := args.CallDefaults(api.backend.RPCGasCap(), vmctx.BaseFee, api.backend.ChainConfig().ChainID); err != nil {
return nil, err
}
-
- var traceConfig *TraceConfig
+ var (
+ msg = args.ToMessage(vmctx.BaseFee)
+ tx = args.ToTransaction()
+ traceConfig *TraceConfig
+ )
if config != nil {
traceConfig = &config.TraceConfig
}
-
- return api.traceTx(ctx, msg, new(Context), vmctx, statedb, traceConfig)
+ return api.traceTx(ctx, tx, msg, new(Context), vmctx, statedb, traceConfig)
}
// traceTx configures a new tracer according to the provided configuration, and
// executes the given message in the provided environment. The return value will
// be tracer dependent.
-func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) {
+func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) {
if config == nil {
config = &TraceConfig{
BorTraceEnabled: defaultBorTraceEnabled,
@@ -1313,25 +1337,32 @@ func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *Conte
}
var (
- tracer Tracer
- err error
- timeout = defaultTraceTimeout
- txContext = core.NewEVMTxContext(message)
+ tracer *Tracer
+ err error
+ timeout = defaultTraceTimeout
+ usedGas uint64
)
if config == nil {
config = &TraceConfig{}
}
// Default tracer is the struct logger
- tracer = logger.NewStructLogger(config.Config)
- if config.Tracer != nil {
+ if config.Tracer == nil {
+ logger := logger.NewStructLogger(config.Config)
+ tracer = &Tracer{
+ Hooks: logger.Hooks(),
+ GetResult: logger.GetResult,
+ Stop: logger.Stop,
+ }
+ } else {
tracer, err = DefaultDirectory.New(*config.Tracer, txctx, config.TracerConfig)
if err != nil {
return nil, err
}
}
-
- vmenv := vm.NewEVM(vmctx, txContext, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer, NoBaseFee: true})
+ // The actual TxContext will be created as part of ApplyTransactionWithEVM.
+ vmenv := vm.NewEVM(vmctx, vm.TxContext{GasPrice: message.GasPrice, BlobFeeCap: message.BlobGasFeeCap}, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true})
+ statedb.SetLogger(tracer.Hooks)
// Define a meaningful timeout of a single transaction trace
if config.Timeout != nil {
@@ -1368,8 +1399,10 @@ func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *Conte
return nil, fmt.Errorf("tracing failed: %w", err)
}
} else {
- // nolint : contextcheck
- if _, err = core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.GasLimit), context.Background()); err != nil {
+ // Call Prepare to clear out the statedb access list
+ statedb.SetTxContext(txctx.TxHash, txctx.TxIndex)
+ _, err = core.ApplyTransactionWithEVM(message, api.backend.ChainConfig(), new(core.GasPool).AddGas(message.GasLimit), statedb, vmctx.BlockNumber, txctx.BlockHash, tx, &usedGas, vmenv, context.Background())
+ if err != nil {
return nil, fmt.Errorf("tracing failed: %w", err)
}
}
diff --git a/eth/tracers/api_bor.go b/eth/tracers/api_bor.go
index 4600b96e5e..0b1408ecc3 100644
--- a/eth/tracers/api_bor.go
+++ b/eth/tracers/api_bor.go
@@ -86,7 +86,7 @@ func (api *API) traceBorBlock(ctx context.Context, block *types.Block, config *T
tracer := logger.NewStructLogger(config.Config)
// Run the transaction with tracing enabled.
- vmenv := vm.NewEVM(blockCtx, txContext, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer, NoBaseFee: true})
+ vmenv := vm.NewEVM(blockCtx, txContext, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks(), NoBaseFee: true})
// Call Prepare to clear out the statedb access list
// Not sure if we need to do this
diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go
index 00c2e58e20..4a3d23a4fa 100644
--- a/eth/tracers/api_test.go
+++ b/eth/tracers/api_test.go
@@ -24,6 +24,7 @@ import (
"fmt"
"math/big"
"reflect"
+ "slices"
"sync/atomic"
"testing"
"time"
@@ -31,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus"
+ "github.com/ethereum/go-ethereum/consensus/beacon"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
@@ -43,7 +45,6 @@ import (
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
- "golang.org/x/exp/slices"
)
var (
@@ -61,7 +62,7 @@ type testBackend struct {
relHook func() // Hook is invoked when the requested state is released
}
-// testBackend creates a new test backend. OBS: After test is done, teardown must be
+// newTestBackend creates a new test backend. OBS: After test is done, teardown must be
// invoked in order to release associated resources.
func newTestBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i int, b *core.BlockGen)) *testBackend {
backend := &testBackend{
@@ -120,9 +121,9 @@ func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber)
return b.chain.GetBlockByNumber(uint64(number)), nil
}
-func (b *testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
+func (b *testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
tx, hash, blockNumber, index := rawdb.ReadTransaction(b.chaindb, txHash)
- return tx, hash, blockNumber, index, nil
+ return tx != nil, tx, hash, blockNumber, index, nil
}
func (b *testBackend) RPCGasCap() uint64 {
@@ -169,7 +170,7 @@ func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reex
return statedb, release, nil
}
-func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) {
+func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) {
parent := b.chain.GetBlock(block.ParentHash(), block.NumberU64()-1)
if parent == nil {
return nil, vm.BlockContext{}, nil, nil, errBlockNotFound
@@ -191,7 +192,7 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block
blockContext := core.NewEVMBlockContext(block.Header(), b.chain, nil)
if idx == txIndex {
- return msg, blockContext, statedb, release, nil
+ return tx, blockContext, statedb, release, nil
}
vmenv := vm.NewEVM(blockContext, txContext, statedb, b.chainConfig, vm.Config{})
@@ -218,7 +219,7 @@ func TestTraceCall(t *testing.T) {
accounts := newAccounts(3)
genesis := &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
@@ -338,7 +339,7 @@ func TestTraceCall(t *testing.T) {
config: &TraceCallConfig{TxIndex: uintPtr(1)},
expectErr: fmt.Errorf("tracing failed: insufficient funds for gas * price + value: address %s have 1000000000000000000 want 1000000000000000100", accounts[2].addr),
},
- // After the target transaction, should be succeed
+ // After the target transaction, should be succeeded
{
blockNumber: rpc.BlockNumber(genBlocks - 1),
call: ethapi.TransactionArgs{
@@ -441,7 +442,7 @@ func TestTraceTransaction(t *testing.T) {
accounts := newAccounts(2)
genesis := &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
},
@@ -502,7 +503,7 @@ func TestTraceBlock(t *testing.T) {
accounts := newAccounts(3)
genesis := &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
@@ -603,7 +604,7 @@ func TestIOdump(t *testing.T) {
// Initialize test accounts
accounts := newAccounts(5)
- genesis := &core.Genesis{Alloc: core.GenesisAlloc{
+ genesis := &core.Genesis{Alloc: types.GenesisAlloc{
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
@@ -694,7 +695,7 @@ func TestTracingWithOverrides(t *testing.T) {
storageAccount := common.Address{0x13, 37}
genesis := &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
@@ -808,7 +809,6 @@ func TestTracingWithOverrides(t *testing.T) {
From: &accounts[0].addr,
// BLOCKNUMBER PUSH1 MSTORE
Input: newRPCBytes(common.Hex2Bytes("4360005260206000f3")),
- //&hexutil.Bytes{0x43}, // blocknumber
},
config: &TraceCallConfig{
BlockOverrides: ðapi.BlockOverrides{Number: (*hexutil.Big)(big.NewInt(0x1337))},
@@ -1077,7 +1077,7 @@ func TestTraceChain(t *testing.T) {
accounts := newAccounts(3)
genesis := &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
@@ -1154,3 +1154,90 @@ func TestTraceChain(t *testing.T) {
}
}
}
+
+// newTestMergedBackend creates a post-merge chain
+func newTestMergedBackend(t *testing.T, n int, gspec *core.Genesis, generator func(i int, b *core.BlockGen)) *testBackend {
+ backend := &testBackend{
+ chainConfig: gspec.Config,
+ engine: beacon.NewFaker(),
+ chaindb: rawdb.NewMemoryDatabase(),
+ }
+ // Generate blocks for testing
+ _, blocks, _ := core.GenerateChainWithGenesis(gspec, backend.engine, n, generator)
+
+ // Import the canonical chain
+ cacheConfig := &core.CacheConfig{
+ TrieCleanLimit: 256,
+ TrieDirtyLimit: 256,
+ TrieTimeLimit: 5 * time.Minute,
+ SnapshotLimit: 0,
+ TrieDirtyDisabled: true, // Archive mode
+ }
+ chain, err := core.NewBlockChain(backend.chaindb, cacheConfig, gspec, nil, backend.engine, vm.Config{}, nil, nil, nil)
+ if err != nil {
+ t.Fatalf("failed to create tester chain: %v", err)
+ }
+ if n, err := chain.InsertChain(blocks); err != nil {
+ t.Fatalf("block %d: failed to insert into chain: %v", n, err)
+ }
+ backend.chain = chain
+ return backend
+}
+
+func TestTraceBlockWithBasefee(t *testing.T) {
+ t.Parallel()
+ accounts := newAccounts(1)
+ target := common.HexToAddress("0x1111111111111111111111111111111111111111")
+ genesis := &core.Genesis{
+ Config: params.AllDevChainProtocolChanges,
+ Alloc: types.GenesisAlloc{
+ accounts[0].addr: {Balance: big.NewInt(1 * params.Ether)},
+ target: {Nonce: 1, Code: []byte{
+ byte(vm.BASEFEE), byte(vm.STOP),
+ }},
+ },
+ }
+ genBlocks := 1
+ signer := types.HomesteadSigner{}
+ var txHash common.Hash
+ var baseFee = new(big.Int)
+ backend := newTestMergedBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
+ tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
+ Nonce: uint64(i),
+ To: &target,
+ Value: big.NewInt(0),
+ Gas: 5 * params.TxGas,
+ GasPrice: b.BaseFee(),
+ Data: nil}),
+ signer, accounts[0].key)
+ b.AddTx(tx)
+ txHash = tx.Hash()
+ baseFee.Set(b.BaseFee())
+ })
+ defer backend.chain.Stop()
+ api := NewAPI(backend)
+
+ var testSuite = []struct {
+ blockNumber rpc.BlockNumber
+ config *TraceConfig
+ want string
+ }{
+ // Trace head block
+ {
+ blockNumber: rpc.BlockNumber(genBlocks),
+ want: fmt.Sprintf(`[{"txHash":"%#x","result":{"gas":21002,"failed":false,"returnValue":"","structLogs":[{"pc":0,"op":"BASEFEE","gas":84000,"gasCost":2,"depth":1,"stack":[]},{"pc":1,"op":"STOP","gas":83998,"gasCost":0,"depth":1,"stack":["%#x"]}]}}]`, txHash, baseFee),
+ },
+ }
+ for i, tc := range testSuite {
+ result, err := api.TraceBlockByNumber(context.Background(), tc.blockNumber, tc.config)
+ if err != nil {
+ t.Errorf("test %d, want no error, have %v", i, err)
+ continue
+ }
+ have, _ := json.Marshal(result)
+ want := tc.want
+ if string(have) != want {
+ t.Errorf("test %d, result mismatch\nhave: %v\nwant: %v\n", i, string(have), want)
+ }
+ }
+}
diff --git a/eth/tracers/tracers.go b/eth/tracers/dir.go
similarity index 70%
rename from eth/tracers/tracers.go
rename to eth/tracers/dir.go
index bf9b766ed5..650815350b 100644
--- a/eth/tracers/tracers.go
+++ b/eth/tracers/dir.go
@@ -14,17 +14,14 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-// Package tracers is a manager for transaction tracing engines.
package tracers
import (
"encoding/json"
- "errors"
- "fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/core/tracing"
)
// Context contains some contextual infos for a transaction execution that is not
@@ -36,17 +33,19 @@ type Context struct {
TxHash common.Hash // Hash of the transaction being traced (zero if dangling call)
}
-// Tracer interface extends vm.EVMLogger and additionally
-// allows collecting the tracing result.
-type Tracer interface {
- vm.EVMLogger
- GetResult() (json.RawMessage, error)
+// The set of methods that must be exposed by a tracer
+// for it to be available through the RPC interface.
+// This involves a method to retrieve results and one to
+// stop tracing.
+type Tracer struct {
+ *tracing.Hooks
+ GetResult func() (json.RawMessage, error)
// Stop terminates execution of the tracer at the first opportune moment.
- Stop(err error)
+ Stop func(err error)
}
-type ctorFn func(*Context, json.RawMessage) (Tracer, error)
-type jsCtorFn func(string, *Context, json.RawMessage) (Tracer, error)
+type ctorFn func(*Context, json.RawMessage) (*Tracer, error)
+type jsCtorFn func(string, *Context, json.RawMessage) (*Tracer, error)
type elem struct {
ctor ctorFn
@@ -79,7 +78,7 @@ func (d *directory) RegisterJSEval(f jsCtorFn) {
// New returns a new instance of a tracer, by iterating through the
// registered lookups. Name is either name of an existing tracer
// or an arbitrary JS code.
-func (d *directory) New(name string, ctx *Context, cfg json.RawMessage) (Tracer, error) {
+func (d *directory) New(name string, ctx *Context, cfg json.RawMessage) (*Tracer, error) {
if elem, ok := d.elems[name]; ok {
return elem.ctor(ctx, cfg)
}
@@ -97,33 +96,3 @@ func (d *directory) IsJS(name string) bool {
// JS eval will execute JS code
return true
}
-
-const (
- memoryPadLimit = 1024 * 1024
-)
-
-// GetMemoryCopyPadded returns offset + size as a new slice.
-// It zero-pads the slice if it extends beyond memory bounds.
-func GetMemoryCopyPadded(m *vm.Memory, offset, size int64) ([]byte, error) {
- if offset < 0 || size < 0 {
- return nil, errors.New("offset or size must not be negative")
- }
-
- if int(offset+size) < m.Len() { // slice fully inside memory
- return m.GetCopy(offset, size), nil
- }
-
- paddingNeeded := int(offset+size) - m.Len()
-
- if paddingNeeded > memoryPadLimit {
- return nil, fmt.Errorf("reached limit for padding memory slice: %d", paddingNeeded)
- }
-
- cpy := make([]byte, size)
-
- if overlap := int64(m.Len()) - offset; overlap > 0 {
- copy(cpy, m.GetPtr(offset, overlap))
- }
-
- return cpy, nil
-}
diff --git a/eth/tracers/internal/tracetest/README.md b/eth/tracers/internal/tracetest/README.md
new file mode 100644
index 0000000000..8c3d5d275f
--- /dev/null
+++ b/eth/tracers/internal/tracetest/README.md
@@ -0,0 +1,10 @@
+# Filling test cases
+
+To fill test cases for the built-in tracers, the `makeTest.js` script can be used. Given a transaction on a dev/test network, `makeTest.js` will fetch its prestate and then traces with the given configuration.
+In the Geth console do:
+
+```terminal
+let tx = '0x...'
+loadScript('makeTest.js')
+makeTest(tx, { tracer: 'callTracer' })
+```
\ No newline at end of file
diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go
index 0f77a39996..fa6e764c61 100644
--- a/eth/tracers/internal/tracetest/calltrace_test.go
+++ b/eth/tracers/internal/tracetest/calltrace_test.go
@@ -19,6 +19,7 @@ package tracetest
import (
"context"
"encoding/json"
+ "fmt"
"math/big"
"os"
"path/filepath"
@@ -27,25 +28,17 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/tests"
)
-type callContext struct {
- Number math.HexOrDecimal64 `json:"number"`
- Difficulty *math.HexOrDecimal256 `json:"difficulty"`
- Time math.HexOrDecimal64 `json:"timestamp"`
- GasLimit math.HexOrDecimal64 `json:"gasLimit"`
- Miner common.Address `json:"miner"`
-}
-
// callLog is the result of LOG opCode
type callLog struct {
Address common.Address `json:"address"`
@@ -128,42 +121,29 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
}
// Configure a blockchain with the given prestate
var (
- signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
- origin, _ = signer.Sender(tx)
- txContext = vm.TxContext{
- Origin: origin,
- GasPrice: tx.GasPrice(),
- }
- blockContext = vm.BlockContext{
- CanTransfer: core.CanTransfer,
- Transfer: core.Transfer,
- Coinbase: test.Context.Miner,
- BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
- Time: uint64(test.Context.Time),
- Difficulty: (*big.Int)(test.Context.Difficulty),
- GasLimit: uint64(test.Context.GasLimit),
- BaseFee: test.Genesis.BaseFee,
- }
- triedb, _, statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
+ signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
+ blockContext = test.Context.toBlockContext(test.Genesis)
+ state = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
)
- triedb.Close()
+ state.Close()
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig)
if err != nil {
t.Fatalf("failed to create call tracer: %v", err)
}
- evm := vm.NewEVM(blockContext, txContext, statedb, test.Genesis.Config, vm.Config{Tracer: tracer})
-
- msg, err := core.TransactionToMessage(tx, signer, nil)
+ state.StateDB.SetLogger(tracer.Hooks)
+ msg, err := core.TransactionToMessage(tx, signer, blockContext.BaseFee)
if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err)
}
-
+ evm := vm.NewEVM(blockContext, core.NewEVMTxContext(msg), state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
+ tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()), context.Background())
if err != nil {
t.Fatalf("failed to execute transaction: %v", err)
}
+ tracer.OnTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas}, nil)
// Retrieve the trace result and compare against the expected.
res, err := tracer.GetResult()
if err != nil {
@@ -240,10 +220,6 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
b.Fatalf("failed to parse testcase input: %v", err)
}
signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
- msg, err := core.TransactionToMessage(tx, signer, nil)
- if err != nil {
- b.Fatalf("failed to prepare transaction for tracing: %v", err)
- }
origin, _ := signer.Sender(tx)
txContext := vm.TxContext{
@@ -259,8 +235,12 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
Difficulty: (*big.Int)(test.Context.Difficulty),
GasLimit: uint64(test.Context.GasLimit),
}
- triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
- defer triedb.Close()
+ msg, err := core.TransactionToMessage(tx, signer, blockContext.BaseFee)
+ if err != nil {
+ b.Fatalf("failed to prepare transaction for tracing: %v", err)
+ }
+ state := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
+ defer state.Close()
b.ReportAllocs()
b.ResetTimer()
@@ -271,8 +251,10 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
b.Fatalf("failed to create call tracer: %v", err)
}
- evm := vm.NewEVM(blockContext, txContext, statedb, test.Genesis.Config, vm.Config{Tracer: tracer})
- snap := statedb.Snapshot()
+ evm := vm.NewEVM(blockContext, txContext, state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
+
+ snap := state.StateDB.Snapshot()
+
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if _, err = st.TransitionDb(context.Background()); err != nil {
@@ -283,7 +265,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
b.Fatal(err)
}
- statedb.RevertToSnapshot(snap)
+ state.StateDB.RevertToSnapshot(snap)
}
}
@@ -291,12 +273,12 @@ func TestInternals(t *testing.T) {
t.Parallel()
var (
- to = common.HexToAddress("0x00000000000000000000000000000000deadbeef")
- origin = common.HexToAddress("0x00000000000000000000000000000000feed")
- txContext = vm.TxContext{
- Origin: origin,
- GasPrice: big.NewInt(1),
- }
+ config = params.MainnetChainConfig
+ to = common.HexToAddress("0x00000000000000000000000000000000deadbeef")
+ originHex = "0x71562b71999873db5b286df957af199ec94617f7"
+ origin = common.HexToAddress(originHex)
+ signer = types.LatestSigner(config)
+ key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
blockContext = vm.BlockContext{
CanTransfer: core.CanTransfer,
Transfer: core.Transfer,
@@ -305,10 +287,10 @@ func TestInternals(t *testing.T) {
Time: 5,
Difficulty: big.NewInt(0x30000),
GasLimit: uint64(6000000),
+ BaseFee: new(big.Int),
}
)
-
- mkTracer := func(name string, cfg json.RawMessage) tracers.Tracer {
+ mkTracer := func(name string, cfg json.RawMessage) *tracers.Tracer {
tr, err := tracers.DefaultDirectory.New(name, nil, cfg)
if err != nil {
t.Fatalf("failed to create call tracer: %v", err)
@@ -320,7 +302,7 @@ func TestInternals(t *testing.T) {
for _, tc := range []struct {
name string
code []byte
- tracer tracers.Tracer
+ tracer *tracers.Tracer
want string
}{
{
@@ -334,13 +316,13 @@ func TestInternals(t *testing.T) {
byte(vm.CALL),
},
tracer: mkTracer("callTracer", nil),
- want: `{"from":"0x000000000000000000000000000000000000feed","gas":"0x13880","gasUsed":"0x54d8","to":"0x00000000000000000000000000000000deadbeef","input":"0x","calls":[{"from":"0x00000000000000000000000000000000deadbeef","gas":"0xe01a","gasUsed":"0x0","to":"0x00000000000000000000000000000000000000ff","input":"0x","value":"0x0","type":"CALL"}],"value":"0x0","type":"CALL"}`,
+ want: fmt.Sprintf(`{"from":"%s","gas":"0x13880","gasUsed":"0x54d8","to":"0x00000000000000000000000000000000deadbeef","input":"0x","calls":[{"from":"0x00000000000000000000000000000000deadbeef","gas":"0xe01a","gasUsed":"0x0","to":"0x00000000000000000000000000000000000000ff","input":"0x","value":"0x0","type":"CALL"}],"value":"0x0","type":"CALL"}`, originHex),
},
{
name: "Stack depletion in LOG0",
code: []byte{byte(vm.LOG3)},
tracer: mkTracer("callTracer", json.RawMessage(`{ "withLog": true }`)),
- want: `{"from":"0x000000000000000000000000000000000000feed","gas":"0x13880","gasUsed":"0x13880","to":"0x00000000000000000000000000000000deadbeef","input":"0x","error":"stack underflow (0 \u003c=\u003e 5)","value":"0x0","type":"CALL"}`,
+ want: fmt.Sprintf(`{"from":"%s","gas":"0x13880","gasUsed":"0x13880","to":"0x00000000000000000000000000000000deadbeef","input":"0x","error":"stack underflow (0 \u003c=\u003e 5)","value":"0x0","type":"CALL"}`, originHex),
},
{
name: "Mem expansion in LOG0",
@@ -353,7 +335,7 @@ func TestInternals(t *testing.T) {
byte(vm.LOG0),
},
tracer: mkTracer("callTracer", json.RawMessage(`{ "withLog": true }`)),
- want: `{"from":"0x000000000000000000000000000000000000feed","gas":"0x13880","gasUsed":"0x5b9e","to":"0x00000000000000000000000000000000deadbeef","input":"0x","logs":[{"address":"0x00000000000000000000000000000000deadbeef","topics":[],"data":"0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","position":"0x0"}],"value":"0x0","type":"CALL"}`,
+ want: fmt.Sprintf(`{"from":"%s","gas":"0x13880","gasUsed":"0x5b9e","to":"0x00000000000000000000000000000000deadbeef","input":"0x","logs":[{"address":"0x00000000000000000000000000000000deadbeef","topics":[],"data":"0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","position":"0x0"},{"address":"0x0000000000000000000000000000000000001010","topics":["0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63","0x0000000000000000000000000000000000000000000000000000000000001010","0x00000000000000000000000071562b71999873db5b286df957af199ec94617f7","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":"0x0000000000000000000000000000000000000000000000000000000000005b9e0000000000000000000000000000000000000000000000000001c6bf5263400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c6bf5262e4620000000000000000000000000000000000000000000000000000000000005b9e","position":"0x0"}],"value":"0x0","type":"CALL"}`, originHex),
},
{
// Leads to OOM on the prestate tracer
@@ -372,7 +354,7 @@ func TestInternals(t *testing.T) {
byte(vm.LOG0),
},
tracer: mkTracer("prestateTracer", nil),
- want: `{"0x0000000000000000000000000000000000000000":{"balance":"0x0"},"0x000000000000000000000000000000000000feed":{"balance":"0x1c6bf52647880"},"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600164ffffffffff60016000f560ff6000a0"}}`,
+ want: fmt.Sprintf(`{"0x0000000000000000000000000000000000000000":{"balance":"0x0"},"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600164ffffffffff60016000f560ff6000a0"},"%s":{"balance":"0x1c6bf52634000"}}`, originHex),
},
{
// CREATE2 which requires padding memory by prestate tracer
@@ -391,36 +373,45 @@ func TestInternals(t *testing.T) {
byte(vm.LOG0),
},
tracer: mkTracer("prestateTracer", nil),
- want: `{"0x0000000000000000000000000000000000000000":{"balance":"0x0"},"0x000000000000000000000000000000000000feed":{"balance":"0x1c6bf52647880"},"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600160ff60016000f560ff6000a0"},"0x91ff9a805d36f54e3e272e230f3e3f5c1b330804":{"balance":"0x0"}}`,
+ want: fmt.Sprintf(`{"0x0000000000000000000000000000000000000000":{"balance":"0x0"},"0x00000000000000000000000000000000deadbeef":{"balance":"0x0","code":"0x6001600052600160ff60016000f560ff6000a0"},"%s":{"balance":"0x1c6bf52634000"}}`, originHex),
},
} {
t.Run(tc.name, func(t *testing.T) {
- triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(),
- core.GenesisAlloc{
- to: core.GenesisAccount{
+ state := tests.MakePreState(rawdb.NewMemoryDatabase(),
+ types.GenesisAlloc{
+ to: types.Account{
Code: tc.code,
},
- origin: core.GenesisAccount{
+ origin: types.Account{
Balance: big.NewInt(500000000000000),
},
}, false, rawdb.HashScheme)
- defer triedb.Close()
-
- evm := vm.NewEVM(blockContext, txContext, statedb, params.MainnetChainConfig, vm.Config{Tracer: tc.tracer})
- msg := &core.Message{
- To: &to,
- From: origin,
- Value: big.NewInt(0),
- GasLimit: 80000,
- GasPrice: big.NewInt(0),
- GasFeeCap: big.NewInt(0),
- GasTipCap: big.NewInt(0),
- SkipAccountChecks: false,
+ defer state.Close()
+ state.StateDB.SetLogger(tc.tracer.Hooks)
+ tx, err := types.SignNewTx(key, signer, &types.LegacyTx{
+ To: &to,
+ Value: big.NewInt(0),
+ Gas: 80000,
+ GasPrice: big.NewInt(1),
+ })
+ if err != nil {
+ t.Fatalf("test %v: failed to sign transaction: %v", tc.name, err)
}
- st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(msg.GasLimit))
- if _, err := st.TransitionDb(context.Background()); err != nil {
+ txContext := vm.TxContext{
+ Origin: origin,
+ GasPrice: tx.GasPrice(),
+ }
+ evm := vm.NewEVM(blockContext, txContext, state.StateDB, config, vm.Config{Tracer: tc.tracer.Hooks})
+ msg, err := core.TransactionToMessage(tx, signer, big.NewInt(0))
+ if err != nil {
+ t.Fatalf("test %v: failed to create message: %v", tc.name, err)
+ }
+ tc.tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
+ vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()), context.Background())
+ if err != nil {
t.Fatalf("test %v: failed to execute transaction: %v", tc.name, err)
}
+ tc.tracer.OnTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas}, nil)
// Retrieve the trace result and compare against the expected
res, err := tc.tracer.GetResult()
if err != nil {
diff --git a/eth/tracers/internal/tracetest/flat_calltrace_test.go b/eth/tracers/internal/tracetest/flat_calltrace_test.go
index 57697fb2f4..958f685d25 100644
--- a/eth/tracers/internal/tracetest/flat_calltrace_test.go
+++ b/eth/tracers/internal/tracetest/flat_calltrace_test.go
@@ -17,11 +17,9 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/tests"
-
- // Force-load the native, to trigger registration
- "github.com/ethereum/go-ethereum/eth/tracers"
)
// flatCallTrace is the result of a callTracerParity run.
@@ -64,8 +62,8 @@ type flatCallTraceResult struct {
// flatCallTracerTest defines a single test to check the call tracer against.
type flatCallTracerTest struct {
- Genesis core.Genesis `json:"genesis"`
- Context callContext `json:"context"`
+ Genesis *core.Genesis `json:"genesis"`
+ Context *callContext `json:"context"`
Input string `json:"input"`
TracerConfig json.RawMessage `json:"tracerConfig"`
Result []flatCallTrace `json:"result"`
@@ -91,22 +89,9 @@ func flatCallTracerTestRunner(tb testing.TB, tracerName string, filename string,
return fmt.Errorf("failed to parse testcase input: %v", err)
}
signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
- origin, _ := signer.Sender(tx)
- txContext := vm.TxContext{
- Origin: origin,
- GasPrice: tx.GasPrice(),
- }
- blockContext := vm.BlockContext{
- CanTransfer: core.CanTransfer,
- Transfer: core.Transfer,
- Coinbase: test.Context.Miner,
- BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
- Time: uint64(test.Context.Time),
- Difficulty: (*big.Int)(test.Context.Difficulty),
- GasLimit: uint64(test.Context.GasLimit),
- }
- triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
- defer triedb.Close()
+ blockContext := test.Context.toBlockContext(test.Genesis)
+ state := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
+ defer state.Close()
// Create the tracer, the EVM environment and run it
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig)
@@ -114,18 +99,18 @@ func flatCallTracerTestRunner(tb testing.TB, tracerName string, filename string,
return fmt.Errorf("failed to create call tracer: %v", err)
}
- evm := vm.NewEVM(blockContext, txContext, statedb, test.Genesis.Config, vm.Config{Tracer: tracer})
-
- msg, err := core.TransactionToMessage(tx, signer, nil)
+ state.StateDB.SetLogger(tracer.Hooks)
+ msg, err := core.TransactionToMessage(tx, signer, blockContext.BaseFee)
if err != nil {
return fmt.Errorf("failed to prepare transaction for tracing: %v", err)
}
-
- st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
-
- if _, err = st.TransitionDb(context.Background()); err != nil {
+ evm := vm.NewEVM(blockContext, core.NewEVMTxContext(msg), state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
+ tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
+ vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()), context.Background())
+ if err != nil {
return fmt.Errorf("failed to execute transaction: %v", err)
}
+ tracer.OnTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas}, nil)
// Retrieve the trace result and compare against the etalon
res, err := tracer.GetResult()
@@ -140,7 +125,7 @@ func flatCallTracerTestRunner(tb testing.TB, tracerName string, filename string,
}
if !jsonEqualFlat(ret, test.Result) {
- tb.Logf("tracer name: %s", tracerName)
+ tb.Logf("test %s failed", filename)
// uncomment this for easier debugging
// have, _ := json.MarshalIndent(ret, "", " ")
@@ -192,7 +177,7 @@ func testFlatCallTracer(t *testing.T, tracerName string, dirPath string) {
}
}
-// jsonEqual is similar to reflect.DeepEqual, but does a 'bounce' via json prior to
+// jsonEqualFlat is similar to reflect.DeepEqual, but does a 'bounce' via json prior to
// comparison
func jsonEqualFlat(x, y interface{}) bool {
xTrace := new([]flatCallTrace)
diff --git a/eth/tracers/internal/tracetest/makeTest.js b/eth/tracers/internal/tracetest/makeTest.js
new file mode 100644
index 0000000000..3ad7a5df73
--- /dev/null
+++ b/eth/tracers/internal/tracetest/makeTest.js
@@ -0,0 +1,53 @@
+// makeTest generates a test for the configured tracer by running
+// a prestate reassembled and a call trace run, assembling all the
+// gathered information into a test case.
+var makeTest = function(tx, traceConfig) {
+ // Generate the genesis block from the block, transaction and prestate data
+ var block = eth.getBlock(eth.getTransaction(tx).blockHash);
+ var genesis = eth.getBlock(block.parentHash);
+
+ delete genesis.gasUsed;
+ delete genesis.logsBloom;
+ delete genesis.parentHash;
+ delete genesis.receiptsRoot;
+ delete genesis.sha3Uncles;
+ delete genesis.size;
+ delete genesis.transactions;
+ delete genesis.transactionsRoot;
+ delete genesis.uncles;
+
+ genesis.gasLimit = genesis.gasLimit.toString();
+ genesis.number = genesis.number.toString();
+ genesis.timestamp = genesis.timestamp.toString();
+
+ genesis.alloc = debug.traceTransaction(tx, {tracer: "prestateTracer"});
+ for (var key in genesis.alloc) {
+ var nonce = genesis.alloc[key].nonce;
+ if (nonce) {
+ genesis.alloc[key].nonce = nonce.toString();
+ }
+ }
+ genesis.config = admin.nodeInfo.protocols.eth.config;
+
+ // Generate the call trace and produce the test input
+ var result = debug.traceTransaction(tx, traceConfig);
+ delete result.time;
+
+ var context = {
+ number: block.number.toString(),
+ difficulty: block.difficulty,
+ timestamp: block.timestamp.toString(),
+ gasLimit: block.gasLimit.toString(),
+ miner: block.miner,
+ };
+ if (block.baseFeePerGas) {
+ context.baseFeePerGas = block.baseFeePerGas.toString();
+ }
+
+ console.log(JSON.stringify({
+ genesis: genesis,
+ context: context,
+ input: eth.getRawTransaction(tx),
+ result: result,
+ }, null, 2));
+}
diff --git a/eth/tracers/internal/tracetest/prestate_test.go b/eth/tracers/internal/tracetest/prestate_test.go
index a54b4a93e0..9c7359aaf9 100644
--- a/eth/tracers/internal/tracetest/prestate_test.go
+++ b/eth/tracers/internal/tracetest/prestate_test.go
@@ -102,42 +102,29 @@ func testPrestateDiffTracer(t *testing.T, tracerName string, dirPath string) {
}
// Configure a blockchain with the given prestate
var (
- signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
- origin, _ = signer.Sender(tx)
- txContext = vm.TxContext{
- Origin: origin,
- GasPrice: tx.GasPrice(),
- }
- blockContext = vm.BlockContext{
- CanTransfer: core.CanTransfer,
- Transfer: core.Transfer,
- Coinbase: test.Context.Miner,
- BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
- Time: uint64(test.Context.Time),
- Difficulty: (*big.Int)(test.Context.Difficulty),
- GasLimit: uint64(test.Context.GasLimit),
- BaseFee: test.Genesis.BaseFee,
- }
- triedb, _, statedb = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
+ signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
+ blockContext = test.Context.toBlockContext(test.Genesis)
+ state = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
)
- defer triedb.Close()
+ defer state.Close()
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig)
if err != nil {
t.Fatalf("failed to create call tracer: %v", err)
}
- evm := vm.NewEVM(blockContext, txContext, statedb, test.Genesis.Config, vm.Config{Tracer: tracer})
-
- msg, err := core.TransactionToMessage(tx, signer, nil)
+ state.StateDB.SetLogger(tracer.Hooks)
+ msg, err := core.TransactionToMessage(tx, signer, blockContext.BaseFee)
if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err)
}
-
- st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
- if _, err = st.TransitionDb(context.Background()); err != nil {
+ evm := vm.NewEVM(blockContext, core.NewEVMTxContext(msg), state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
+ tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
+ vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()), context.Background())
+ if err != nil {
t.Fatalf("failed to execute transaction: %v", err)
}
+ tracer.OnTxEnd(&types.Receipt{GasUsed: vmRet.UsedGas}, nil)
// Retrieve the trace result and compare against the expected
res, err := tracer.GetResult()
if err != nil {
diff --git a/eth/tracers/internal/tracetest/supply_test.go b/eth/tracers/internal/tracetest/supply_test.go
new file mode 100644
index 0000000000..65576333e6
--- /dev/null
+++ b/eth/tracers/internal/tracetest/supply_test.go
@@ -0,0 +1,614 @@
+// Copyright 2021 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 tracetest
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "math/big"
+ "os"
+ "path"
+ "path/filepath"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/consensus/beacon"
+ "github.com/ethereum/go-ethereum/consensus/ethash"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/eth/tracers"
+ "github.com/ethereum/go-ethereum/params"
+
+ // Force-load live packages, to trigger registration
+ _ "github.com/ethereum/go-ethereum/eth/tracers/live"
+)
+
+type supplyInfoIssuance struct {
+ GenesisAlloc *hexutil.Big `json:"genesisAlloc,omitempty"`
+ Reward *hexutil.Big `json:"reward,omitempty"`
+ Withdrawals *hexutil.Big `json:"withdrawals,omitempty"`
+}
+
+type supplyInfoBurn struct {
+ EIP1559 *hexutil.Big `json:"1559,omitempty"`
+ Blob *hexutil.Big `json:"blob,omitempty"`
+ Misc *hexutil.Big `json:"misc,omitempty"`
+}
+
+type supplyInfo struct {
+ Issuance *supplyInfoIssuance `json:"issuance,omitempty"`
+ Burn *supplyInfoBurn `json:"burn,omitempty"`
+
+ // Block info
+ Number uint64 `json:"blockNumber"`
+ Hash common.Hash `json:"hash"`
+ ParentHash common.Hash `json:"parentHash"`
+}
+
+func emptyBlockGenerationFunc(b *core.BlockGen) {}
+
+func TestSupplyOmittedFields(t *testing.T) {
+ var (
+ config = *params.TestChainConfig
+ gspec = &core.Genesis{
+ Config: &config,
+ }
+ )
+
+ gspec.Config.TerminalTotalDifficulty = big.NewInt(0)
+
+ out, _, err := testSupplyTracer(t, gspec, func(b *core.BlockGen) {
+ b.SetPoS()
+ })
+ if err != nil {
+ t.Fatalf("failed to test supply tracer: %v", err)
+ }
+
+ expected := supplyInfo{
+ Number: 0,
+ Hash: common.HexToHash("0xadeda0a83e337b6c073e3f0e9a17531a04009b397a9588c093b628f21b8bc5a3"),
+ ParentHash: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"),
+ }
+ actual := out[expected.Number]
+
+ compareAsJSON(t, expected, actual)
+}
+
+func TestSupplyGenesisAlloc(t *testing.T) {
+ var (
+ key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
+ addr1 = crypto.PubkeyToAddress(key1.PublicKey)
+ addr2 = crypto.PubkeyToAddress(key2.PublicKey)
+ eth1 = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether))
+
+ config = *params.AllEthashProtocolChanges
+
+ gspec = &core.Genesis{
+ Config: &config,
+ Alloc: types.GenesisAlloc{
+ addr1: {Balance: eth1},
+ addr2: {Balance: eth1},
+ },
+ }
+ )
+
+ expected := supplyInfo{
+ Issuance: &supplyInfoIssuance{
+ GenesisAlloc: (*hexutil.Big)(new(big.Int).Mul(common.Big2, big.NewInt(params.Ether))),
+ },
+ Number: 0,
+ Hash: common.HexToHash("0xbcc9466e9fc6a8b56f4b29ca353a421ff8b51a0c1a58ca4743b427605b08f2ca"),
+ ParentHash: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"),
+ }
+
+ out, _, err := testSupplyTracer(t, gspec, emptyBlockGenerationFunc)
+ if err != nil {
+ t.Fatalf("failed to test supply tracer: %v", err)
+ }
+
+ actual := out[expected.Number]
+
+ compareAsJSON(t, expected, actual)
+}
+
+func TestSupplyRewards(t *testing.T) {
+ var (
+ config = *params.AllEthashProtocolChanges
+
+ gspec = &core.Genesis{
+ Config: &config,
+ }
+ )
+
+ expected := supplyInfo{
+ Issuance: &supplyInfoIssuance{
+ Reward: (*hexutil.Big)(new(big.Int).Mul(common.Big2, big.NewInt(params.Ether))),
+ },
+ Number: 1,
+ Hash: common.HexToHash("0xcbb08370505be503dafedc4e96d139ea27aba3cbc580148568b8a307b3f51052"),
+ ParentHash: common.HexToHash("0xadeda0a83e337b6c073e3f0e9a17531a04009b397a9588c093b628f21b8bc5a3"),
+ }
+
+ out, _, err := testSupplyTracer(t, gspec, emptyBlockGenerationFunc)
+ if err != nil {
+ t.Fatalf("failed to test supply tracer: %v", err)
+ }
+
+ actual := out[expected.Number]
+
+ compareAsJSON(t, expected, actual)
+}
+
+func TestSupplyEip1559Burn(t *testing.T) {
+ var (
+ config = *params.AllEthashProtocolChanges
+
+ aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa")
+ // A sender who makes transactions, has some eth1
+ key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ addr1 = crypto.PubkeyToAddress(key1.PublicKey)
+ gwei5 = new(big.Int).Mul(big.NewInt(5), big.NewInt(params.GWei))
+ eth1 = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether))
+
+ gspec = &core.Genesis{
+ Config: &config,
+ BaseFee: big.NewInt(params.InitialBaseFee),
+ Alloc: types.GenesisAlloc{
+ addr1: {Balance: eth1},
+ },
+ }
+ )
+
+ signer := types.LatestSigner(gspec.Config)
+
+ eip1559BlockGenerationFunc := func(b *core.BlockGen) {
+ txdata := &types.DynamicFeeTx{
+ ChainID: gspec.Config.ChainID,
+ Nonce: 0,
+ To: &aa,
+ Gas: 21000,
+ GasFeeCap: gwei5,
+ GasTipCap: big.NewInt(2),
+ }
+ tx := types.NewTx(txdata)
+ tx, _ = types.SignTx(tx, signer, key1)
+
+ b.AddTx(tx)
+ }
+
+ out, chain, err := testSupplyTracer(t, gspec, eip1559BlockGenerationFunc)
+ if err != nil {
+ t.Fatalf("failed to test supply tracer: %v", err)
+ }
+ var (
+ head = chain.CurrentBlock()
+ reward = new(big.Int).Mul(common.Big2, big.NewInt(params.Ether))
+ burn = new(big.Int).Mul(big.NewInt(21000), head.BaseFee)
+ expected = supplyInfo{
+ Issuance: &supplyInfoIssuance{
+ Reward: (*hexutil.Big)(reward),
+ },
+ Burn: &supplyInfoBurn{
+ EIP1559: (*hexutil.Big)(burn),
+ },
+ Number: 1,
+ Hash: head.Hash(),
+ ParentHash: head.ParentHash,
+ }
+ )
+
+ actual := out[expected.Number]
+ compareAsJSON(t, expected, actual)
+}
+
+func TestSupplyWithdrawals(t *testing.T) {
+ t.Skip("not relevant to bor")
+ var (
+ config = *params.MergedTestChainConfig
+ gspec = &core.Genesis{
+ Config: &config,
+ }
+ )
+
+ withdrawalsBlockGenerationFunc := func(b *core.BlockGen) {
+ b.SetPoS()
+
+ b.AddWithdrawal(&types.Withdrawal{
+ Validator: 42,
+ Address: common.Address{0xee},
+ Amount: 1337,
+ })
+ }
+
+ out, chain, err := testSupplyTracer(t, gspec, withdrawalsBlockGenerationFunc)
+ if err != nil {
+ t.Fatalf("failed to test supply tracer: %v", err)
+ }
+
+ var (
+ head = chain.CurrentBlock()
+ expected = supplyInfo{
+ Issuance: &supplyInfoIssuance{
+ Withdrawals: (*hexutil.Big)(big.NewInt(1337000000000)),
+ },
+ Number: 1,
+ Hash: head.Hash(),
+ ParentHash: head.ParentHash,
+ }
+ actual = out[expected.Number]
+ )
+
+ compareAsJSON(t, expected, actual)
+}
+
+// Tests fund retrieval after contract's selfdestruct.
+// Contract A calls contract B which selfdestructs, but B receives eth1
+// after the selfdestruct opcode executes from Contract A.
+// Because Contract B is removed only at the end of the transaction
+// the ether sent in between is burnt before Cancun hard fork.
+func TestSupplySelfdestruct(t *testing.T) {
+ var (
+ config = *params.TestChainConfig
+
+ aa = common.HexToAddress("0x1111111111111111111111111111111111111111")
+ bb = common.HexToAddress("0x2222222222222222222222222222222222222222")
+ dad = common.HexToAddress("0x0000000000000000000000000000000000000dad")
+ key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ addr1 = crypto.PubkeyToAddress(key1.PublicKey)
+ gwei5 = new(big.Int).Mul(big.NewInt(5), big.NewInt(params.GWei))
+ eth1 = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether))
+
+ gspec = &core.Genesis{
+ Config: &config,
+ BaseFee: big.NewInt(params.InitialBaseFee),
+ Alloc: types.GenesisAlloc{
+ addr1: {Balance: eth1},
+ aa: {
+ Code: common.FromHex("0x61face60f01b6000527322222222222222222222222222222222222222226000806002600080855af160008103603457600080fd5b60008060008034865af1905060008103604c57600080fd5b5050"),
+ // Nonce: 0,
+ Balance: big.NewInt(0),
+ },
+ bb: {
+ Code: common.FromHex("0x6000357fface000000000000000000000000000000000000000000000000000000000000808203602f57610dad80ff5b5050"),
+ Nonce: 0,
+ Balance: eth1,
+ },
+ },
+ }
+ )
+
+ gspec.Config.TerminalTotalDifficulty = big.NewInt(0)
+
+ signer := types.LatestSigner(gspec.Config)
+
+ testBlockGenerationFunc := func(b *core.BlockGen) {
+ b.SetPoS()
+
+ txdata := &types.LegacyTx{
+ Nonce: 0,
+ To: &aa,
+ Value: gwei5,
+ Gas: 150000,
+ GasPrice: gwei5,
+ Data: []byte{},
+ }
+
+ tx := types.NewTx(txdata)
+ tx, _ = types.SignTx(tx, signer, key1)
+
+ b.AddTx(tx)
+ }
+
+ // 1. Test pre Cancun
+ preCancunOutput, preCancunChain, err := testSupplyTracer(t, gspec, testBlockGenerationFunc)
+ if err != nil {
+ t.Fatalf("Pre-cancun failed to test supply tracer: %v", err)
+ }
+
+ // Check balance at state:
+ // 1. 0x0000...000dad has 1 ether
+ // 2. A has 0 ether
+ // 3. B has 0 ether
+ statedb, _ := preCancunChain.State()
+ if got, exp := statedb.GetBalance(dad), eth1; got.CmpBig(exp) != 0 {
+ t.Fatalf("Pre-cancun address \"%v\" balance, got %v exp %v\n", dad, got, exp)
+ }
+ if got, exp := statedb.GetBalance(aa), big.NewInt(0); got.CmpBig(exp) != 0 {
+ t.Fatalf("Pre-cancun address \"%v\" balance, got %v exp %v\n", aa, got, exp)
+ }
+ if got, exp := statedb.GetBalance(bb), big.NewInt(0); got.CmpBig(exp) != 0 {
+ t.Fatalf("Pre-cancun address \"%v\" balance, got %v exp %v\n", bb, got, exp)
+ }
+
+ head := preCancunChain.CurrentBlock()
+ // Check live trace output
+ expected := supplyInfo{
+ Burn: &supplyInfoBurn{
+ EIP1559: (*hexutil.Big)(big.NewInt(55289500000000)),
+ Misc: (*hexutil.Big)(big.NewInt(5000000000)),
+ },
+ Number: 1,
+ Hash: head.Hash(),
+ ParentHash: head.ParentHash,
+ }
+
+ actual := preCancunOutput[expected.Number]
+
+ compareAsJSON(t, expected, actual)
+
+ // 2. Test post Cancun
+ cancunBlock := big.NewInt(0)
+ gspec.Config.ShanghaiBlock = cancunBlock
+ gspec.Config.CancunBlock = cancunBlock
+
+ postCancunOutput, postCancunChain, err := testSupplyTracer(t, gspec, testBlockGenerationFunc)
+ if err != nil {
+ t.Fatalf("Post-cancun failed to test supply tracer: %v", err)
+ }
+
+ // Check balance at state:
+ // 1. 0x0000...000dad has 1 ether
+ // 3. A has 0 ether
+ // 3. B has 5 gwei
+ statedb, _ = postCancunChain.State()
+ if got, exp := statedb.GetBalance(dad), eth1; got.CmpBig(exp) != 0 {
+ t.Fatalf("Post-shanghai address \"%v\" balance, got %v exp %v\n", dad, got, exp)
+ }
+ if got, exp := statedb.GetBalance(aa), big.NewInt(0); got.CmpBig(exp) != 0 {
+ t.Fatalf("Post-shanghai address \"%v\" balance, got %v exp %v\n", aa, got, exp)
+ }
+ if got, exp := statedb.GetBalance(bb), gwei5; got.CmpBig(exp) != 0 {
+ t.Fatalf("Post-shanghai address \"%v\" balance, got %v exp %v\n", bb, got, exp)
+ }
+
+ // Check live trace output
+ head = postCancunChain.CurrentBlock()
+ expected = supplyInfo{
+ Burn: &supplyInfoBurn{
+ EIP1559: (*hexutil.Big)(big.NewInt(55289500000000)),
+ },
+ Number: 1,
+ Hash: head.Hash(),
+ ParentHash: head.ParentHash,
+ }
+
+ actual = postCancunOutput[expected.Number]
+
+ compareAsJSON(t, expected, actual)
+}
+
+// Tests selfdestructing contract to send its balance to itself (burn).
+// It tests both cases of selfdestructing succeeding and being reverted.
+// - Contract A calls B and D.
+// - Contract B selfdestructs and sends the eth1 to itself (Burn amount to be counted).
+// - Contract C selfdestructs and sends the eth1 to itself.
+// - Contract D calls C and reverts (Burn amount of C
+// has to be reverted as well).
+func TestSupplySelfdestructItselfAndRevert(t *testing.T) {
+ var (
+ config = *params.TestChainConfig
+
+ aa = common.HexToAddress("0x1111111111111111111111111111111111111111")
+ bb = common.HexToAddress("0x2222222222222222222222222222222222222222")
+ cc = common.HexToAddress("0x3333333333333333333333333333333333333333")
+ dd = common.HexToAddress("0x4444444444444444444444444444444444444444")
+ key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ addr1 = crypto.PubkeyToAddress(key1.PublicKey)
+ gwei5 = new(big.Int).Mul(big.NewInt(5), big.NewInt(params.GWei))
+ eth1 = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether))
+ eth2 = new(big.Int).Mul(common.Big2, big.NewInt(params.Ether))
+ eth5 = new(big.Int).Mul(big.NewInt(5), big.NewInt(params.Ether))
+
+ gspec = &core.Genesis{
+ Config: &config,
+ // BaseFee: big.NewInt(params.InitialBaseFee),
+ Alloc: types.GenesisAlloc{
+ addr1: {Balance: eth1},
+ aa: {
+ // Contract code in YUL:
+ //
+ // object "ContractA" {
+ // code {
+ // let B := 0x2222222222222222222222222222222222222222
+ // let D := 0x4444444444444444444444444444444444444444
+
+ // // Call to Contract B
+ // let resB:= call(gas(), B, 0, 0x0, 0x0, 0, 0)
+
+ // // Call to Contract D
+ // let resD := call(gas(), D, 0, 0x0, 0x0, 0, 0)
+ // }
+ // }
+ Code: common.FromHex("0x73222222222222222222222222222222222222222273444444444444444444444444444444444444444460006000600060006000865af160006000600060006000865af150505050"),
+ Balance: common.Big0,
+ },
+ bb: {
+ // Contract code in YUL:
+ //
+ // object "ContractB" {
+ // code {
+ // let self := address()
+ // selfdestruct(self)
+ // }
+ // }
+ Code: common.FromHex("0x3080ff50"),
+ Balance: eth5,
+ },
+ cc: {
+ Code: common.FromHex("0x3080ff50"),
+ Balance: eth1,
+ },
+ dd: {
+ // Contract code in YUL:
+ //
+ // object "ContractD" {
+ // code {
+ // let C := 0x3333333333333333333333333333333333333333
+
+ // // Call to Contract C
+ // let resC := call(gas(), C, 0, 0x0, 0x0, 0, 0)
+
+ // // Revert
+ // revert(0, 0)
+ // }
+ // }
+ Code: common.FromHex("0x73333333333333333333333333333333333333333360006000600060006000855af160006000fd5050"),
+ Balance: eth2,
+ },
+ },
+ }
+ )
+
+ gspec.Config.TerminalTotalDifficulty = big.NewInt(0)
+
+ signer := types.LatestSigner(gspec.Config)
+
+ testBlockGenerationFunc := func(b *core.BlockGen) {
+ b.SetPoS()
+
+ txdata := &types.LegacyTx{
+ Nonce: 0,
+ To: &aa,
+ Value: common.Big0,
+ Gas: 150000,
+ GasPrice: gwei5,
+ Data: []byte{},
+ }
+
+ tx := types.NewTx(txdata)
+ tx, _ = types.SignTx(tx, signer, key1)
+
+ b.AddTx(tx)
+ }
+
+ output, chain, err := testSupplyTracer(t, gspec, testBlockGenerationFunc)
+ if err != nil {
+ t.Fatalf("failed to test supply tracer: %v", err)
+ }
+
+ // Check balance at state:
+ // 1. A has 0 ether
+ // 2. B has 0 ether, burned
+ // 3. C has 2 ether, selfdestructed but parent D reverted
+ // 4. D has 1 ether, reverted
+ statedb, _ := chain.State()
+ if got, exp := statedb.GetBalance(aa), common.Big0; got.CmpBig(exp) != 0 {
+ t.Fatalf("address \"%v\" balance, got %v exp %v\n", aa, got, exp)
+ }
+ if got, exp := statedb.GetBalance(bb), common.Big0; got.CmpBig(exp) != 0 {
+ t.Fatalf("address \"%v\" balance, got %v exp %v\n", bb, got, exp)
+ }
+ if got, exp := statedb.GetBalance(cc), eth1; got.CmpBig(exp) != 0 {
+ t.Fatalf("address \"%v\" balance, got %v exp %v\n", bb, got, exp)
+ }
+ if got, exp := statedb.GetBalance(dd), eth2; got.CmpBig(exp) != 0 {
+ t.Fatalf("address \"%v\" balance, got %v exp %v\n", bb, got, exp)
+ }
+
+ // Check live trace output
+ block := chain.GetBlockByNumber(1)
+
+ expected := supplyInfo{
+ Burn: &supplyInfoBurn{
+ EIP1559: (*hexutil.Big)(new(big.Int).Mul(block.BaseFee(), big.NewInt(int64(block.GasUsed())))),
+ Misc: (*hexutil.Big)(eth5), // 5ETH burned from contract B
+ },
+ Number: 1,
+ Hash: block.Hash(),
+ ParentHash: block.ParentHash(),
+ }
+
+ actual := output[expected.Number]
+
+ compareAsJSON(t, expected, actual)
+}
+
+func testSupplyTracer(t *testing.T, genesis *core.Genesis, gen func(*core.BlockGen)) ([]supplyInfo, *core.BlockChain, error) {
+ var (
+ engine = beacon.New(ethash.NewFaker())
+ )
+
+ traceOutputPath := filepath.ToSlash(t.TempDir())
+ traceOutputFilename := path.Join(traceOutputPath, "supply.jsonl")
+
+ // Load supply tracer
+ tracer, err := tracers.LiveDirectory.New("supply", json.RawMessage(fmt.Sprintf(`{"path":"%s"}`, traceOutputPath)))
+ if err != nil {
+ return nil, nil, fmt.Errorf("failed to create call tracer: %v", err)
+ }
+
+ chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), core.DefaultCacheConfigWithScheme(rawdb.PathScheme), genesis, nil, engine, vm.Config{Tracer: tracer}, nil, nil, nil)
+ if err != nil {
+ return nil, nil, fmt.Errorf("failed to create tester chain: %v", err)
+ }
+ defer chain.Stop()
+
+ _, blocks, _ := core.GenerateChainWithGenesis(genesis, engine, 1, func(i int, b *core.BlockGen) {
+ b.SetCoinbase(common.Address{1})
+ gen(b)
+ })
+
+ if n, err := chain.InsertChain(blocks); err != nil {
+ return nil, chain, fmt.Errorf("block %d: failed to insert into chain: %v", n, err)
+ }
+
+ // Check and compare the results
+ file, err := os.OpenFile(traceOutputFilename, os.O_RDONLY, 0666)
+ if err != nil {
+ return nil, chain, fmt.Errorf("failed to open output file: %v", err)
+ }
+ defer file.Close()
+
+ var output []supplyInfo
+ scanner := bufio.NewScanner(file)
+
+ for scanner.Scan() {
+ blockBytes := scanner.Bytes()
+
+ var info supplyInfo
+ if err := json.Unmarshal(blockBytes, &info); err != nil {
+ return nil, chain, fmt.Errorf("failed to unmarshal result: %v", err)
+ }
+
+ output = append(output, info)
+ }
+
+ return output, chain, nil
+}
+
+func compareAsJSON(t *testing.T, expected interface{}, actual interface{}) {
+ want, err := json.Marshal(expected)
+ if err != nil {
+ t.Fatalf("failed to marshal expected value to JSON: %v", err)
+ }
+
+ have, err := json.Marshal(actual)
+ if err != nil {
+ t.Fatalf("failed to marshal actual value to JSON: %v", err)
+ }
+
+ if !bytes.Equal(want, have) {
+ t.Fatalf("incorrect supply info: expected %s, got %s", string(want), string(have))
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer/inner_instafail.json b/eth/tracers/internal/tracetest/testdata/call_tracer/inner_instafail.json
index 9b45b52fe9..ed3688a942 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer/inner_instafail.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer/inner_instafail.json
@@ -56,6 +56,16 @@
"value": "0x0",
"gas": "0x1f97e",
"gasUsed": "0x72de",
- "input": "0x2e1a7d4d00000000000000000000000000000000000000000000000014d1120d7b160000"
+ "input": "0x2e1a7d4d00000000000000000000000000000000000000000000000014d1120d7b160000",
+ "calls": [{
+ "from":"0x6c06b16512b332e6cd8293a2974872674716ce18",
+ "gas":"0x8fc",
+ "gasUsed":"0x0",
+ "to":"0x66fdfd05e46126a07465ad24e40cc0597bc1ef31",
+ "input":"0x",
+ "error":"insufficient balance for transfer",
+ "value":"0x14d1120d7b160000",
+ "type":"CALL"
+ }]
}
}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer/inner_revert_reason.json b/eth/tracers/internal/tracetest/testdata/call_tracer/inner_revert_reason.json
index 9d8356e4dd..3780bffeb2 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer/inner_revert_reason.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer/inner_revert_reason.json
@@ -52,7 +52,8 @@
"difficulty": "2",
"timestamp": "1665537018",
"gasLimit": "11511229",
- "miner": "0x0000000000000000000000000000000000000000"
+ "miner": "0x0000000000000000000000000000000000000000",
+ "baseFeePerGas": "875000000"
},
"input": "0x02f9029d82053980849502f90085010c388d00832dc6c08080b90241608060405234801561001057600080fd5b50600060405161001f906100a2565b604051809103906000f08015801561003b573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663c04062266040518163ffffffff1660e01b815260040160006040518083038186803b15801561008457600080fd5b505afa158015610098573d6000803e3d6000fd5b50505050506100af565b610145806100fc83390190565b603f806100bd6000396000f3fe6080604052600080fdfea264697066735822122077f7dbd3450d6e817079cf3fe27107de5768bb3163a402b94e2206b468eb025664736f6c63430008070033608060405234801561001057600080fd5b50610125806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063c040622614602d575b600080fd5b60336035565b005b60036002116076576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401606d906097565b60405180910390fd5b565b6000608360128360b5565b9150608c8260c6565b602082019050919050565b6000602082019050818103600083015260ae816078565b9050919050565b600082825260208201905092915050565b7f546869732063616c6c6564206661696c6564000000000000000000000000000060008201525056fea264697066735822122033f8d92e29d467e5ea08d0024eab0b36b86b8cdb3542c6e89dbaabeb8ffaa42064736f6c63430008070033c001a07566181071cabaf58b70fc41557eb813bfc7a24f5c58554e7fed0bf7c031f169a0420af50b5fe791a4d839e181a676db5250b415dfb35cb85d544db7a1475ae2cc",
"result": {
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json
index c796804a4b..a2386ea9c7 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_fail_hide.json
@@ -63,12 +63,27 @@
"address": "0x5f8a7e007172ba80afbff1b15f800eb0b260f224"
},
"traceAddress": [],
- "subtraces": 0,
+ "subtraces": 1,
"transactionPosition": 74,
"transactionHash": "0x5ef60b27ac971c22a7d484e546e50093ca62300c8986d165154e47773764b6a4",
"blockNumber": 1555279,
"blockHash": "0xd6c98d1b87dfa92a210d99bad2873adaf0c9e51fe43addc63fd9cca03a5c6f46",
"time": "209.346µs"
+ },
+ {
+ "action": {
+ "balance": "0x0",
+ "callType": "callcode",
+ "from": "0x5f8a7e007172ba80afbff1b15f800eb0b260f224",
+ "gas": "0xaf64",
+ "to": "0x0000000000000000000000000000000000000004",
+ "value": "0x13"
+ },
+ "error": "insufficient balance for transfer",
+ "result": {},
+ "subtraces": 0,
+ "traceAddress": [0],
+ "type": "call"
}
]
}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json
index 3c1e370f91..5e27261554 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/callcode_precompiled_throw.json
@@ -57,7 +57,7 @@
"gas": "0x1a034",
"init": "0x36600060003760406103e8366000600060095af26001556103e8516002556104085160035500"
},
- "error": "out of gas",
+ "error": "out of gas: not enough gas for reentrancy sentry",
"traceAddress": [],
"subtraces": 1,
"transactionPosition": 117,
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_instafail.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_instafail.json
index 4de08f2cca..611e50e2c0 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_instafail.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/inner_instafail.json
@@ -64,9 +64,23 @@
"gasUsed": "0x72de",
"output": "0x"
},
- "subtraces": 0,
+ "subtraces": 1,
"traceAddress": [],
"type": "call"
+ },
+ {
+ "action": {
+ "callType": "call",
+ "from": "0x6c06b16512b332e6cd8293a2974872674716ce18",
+ "gas": "0x8fc",
+ "to": "0x66fdfd05e46126a07465ad24e40cc0597bc1ef31",
+ "value": "0x14d1120d7b160000"
+ },
+ "error": "insufficient balance for transfer",
+ "result": {},
+ "subtraces": 0,
+ "traceAddress": [0],
+ "type": "call"
}
]
}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json
index 132b84df36..a00ea7a93b 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_action_gas.json
@@ -57,7 +57,7 @@
"gas": "0x19ee4",
"init": "0x5a600055600060006000f0505a60015500"
},
- "error": "out of gas",
+ "error": "out of gas: not enough gas for reentrancy sentry",
"traceAddress": [],
"subtraces": 1,
"transactionPosition": 63,
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_inerror.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_inerror.json
index 28e96684b2..f3a7d9a946 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_inerror.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/nested_create_inerror.json
@@ -70,12 +70,25 @@
"output": "0x"
},
"traceAddress": [],
- "subtraces": 0,
+ "subtraces": 1,
"transactionPosition": 26,
"transactionHash": "0xcb1090fa85d2a3da8326b75333e92b3dca89963c895d9c981bfdaa64643135e4",
"blockNumber": 839247,
"blockHash": "0xce7ff7d84ca97f0f89d6065e2c12409a795c9f607cdb14aef0713cad5d7e311c",
"time": "182.267µs"
+ },
+ {
+ "action": {
+ "from": "0x76554b33410b6d90b7dc889bfed0451ad195f27e",
+ "gas": "0x25a18",
+ "init": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "value": "0xa"
+ },
+ "error": "insufficient balance for transfer",
+ "result": {},
+ "subtraces": 0,
+ "traceAddress": [0],
+ "type": "create"
}
]
}
\ No newline at end of file
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/selfdestruct.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/selfdestruct.json
index 74fd87cc6c..3c5d6d9f2b 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/selfdestruct.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/selfdestruct.json
@@ -63,13 +63,26 @@
"address": "0x1d99a1a3efa9181f540f9e24fa6e4e08eb7844ca"
},
"traceAddress": [],
- "subtraces": 1,
+ "subtraces": 2,
"transactionPosition": 14,
"transactionHash": "0xdd76f02407e2f8329303ba688e111cae4f7008ad0d14d6e42c5698424ea36d79",
"blockNumber": 1555146,
"blockHash": "0xafb4f1dd27b9054c805acb81a88ed04384788cb31d84164c21874935c81e5c7e",
"time": "187.145µs"
},
+ {
+ "action": {
+ "from": "0x1d99a1a3efa9181f540f9e24fa6e4e08eb7844ca",
+ "gas": "0x50ac",
+ "init": "0x5a",
+ "value": "0x1"
+ },
+ "error": "insufficient balance for transfer",
+ "result": {},
+ "subtraces": 0,
+ "traceAddress": [0],
+ "type": "create"
+ },
{
"type": "suicide",
"action": {
@@ -79,7 +92,7 @@
},
"result": null,
"traceAddress": [
- 0
+ 1
],
"subtraces": 0,
"transactionPosition": 14,
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json
index 96060d5545..6911ed4b32 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_flat/skip_no_balance_error.json
@@ -59,12 +59,25 @@
},
"error": "out of gas",
"traceAddress": [],
- "subtraces": 0,
+ "subtraces": 1,
"transactionPosition": 16,
"transactionHash": "0x384487e5ae8d2997aece8e28403d393cb9752425e6de358891bed981c5af1c05",
"blockNumber": 1555285,
"blockHash": "0x93231d8e9662adb4c5c703583a92c7b3112cd5448f43ab4fa1f0f00a0183ed3f",
"time": "665.278µs"
+ },
+ {
+ "action": {
+ "from": "0xf84bf5189ccd19f5897739756d214fa0dc099e0d",
+ "gas": "0x1d5c",
+ "init": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "value": "0xc350"
+ },
+ "error": "insufficient balance for transfer",
+ "result": {},
+ "subtraces": 0,
+ "traceAddress": [0],
+ "type": "create"
}
]
}
\ No newline at end of file
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/calldata.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/calldata.json
index dbece7229d..aaba0e413e 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/calldata.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/calldata.json
@@ -111,6 +111,30 @@
"type": "CALLCODE"
}
],
+ "logs": [
+ {
+ "address": "0x0000000000000000000000000000000000001010",
+ "topics": [
+ "0xe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c4",
+ "0x0000000000000000000000000000000000000000000000000000000000001010",
+ "0x0000000000000000000000004f5777744b500616697cb655dcb02ee6cd51deb5",
+ "0x000000000000000000000000200edd17f30485a8735878661960cd7a9a95733f"
+ ],
+ "data": "0x0000000000000000000000000000000000000000000000008ac7230489e80000000000000000000000000000000000000000000000000000b0767db57cd070aa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025af5ab0f2e870aa0000000000000000000000000000000000000000000000008ac7230489e80000",
+ "position": "0x0"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000001010",
+ "topics": [
+ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63",
+ "0x0000000000000000000000000000000000000000000000000000000000001010",
+ "0x0000000000000000000000004f5777744b500616697cb655dcb02ee6cd51deb5",
+ "0x000000000000000000000000f8b483dba2c3b7176a3da549ad41a48bb3121069"
+ ],
+ "data": "0x00000000000000000000000000000000000000000000000000119b54eb98e126000000000000000000000000000000000000000000000000b0983f1b83eec29000000000000000000000000000000000000000000000016969a0ba2c2d384d07000000000000000000000000000000000000000000000000b086a3c69855e16a00000000000000000000000000000000000000000000016969b2558118d12e2d",
+ "position": "0x1"
+ }
+ ],
"value": "0x8ac7230489e80000",
"type": "CALL"
}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/delegatecall.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/delegatecall.json
index 2b03dbb8dd..c0ff5c417a 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/delegatecall.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/delegatecall.json
@@ -407,6 +407,19 @@
"type": "CALL"
}
],
+ "logs": [
+ {
+ "address": "0x0000000000000000000000000000000000001010",
+ "topics": [
+ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63",
+ "0x0000000000000000000000000000000000000000000000000000000000001010",
+ "0x0000000000000000000000003de712784baf97260455ae25fb74f574ec9c1add",
+ "0x00000000000000000000000061c808d82a3ac53231750dadc13c777b59310bd9"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000b9e774e8d580000000000000000000000000000000000000000000000000023c8352f33854625000000000000000000000000000000000000000000000090a7af5d475598456100000000000000000000000000000000000000000000000023bc96b7e4f7ee25000000000000000000000000000000000000000000000090a7bafbbea4259d61",
+ "position": "0x8"
+ }
+ ],
"value": "0x0",
"type": "CALL"
}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/frontier_create_outofstorage.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/frontier_create_outofstorage.json
new file mode 100644
index 0000000000..7e34a69574
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/frontier_create_outofstorage.json
@@ -0,0 +1,205 @@
+{
+ "genesis": {
+ "difficulty": "7797655526461",
+ "extraData": "0xd583010203844765746885676f312e35856c696e7578",
+ "gasLimit": "3141592",
+ "hash": "0x4ad333086cb86a6d261329504c9e1ca4d571212f56d6635dd213b700e1e85a6f",
+ "miner": "0x2a65aca4d5fc5b5c859090a6c34d164135398226",
+ "mixHash": "0xdaca4c8bd9a6e6707059736633543ebf50f97c07700a9ed55859b97275c19ea5",
+ "nonce": "0x894c15d74e8ae8bd",
+ "number": "469666",
+ "stateRoot": "0xf9c50965ffae3f99310483a7836c545a025cc680303adaf3671dbeef99edf03a",
+ "timestamp": "1446318401",
+ "totalDifficulty": "2462705215747880313",
+ "alloc": {
+ "0x0000000000000000000000000000000000000004": {
+ "balance": "0x0"
+ },
+ "0x0047a8033cc6d6ca2ed5044674fd421f44884de8": {
+ "balance": "0x44f5ced08fe37cf7",
+ "nonce": "872"
+ },
+ "0x1d11e5eae3112dbd44f99266872ff1d07c77dce8": {
+ "balance": "0x0",
+ "code": "0x60606040526000357c01000000000000000000000000000000000000000000000000000000009004806338cc48311461004f578063767800de14610088578063d1d80fdf146100c15761004d565b005b61005c60048050506100ff565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61009560048050506100d9565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100d7600480803590602001909190505061012e565b005b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905061012b565b90565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561018a57610002565b80600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b5056",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000f631e3b3aafa084bc51c714825aacf505d2059be"
+ }
+ },
+ "0xe48430c4e88a929bba0ee3dce284866a9937b609": {
+ "balance": "0x26758774d51d8677a",
+ "nonce": "261"
+ },
+ "0xf631e3b3aafa084bc51c714825aacf505d2059be": {
+ "balance": "0x0",
+ "code": "0x606060405236156100da5760e060020a600035046323dc42e781146100ff5780632ef3accc146101a5578063385928321461021d57806345362978146102b65780634c7737951461034a578063524f38891461035c5780635c242c59146103ad578063772286591461044a5780637e1c42051461052457806381ade30714610601578063a2ec191a14610696578063adf59f991461071b578063ae815843146107b5578063bf1fe4201461084f578063de4b326214610890578063e8025731146108d4578063e839e65e14610970578063fbf8041814610a44575b610b20604051600160a060020a03331690600090349082818181858883f15050505050565b60408051602060046024803582810135601f8101859004850286018501909652858552610b229583359593946044949392909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a01909352828252969897606497919650602491909101945090925082915084018382808284375094965050505050505060008260006000610c0b83335b60006113fd8362030d40846101f5565b6040805160206004803580820135601f8101849004840285018401909552848452610b22949193602493909291840191908190840183828082843750949650509335935050505060006113fd8383335b600160a060020a03811660009081526003602052604081205460ff168114156114b557610b57565b60408051602060046024803582810135601f8101859004850286018501909652858552610b229583359593946044949392909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a01909352828252969897606497919650602491909101945090925082915084018382808284375094965050933593505050506000610d5885858585610841565b6040805160206004803580820135601f8101849004840285018401909552848452610b2294919360249390929184019190819084018382808284375050604080516020601f8935808c01359182018390048302840183019094528083529799986044989297509290920194509250829150840183828082843750949650505050505050600082600060006114068333610195565b610b34600154600160a060020a031681565b6040805160206004803580820135601f8101849004840285018401909552848452610b2294919360249390929184019190819084018382808284375094965050505050505060006114008233610195565b60408051602060046024803582810135601f8101859004850286018501909652858552610b229583359593946044949392909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a01909352828252969897606497919650602491909101945090925082915084018382808284375094965050933593505050505b60008360006000610d5f8333610195565b60408051602060046024803582810135601f8101859004850286018501909652858552610b229583359593946044949392909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750506040805160209735808a0135601f81018a90048a0283018a01909352828252969897608497919650602491909101945090925082915084018382808284375094965050505050505060008360006000610cb88333610195565b60408051602060046024803582810135601f8101859004850286018501909652858552610b229583359593946044949392909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750506040805160209735808a0135601f81018a90048a0283018a01909352828252969897608497919650602491909101945090925082915084018382808284375094965050933593505050505b60008460006000610f288333610195565b6040805160206004803580820135601f8101849004840285018401909552848452610b2294919360249390929184019190819084018382808284375050604080516020601f8935808c0135918201839004830284018301909452808352979998604498929750929092019450925082915084018382808284375094965050505050505060006113fd6000848462030d40610439565b6040805160206004803580820135601f8101849004840285018401909552848452610b209491936024939092918401919081908401838280828437509496505093359350505050600254600090600160a060020a039081163391909116148015906107115750600154600160a060020a039081163390911614155b156111fd57610002565b60408051602060046024803582810135601f8101859004850286018501909652858552610b229583359593946044949392909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a0190935282825296989760649791965060249190910194509092508291508401838280828437509496505050505050506000610c0484848462030d40610439565b60408051602060046024803582810135601f8101859004850286018501909652858552610b229583359593946044949392909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a01909352828252969897606497919650602491909101945090925082915084018382808284375094965050933593505050505b6000610d5885858585610439565b610b20600435600254600160a060020a039081163391909116148015906108865750600154600160a060020a039081163390911614155b156114b057610002565b610b20600435600254600090600160a060020a039081163391909116148015906108ca5750600154600160a060020a039081163390911614155b1561134d57610002565b60408051602060046024803582810135601f8101859004850286018501909652858552610b229583359593946044949392909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a0190935282825296989760649791965060249190910194509092508291508401838280828437509496505093359350505050600083600060006111618333610195565b6040805160206004803580820135601f8101849004840285018401909552848452610b2294919360249390929184019190819084018382808284375050604080516020601f8935808c01359182018390048302840183019094528083529799986044989297509290920194509250829150840183828082843750506040805160209735808a0135601f81018a90048a0283018a01909352828252969897606497919650602491909101945090925082915084018382808284375094965050505050505060008360006000610b5e8333610195565b60408051602060046024803582810135601f8101859004850286018501909652858552610b229583359593946044949392909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750506040805160209735808a0135601f81018a90048a0283018a0190935282825296989760849791965060249190910194509092508291508401838280828437509496505093359350505050600084600060006112a68333610195565b005b60408051918252519081900360200190f35b60408051600160a060020a03929092168252519081900360200190f35b93505050505b9392505050565b91508160001415610b8d57600160a060020a0333166000908152600360205260409020805460ff191660011790555b34829010610bff5760405173f65b3b60010d57d0bb8478aa6ced15fe720621b490600090849082818181858883f15050503484900392508211159050610bee57604051600160a060020a03331690600090839082818181858883f150505050505b610b51600088888862030d406105f0565b610002565b9050610b57565b91508160001415610c3a57600160a060020a0333166000908152600360205260409020805460ff191660011790555b34829010610bff5760405173f65b3b60010d57d0bb8478aa6ced15fe720621b490600090849082818181858883f15050503484900392508211159050610c9b57604051600160a060020a03331690600090839082818181858883f150505050505b610b5187878762030d40610439565b93505050505b949350505050565b91508160001415610ce757600160a060020a0333166000908152600360205260409020805460ff191660011790555b34829010610bff5760405173f65b3b60010d57d0bb8478aa6ced15fe720621b490600090849082818181858883f15050503484900392508211159050610d4857604051600160a060020a03331690600090839082818181858883f150505050505b610caa8888888862030d406105f0565b9050610cb0565b91508160001415610d8e57600160a060020a0333166000908152600360205260409020805460ff191660011790555b34829010610bff5760405173f65b3b60010d57d0bb8478aa6ced15fe720621b490600090849082818181858883f15050503484900392508211159050610def57604051600160a060020a03331690600090839082818181858883f150505050505b604080516000805442810183528351928390036020908101842060019290920183558184528381018d9052608084018a905260a09484018581528c51958501959095528b519198507f1f28d876aff267c3302a63cd25ebcca53e6f60691049df42275b6d06ab455c679489948e948e948e948e9492606085019260c086019289810192829185918391869190600490601f850104600302600f01f150905090810190601f168015610eb45780820380516001836020036101000a031916815260200191505b508381038252858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610f0d5780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390a150610cb0915050565b91508160001415610f5757600160a060020a0333166000908152600360205260409020805460ff191660011790555b34829010610bff5760405173f65b3b60010d57d0bb8478aa6ced15fe720621b490600090849082818181858883f15050503484900392508211159050610fb857604051600160a060020a03331690600090839082818181858883f150505050505b60006000505442016040518082815260200191505060405180910390209350835060006000818150548092919060010191905055507f4e65aab8959da44521dc50a6ce3dfbd65016d8cfab70a47ea7541458206c4d5b848a8a8a8a8a604051808781526020018681526020018060200180602001806020018581526020018481038452888181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f16801561108e5780820380516001836020036101000a031916815260200191505b508481038352878181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156110e75780820380516001836020036101000a031916815260200191505b508481038252868181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156111405780820380516001836020036101000a031916815260200191505b50995050505050505050505060405180910390a15050505b95945050505050565b9150816000141561119057600160a060020a0333166000908152600360205260409020805460ff191660011790555b34829010610bff5760405173f65b3b60010d57d0bb8478aa6ced15fe720621b490600090849082818181858883f150505034849003925082111590506111f157604051600160a060020a03331690600090839082818181858883f150505050505b610caa88888888610439565b82604051808280519060200190808383829060006004602084601f0104600302600f01f1506007805491909301849003909320600184018084559095508594509192918391508280158290116112765781836000526020600020918201910161127691905b808211156112a25760008155600101611262565b505050815481101561000257600091825260208083209091019290925591825260069052604090205550565b5090565b915081600014156112d557600160a060020a0333166000908152600360205260409020805460ff191660011790555b34829010610bff5760405173f65b3b60010d57d0bb8478aa6ced15fe720621b490600090849082818181858883f1505050348490039250821115905061133657604051600160a060020a03331690600090839082818181858883f150505050505b61134389898989896105f0565b9350505050611158565b50600481905560005b6007548110156113f957600780546006916000918490811015610002575080547fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6888501548352602093909352604082205485029260059291908590811015610002579082527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688018150548152602081019190915260400160002055600101611356565b5050565b90505b92915050565b9150816000141561143557600160a060020a0333166000908152600360205260409020805460ff191660011790555b34829010610bff5760405173f65b3b60010d57d0bb8478aa6ced15fe720621b490600090849082818181858883f1505050348490039250821115905061149657604051600160a060020a03331690600090839082818181858883f150505050505b6114a66000878762030d40610439565b9350505050611400565b600855565b6005600050600085604051808280519060200190808383829060006004602084601f0104600302600f01f1509091018290039091208352505060209190915260409020546008548402019050610b5756",
+ "storage": {
+ "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000004",
+ "0xde5cab2c6836c23f6388364c9a0e20bd1c8c7e6c3b5d0339cd8a2f7c4b36208c": "0x0000000000000000000000000000000000000000000000000000000000000000"
+ }
+ },
+ "0xf65b3b60010d57d0bb8478aa6ced15fe720621b4": {
+ "balance": "0x2c52a97273d2164"
+ }
+ },
+ "config": {
+ "chainId": 1,
+ "homesteadBlock": 1150000,
+ "daoForkBlock": 1920000,
+ "daoForkSupport": true,
+ "eip150Block": 2463000,
+ "eip155Block": 2675000,
+ "eip158Block": 2675000,
+ "byzantiumBlock": 4370000,
+ "constantinopleBlock": 7280000,
+ "petersburgBlock": 7280000,
+ "istanbulBlock": 9069000,
+ "muirGlacierBlock": 9200000,
+ "berlinBlock": 12244000,
+ "londonBlock": 12965000,
+ "arrowGlacierBlock": 13773000,
+ "grayGlacierBlock": 15050000,
+ "shanghaiTime": 1681338455,
+ "terminalTotalDifficulty": 7797655526461000,
+ "terminalTotalDifficultyPassed": true,
+ "ethash": {}
+ }
+ },
+ "context": {
+ "number": "469667",
+ "difficulty": "7793848077478",
+ "timestamp": "1446318425",
+ "gasLimit": "3141592",
+ "miner": "0xe48430c4e88a929bba0ee3dce284866a9937b609"
+ },
+ "input": "0xf91ec7820368850ba43b7400831b77408080b91e72606060405260018054600160a060020a0319163317905561036f600360609081527f55524c0000000000000000000000000000000000000000000000000000000000608052610120604052604c60a09081527f6a736f6e2868747470733a2f2f6170692e6b72616b656e2e636f6d2f302f707560c0527f626c69632f5469636b65723f706169723d455448584254292e726573756c742e60e0527f58455448585842542e632e3000000000000000000000000000000000000000006101005261037d919062030d417f38cc483100000000000000000000000000000000000000000000000000000000610120908152600090731d11e5eae3112dbd44f99266872ff1d07c77dce89081906338cc4831906101249060209060048188876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a03166338592832600060009054906101000a9004600160a060020a0316600160a060020a0316632ef3accc8887604051837c010000000000000000000000000000000000000000000000000000000002815260040180806020018381526020018281038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156102255780820380516001836020036101000a031916815260200191505b5093505050506020604051808303816000876161da5a03f11561000257505060405180517f385928320000000000000000000000000000000000000000000000000000000082526004828101888152606484018a90526080602485018181528d5160848701528d519496508a958e958e958e9594604484019360a40192909181908490829085908e906020601f850104600302600f01f150905090810190601f1680156102e65780820380516001836020036101000a031916815260200191505b508381038252858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f16801561033f5780820380516001836020036101000a031916815260200191505b50965050505050505060206040518083038185886185025a03f11561000257505060405151979650505050505050565b611af2806103806000396000f35b5056606060405236156100985760e060020a6000350463056e1059811461009a57806327dc297e14610391578063346b306a146103e257806341c0e1b51461075e578063489306eb146107855780635731f35714610a5e57806365a4dfb314610de05780637975c56e14611179578063a2e6204514611458578063ae152cf414611528578063b77644751461181b578063d594877014611876575b005b60408051602060248035600481810135601f81018590048502860185019096528585526119559581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750949650509335935050505060006000731d11e5eae3112dbd44f99266872ff1d07c77dce8905080600160a060020a03166338cc48316040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a03166338592832600060009054906101000a9004600160a060020a0316600160a060020a0316632ef3accc88876040518360e060020a02815260040180806020018381526020018281038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f16801561025e5780820380516001836020036101000a031916815260200191505b5093505050506020604051808303816000876161da5a03f1156100025750505060405180519060200150888888886040518660e060020a0281526004018085815260200180602001806020018481526020018381038352868181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156103085780820380516001836020036101000a031916815260200191505b508381038252858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156103615780820380516001836020036101000a031916815260200191505b50965050505050505060206040518083038185886185025a03f115610002575050604051519350610dd892505050565b60408051602060248035600481810135601f81018590048502860185019096528585526100989581359591946044949293909201918190840183828082843750949650505050505050611a2761187a565b6040805160206004803580820135601f8101849004840285018401909552848452611955949193602493909291840191908190840183828082843750506040805160208835808b0135601f8101839004830284018301909452838352979998604498929750919091019450909250829150840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750506040805160e060020a6338cc48310281529051959760009750731d11e5eae3112dbd44f99266872ff1d07c77dce8968796506338cc4831955082820194506020935091829003018188876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a03166377228659600060009054906101000a9004600160a060020a0316600160a060020a031663524f3889886040518260e060020a02815260040180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156105d15780820380516001836020036101000a031916815260200191505b50925050506020604051808303816000876161da5a03f115610002575050506040518051906020015060008888886040518660e060020a028152600401808581526020018060200180602001806020018481038452878181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156106795780820380516001836020036101000a031916815260200191505b508481038352868181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156106d25780820380516001836020036101000a031916815260200191505b508481038252858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f16801561072b5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038185886185025a03f1156100025750506040515193505050505b9392505050565b610098600154600160a060020a03908116339091161415611a255733600160a060020a0316ff5b6040805160206004803580820135601f8101849004840285018401909552848452611955949193602493909291840191908190840183828082843750506040805160208835808b0135601f8101839004830284018301909452838352979998604498929750919091019450909250829150840183828082843750506040805160e060020a6338cc48310281529051959760009750731d11e5eae3112dbd44f99266872ff1d07c77dce8968796506338cc4831955082820194506020935091829003018188876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a031663adf59f99600060009054906101000a9004600160a060020a0316600160a060020a031663524f3889876040518260e060020a02815260040180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156109345780820380516001836020036101000a031916815260200191505b50925050506020604051808303816000876161da5a03f1156100025750505060405180519060200150600087876040518560e060020a0281526004018084815260200180602001806020018381038352858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156109d75780820380516001836020036101000a031916815260200191505b508381038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610a305780820380516001836020036101000a031916815260200191505b509550505050505060206040518083038185886185025a03f115610002575050604051519695505050505050565b60408051602060248035600481810135601f81018590048502860185019096528585526119559581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976084979196506024919091019450909250829150840183828082843750506040805160e060020a6338cc48310281529051959760009750731d11e5eae3112dbd44f99266872ff1d07c77dce8968796506338cc4831955082820194506020935091829003018188876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a03166377228659600060009054906101000a9004600160a060020a0316600160a060020a031663524f3889886040518260e060020a02815260040180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610c535780820380516001836020036101000a031916815260200191505b50925050506020604051808303816000876161da5a03f1156100025750505060405180519060200150888888886040518660e060020a028152600401808581526020018060200180602001806020018481038452878181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610cfa5780820380516001836020036101000a031916815260200191505b508481038352868181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610d535780820380516001836020036101000a031916815260200191505b508481038252858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610dac5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038185886185025a03f1156100025750506040515193505050505b949350505050565b60408051602060248035600481810135601f81018590048502860185019096528585526119559581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976084979196506024919091019450909250829150840183828082843750949650509335935050505060006000731d11e5eae3112dbd44f99266872ff1d07c77dce8905080600160a060020a03166338cc48316040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a031663fbf80418600060009054906101000a9004600160a060020a0316600160a060020a0316632ef3accc89876040518360e060020a02815260040180806020018381526020018281038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610fe45780820380516001836020036101000a031916815260200191505b5093505050506020604051808303816000876161da5a03f115610002575050506040518051906020015089898989896040518760e060020a028152600401808681526020018060200180602001806020018581526020018481038452888181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156110935780820380516001836020036101000a031916815260200191505b508481038352878181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156110ec5780820380516001836020036101000a031916815260200191505b508481038252868181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156111455780820380516001836020036101000a031916815260200191505b509850505050505050505060206040518083038185886185025a03f115610002575050604051519998505050505050505050565b60408051602060248035600481810135601f81018590048502860185019096528585526119559581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750506040805160e060020a6338cc48310281529051959760009750731d11e5eae3112dbd44f99266872ff1d07c77dce8968796506338cc4831955082820194506020935091829003018188876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a031663adf59f99600060009054906101000a9004600160a060020a0316600160a060020a031663524f3889876040518260e060020a02815260040180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f16801561132e5780820380516001836020036101000a031916815260200191505b50925050506020604051808303816000876161da5a03f11561000257505050604051805190602001508787876040518560e060020a0281526004018084815260200180602001806020018381038352858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156113d05780820380516001836020036101000a031916815260200191505b508381038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156114295780820380516001836020036101000a031916815260200191505b509550505050505060206040518083038185886185025a03f11561000257505060405151935061075792505050565b6100985b611aef604060405190810160405280600381526020017f55524c0000000000000000000000000000000000000000000000000000000000815260200150608060405190810160405280604c81526020017f6a736f6e2868747470733a2f2f6170692e6b72616b656e2e636f6d2f302f707581526020017f626c69632f5469636b65723f706169723d455448584254292e726573756c742e81526020017f58455448585842542e632e30000000000000000000000000000000000000000081526020015062030d416115ae565b6040805160206004803580820135601f8101849004840285018401909552848452611955949193602493909291840191908190840183828082843750506040805160208835808b0135601f810183900483028401830190945283835297999860449892975091909101945090925082915084018382808284375094965050933593505050505b60006000731d11e5eae3112dbd44f99266872ff1d07c77dce8905080600160a060020a03166338cc48316040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a03166338592832600060009054906101000a9004600160a060020a0316600160a060020a0316632ef3accc88876040518360e060020a02815260040180806020018381526020018281038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156116e75780820380516001836020036101000a031916815260200191505b5093505050506020604051808303816000876161da5a03f115610002575050506040518051906020015060008888886040518660e060020a0281526004018085815260200180602001806020018481526020018381038352868181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156117925780820380516001836020036101000a031916815260200191505b508381038252858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156117eb5780820380516001836020036101000a031916815260200191505b50965050505050505060206040518083038185886185025a03f11561000257505060405151935061075792505050565b6040805160028054602060018216156101000260001901909116829004601f81018290048202840182019094528383526119679390830182828015611a1d5780601f106119f257610100808354040283529160200191611a1d565b6119d55b60006000731d11e5eae3112dbd44f99266872ff1d07c77dce8905080600160a060020a03166338cc48316040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604080518051855473ffffffffffffffffffffffffffffffffffffffff1916178086557f4c7737950000000000000000000000000000000000000000000000000000000082529151600160a060020a03929092169250634c773795916004828101926020929190829003018188876161da5a03f115610002575050604051519250505090565b60408051918252519081900360200190f35b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156119c75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60408051600160a060020a03929092168252519081900360200190f35b820191906000526020600020905b815481529060010190602001808311611a0057829003601f168201915b505050505081565b565b600160a060020a031633600160a060020a0316141515611a4657610002565b8060026000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611aad57805160ff19168380011785555b50611add9291505b80821115611ae75760008155600101611a99565b82800160010185558215611a91579182015b82811115611a91578251826000505591602001919060010190611abf565b5050611aeb61145c565b5090565b5050565b50561ca083d25971e732af3acb0a223dea6258f37407bf2d075fd852a83312238fca7cdea01f5a1189b054e947a0a140c565c4fc829b584e7348c9a7f65a890fe688e8b67f",
+ "tracerConfig": {
+ "withLog": true
+ },
+ "result": {
+ "from": "0x0047a8033cc6d6ca2ed5044674fd421f44884de8",
+ "gas": "0x1b7740",
+ "gasUsed": "0x9274f",
+ "to": "0xc24431c1a1147456414355b1f1769de450e524da",
+ "input": "0x606060405260018054600160a060020a0319163317905561036f600360609081527f55524c0000000000000000000000000000000000000000000000000000000000608052610120604052604c60a09081527f6a736f6e2868747470733a2f2f6170692e6b72616b656e2e636f6d2f302f707560c0527f626c69632f5469636b65723f706169723d455448584254292e726573756c742e60e0527f58455448585842542e632e3000000000000000000000000000000000000000006101005261037d919062030d417f38cc483100000000000000000000000000000000000000000000000000000000610120908152600090731d11e5eae3112dbd44f99266872ff1d07c77dce89081906338cc4831906101249060209060048188876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a03166338592832600060009054906101000a9004600160a060020a0316600160a060020a0316632ef3accc8887604051837c010000000000000000000000000000000000000000000000000000000002815260040180806020018381526020018281038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156102255780820380516001836020036101000a031916815260200191505b5093505050506020604051808303816000876161da5a03f11561000257505060405180517f385928320000000000000000000000000000000000000000000000000000000082526004828101888152606484018a90526080602485018181528d5160848701528d519496508a958e958e958e9594604484019360a40192909181908490829085908e906020601f850104600302600f01f150905090810190601f1680156102e65780820380516001836020036101000a031916815260200191505b508381038252858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f16801561033f5780820380516001836020036101000a031916815260200191505b50965050505050505060206040518083038185886185025a03f11561000257505060405151979650505050505050565b611af2806103806000396000f35b5056606060405236156100985760e060020a6000350463056e1059811461009a57806327dc297e14610391578063346b306a146103e257806341c0e1b51461075e578063489306eb146107855780635731f35714610a5e57806365a4dfb314610de05780637975c56e14611179578063a2e6204514611458578063ae152cf414611528578063b77644751461181b578063d594877014611876575b005b60408051602060248035600481810135601f81018590048502860185019096528585526119559581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750949650509335935050505060006000731d11e5eae3112dbd44f99266872ff1d07c77dce8905080600160a060020a03166338cc48316040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a03166338592832600060009054906101000a9004600160a060020a0316600160a060020a0316632ef3accc88876040518360e060020a02815260040180806020018381526020018281038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f16801561025e5780820380516001836020036101000a031916815260200191505b5093505050506020604051808303816000876161da5a03f1156100025750505060405180519060200150888888886040518660e060020a0281526004018085815260200180602001806020018481526020018381038352868181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156103085780820380516001836020036101000a031916815260200191505b508381038252858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156103615780820380516001836020036101000a031916815260200191505b50965050505050505060206040518083038185886185025a03f115610002575050604051519350610dd892505050565b60408051602060248035600481810135601f81018590048502860185019096528585526100989581359591946044949293909201918190840183828082843750949650505050505050611a2761187a565b6040805160206004803580820135601f8101849004840285018401909552848452611955949193602493909291840191908190840183828082843750506040805160208835808b0135601f8101839004830284018301909452838352979998604498929750919091019450909250829150840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750506040805160e060020a6338cc48310281529051959760009750731d11e5eae3112dbd44f99266872ff1d07c77dce8968796506338cc4831955082820194506020935091829003018188876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a03166377228659600060009054906101000a9004600160a060020a0316600160a060020a031663524f3889886040518260e060020a02815260040180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156105d15780820380516001836020036101000a031916815260200191505b50925050506020604051808303816000876161da5a03f115610002575050506040518051906020015060008888886040518660e060020a028152600401808581526020018060200180602001806020018481038452878181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156106795780820380516001836020036101000a031916815260200191505b508481038352868181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156106d25780820380516001836020036101000a031916815260200191505b508481038252858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f16801561072b5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038185886185025a03f1156100025750506040515193505050505b9392505050565b610098600154600160a060020a03908116339091161415611a255733600160a060020a0316ff5b6040805160206004803580820135601f8101849004840285018401909552848452611955949193602493909291840191908190840183828082843750506040805160208835808b0135601f8101839004830284018301909452838352979998604498929750919091019450909250829150840183828082843750506040805160e060020a6338cc48310281529051959760009750731d11e5eae3112dbd44f99266872ff1d07c77dce8968796506338cc4831955082820194506020935091829003018188876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a031663adf59f99600060009054906101000a9004600160a060020a0316600160a060020a031663524f3889876040518260e060020a02815260040180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156109345780820380516001836020036101000a031916815260200191505b50925050506020604051808303816000876161da5a03f1156100025750505060405180519060200150600087876040518560e060020a0281526004018084815260200180602001806020018381038352858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156109d75780820380516001836020036101000a031916815260200191505b508381038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610a305780820380516001836020036101000a031916815260200191505b509550505050505060206040518083038185886185025a03f115610002575050604051519695505050505050565b60408051602060248035600481810135601f81018590048502860185019096528585526119559581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976084979196506024919091019450909250829150840183828082843750506040805160e060020a6338cc48310281529051959760009750731d11e5eae3112dbd44f99266872ff1d07c77dce8968796506338cc4831955082820194506020935091829003018188876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a03166377228659600060009054906101000a9004600160a060020a0316600160a060020a031663524f3889886040518260e060020a02815260040180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610c535780820380516001836020036101000a031916815260200191505b50925050506020604051808303816000876161da5a03f1156100025750505060405180519060200150888888886040518660e060020a028152600401808581526020018060200180602001806020018481038452878181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610cfa5780820380516001836020036101000a031916815260200191505b508481038352868181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610d535780820380516001836020036101000a031916815260200191505b508481038252858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610dac5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038185886185025a03f1156100025750506040515193505050505b949350505050565b60408051602060248035600481810135601f81018590048502860185019096528585526119559581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976084979196506024919091019450909250829150840183828082843750949650509335935050505060006000731d11e5eae3112dbd44f99266872ff1d07c77dce8905080600160a060020a03166338cc48316040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a031663fbf80418600060009054906101000a9004600160a060020a0316600160a060020a0316632ef3accc89876040518360e060020a02815260040180806020018381526020018281038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610fe45780820380516001836020036101000a031916815260200191505b5093505050506020604051808303816000876161da5a03f115610002575050506040518051906020015089898989896040518760e060020a028152600401808681526020018060200180602001806020018581526020018481038452888181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156110935780820380516001836020036101000a031916815260200191505b508481038352878181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156110ec5780820380516001836020036101000a031916815260200191505b508481038252868181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156111455780820380516001836020036101000a031916815260200191505b509850505050505050505060206040518083038185886185025a03f115610002575050604051519998505050505050505050565b60408051602060248035600481810135601f81018590048502860185019096528585526119559581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750506040805160e060020a6338cc48310281529051959760009750731d11e5eae3112dbd44f99266872ff1d07c77dce8968796506338cc4831955082820194506020935091829003018188876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a031663adf59f99600060009054906101000a9004600160a060020a0316600160a060020a031663524f3889876040518260e060020a02815260040180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f16801561132e5780820380516001836020036101000a031916815260200191505b50925050506020604051808303816000876161da5a03f11561000257505050604051805190602001508787876040518560e060020a0281526004018084815260200180602001806020018381038352858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156113d05780820380516001836020036101000a031916815260200191505b508381038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156114295780820380516001836020036101000a031916815260200191505b509550505050505060206040518083038185886185025a03f11561000257505060405151935061075792505050565b6100985b611aef604060405190810160405280600381526020017f55524c0000000000000000000000000000000000000000000000000000000000815260200150608060405190810160405280604c81526020017f6a736f6e2868747470733a2f2f6170692e6b72616b656e2e636f6d2f302f707581526020017f626c69632f5469636b65723f706169723d455448584254292e726573756c742e81526020017f58455448585842542e632e30000000000000000000000000000000000000000081526020015062030d416115ae565b6040805160206004803580820135601f8101849004840285018401909552848452611955949193602493909291840191908190840183828082843750506040805160208835808b0135601f810183900483028401830190945283835297999860449892975091909101945090925082915084018382808284375094965050933593505050505b60006000731d11e5eae3112dbd44f99266872ff1d07c77dce8905080600160a060020a03166338cc48316040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a03166338592832600060009054906101000a9004600160a060020a0316600160a060020a0316632ef3accc88876040518360e060020a02815260040180806020018381526020018281038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156116e75780820380516001836020036101000a031916815260200191505b5093505050506020604051808303816000876161da5a03f115610002575050506040518051906020015060008888886040518660e060020a0281526004018085815260200180602001806020018481526020018381038352868181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156117925780820380516001836020036101000a031916815260200191505b508381038252858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156117eb5780820380516001836020036101000a031916815260200191505b50965050505050505060206040518083038185886185025a03f11561000257505060405151935061075792505050565b6040805160028054602060018216156101000260001901909116829004601f81018290048202840182019094528383526119679390830182828015611a1d5780601f106119f257610100808354040283529160200191611a1d565b6119d55b60006000731d11e5eae3112dbd44f99266872ff1d07c77dce8905080600160a060020a03166338cc48316040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604080518051855473ffffffffffffffffffffffffffffffffffffffff1916178086557f4c7737950000000000000000000000000000000000000000000000000000000082529151600160a060020a03929092169250634c773795916004828101926020929190829003018188876161da5a03f115610002575050604051519250505090565b60408051918252519081900360200190f35b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156119c75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60408051600160a060020a03929092168252519081900360200190f35b820191906000526020600020905b815481529060010190602001808311611a0057829003601f168201915b505050505081565b565b600160a060020a031633600160a060020a0316141515611a4657610002565b8060026000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611aad57805160ff19168380011785555b50611add9291505b80821115611ae75760008155600101611a99565b82800160010185558215611a91579182015b82811115611a91578251826000505591602001919060010190611abf565b5050611aeb61145c565b5090565b5050565b5056",
+ "output": "0x606060405236156100985760e060020a6000350463056e1059811461009a57806327dc297e14610391578063346b306a146103e257806341c0e1b51461075e578063489306eb146107855780635731f35714610a5e57806365a4dfb314610de05780637975c56e14611179578063a2e6204514611458578063ae152cf414611528578063b77644751461181b578063d594877014611876575b005b60408051602060248035600481810135601f81018590048502860185019096528585526119559581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750949650509335935050505060006000731d11e5eae3112dbd44f99266872ff1d07c77dce8905080600160a060020a03166338cc48316040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a03166338592832600060009054906101000a9004600160a060020a0316600160a060020a0316632ef3accc88876040518360e060020a02815260040180806020018381526020018281038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f16801561025e5780820380516001836020036101000a031916815260200191505b5093505050506020604051808303816000876161da5a03f1156100025750505060405180519060200150888888886040518660e060020a0281526004018085815260200180602001806020018481526020018381038352868181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156103085780820380516001836020036101000a031916815260200191505b508381038252858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156103615780820380516001836020036101000a031916815260200191505b50965050505050505060206040518083038185886185025a03f115610002575050604051519350610dd892505050565b60408051602060248035600481810135601f81018590048502860185019096528585526100989581359591946044949293909201918190840183828082843750949650505050505050611a2761187a565b6040805160206004803580820135601f8101849004840285018401909552848452611955949193602493909291840191908190840183828082843750506040805160208835808b0135601f8101839004830284018301909452838352979998604498929750919091019450909250829150840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750506040805160e060020a6338cc48310281529051959760009750731d11e5eae3112dbd44f99266872ff1d07c77dce8968796506338cc4831955082820194506020935091829003018188876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a03166377228659600060009054906101000a9004600160a060020a0316600160a060020a031663524f3889886040518260e060020a02815260040180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156105d15780820380516001836020036101000a031916815260200191505b50925050506020604051808303816000876161da5a03f115610002575050506040518051906020015060008888886040518660e060020a028152600401808581526020018060200180602001806020018481038452878181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156106795780820380516001836020036101000a031916815260200191505b508481038352868181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156106d25780820380516001836020036101000a031916815260200191505b508481038252858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f16801561072b5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038185886185025a03f1156100025750506040515193505050505b9392505050565b610098600154600160a060020a03908116339091161415611a255733600160a060020a0316ff5b6040805160206004803580820135601f8101849004840285018401909552848452611955949193602493909291840191908190840183828082843750506040805160208835808b0135601f8101839004830284018301909452838352979998604498929750919091019450909250829150840183828082843750506040805160e060020a6338cc48310281529051959760009750731d11e5eae3112dbd44f99266872ff1d07c77dce8968796506338cc4831955082820194506020935091829003018188876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a031663adf59f99600060009054906101000a9004600160a060020a0316600160a060020a031663524f3889876040518260e060020a02815260040180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156109345780820380516001836020036101000a031916815260200191505b50925050506020604051808303816000876161da5a03f1156100025750505060405180519060200150600087876040518560e060020a0281526004018084815260200180602001806020018381038352858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156109d75780820380516001836020036101000a031916815260200191505b508381038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610a305780820380516001836020036101000a031916815260200191505b509550505050505060206040518083038185886185025a03f115610002575050604051519695505050505050565b60408051602060248035600481810135601f81018590048502860185019096528585526119559581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976084979196506024919091019450909250829150840183828082843750506040805160e060020a6338cc48310281529051959760009750731d11e5eae3112dbd44f99266872ff1d07c77dce8968796506338cc4831955082820194506020935091829003018188876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a03166377228659600060009054906101000a9004600160a060020a0316600160a060020a031663524f3889886040518260e060020a02815260040180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610c535780820380516001836020036101000a031916815260200191505b50925050506020604051808303816000876161da5a03f1156100025750505060405180519060200150888888886040518660e060020a028152600401808581526020018060200180602001806020018481038452878181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610cfa5780820380516001836020036101000a031916815260200191505b508481038352868181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610d535780820380516001836020036101000a031916815260200191505b508481038252858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610dac5780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038185886185025a03f1156100025750506040515193505050505b949350505050565b60408051602060248035600481810135601f81018590048502860185019096528585526119559581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976084979196506024919091019450909250829150840183828082843750949650509335935050505060006000731d11e5eae3112dbd44f99266872ff1d07c77dce8905080600160a060020a03166338cc48316040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a031663fbf80418600060009054906101000a9004600160a060020a0316600160a060020a0316632ef3accc89876040518360e060020a02815260040180806020018381526020018281038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015610fe45780820380516001836020036101000a031916815260200191505b5093505050506020604051808303816000876161da5a03f115610002575050506040518051906020015089898989896040518760e060020a028152600401808681526020018060200180602001806020018581526020018481038452888181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156110935780820380516001836020036101000a031916815260200191505b508481038352878181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156110ec5780820380516001836020036101000a031916815260200191505b508481038252868181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156111455780820380516001836020036101000a031916815260200191505b509850505050505050505060206040518083038185886185025a03f115610002575050604051519998505050505050505050565b60408051602060248035600481810135601f81018590048502860185019096528585526119559581359591946044949293909201918190840183828082843750506040805160209735808a0135601f81018a90048a0283018a019093528282529698976064979196506024919091019450909250829150840183828082843750506040805160e060020a6338cc48310281529051959760009750731d11e5eae3112dbd44f99266872ff1d07c77dce8968796506338cc4831955082820194506020935091829003018188876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a031663adf59f99600060009054906101000a9004600160a060020a0316600160a060020a031663524f3889876040518260e060020a02815260040180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f16801561132e5780820380516001836020036101000a031916815260200191505b50925050506020604051808303816000876161da5a03f11561000257505050604051805190602001508787876040518560e060020a0281526004018084815260200180602001806020018381038352858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156113d05780820380516001836020036101000a031916815260200191505b508381038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156114295780820380516001836020036101000a031916815260200191505b509550505050505060206040518083038185886185025a03f11561000257505060405151935061075792505050565b6100985b611aef604060405190810160405280600381526020017f55524c0000000000000000000000000000000000000000000000000000000000815260200150608060405190810160405280604c81526020017f6a736f6e2868747470733a2f2f6170692e6b72616b656e2e636f6d2f302f707581526020017f626c69632f5469636b65723f706169723d455448584254292e726573756c742e81526020017f58455448585842542e632e30000000000000000000000000000000000000000081526020015062030d416115ae565b6040805160206004803580820135601f8101849004840285018401909552848452611955949193602493909291840191908190840183828082843750506040805160208835808b0135601f810183900483028401830190945283835297999860449892975091909101945090925082915084018382808284375094965050933593505050505b60006000731d11e5eae3112dbd44f99266872ff1d07c77dce8905080600160a060020a03166338cc48316040518160e060020a0281526004018090506020604051808303816000876161da5a03f1156100025750505060405180519060200150600060006101000a815481600160a060020a0302191690830217905550600060009054906101000a9004600160a060020a0316600160a060020a03166338592832600060009054906101000a9004600160a060020a0316600160a060020a0316632ef3accc88876040518360e060020a02815260040180806020018381526020018281038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156116e75780820380516001836020036101000a031916815260200191505b5093505050506020604051808303816000876161da5a03f115610002575050506040518051906020015060008888886040518660e060020a0281526004018085815260200180602001806020018481526020018381038352868181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156117925780820380516001836020036101000a031916815260200191505b508381038252858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156117eb5780820380516001836020036101000a031916815260200191505b50965050505050505060206040518083038185886185025a03f11561000257505060405151935061075792505050565b6040805160028054602060018216156101000260001901909116829004601f81018290048202840182019094528383526119679390830182828015611a1d5780601f106119f257610100808354040283529160200191611a1d565b6119d55b60006000731d11e5eae3112dbd44f99266872ff1d07c77dce8905080600160a060020a03166338cc48316040518160e060020a0281526004018090506020604051808303816000876161da5a03f115610002575050604080518051855473ffffffffffffffffffffffffffffffffffffffff1916178086557f4c7737950000000000000000000000000000000000000000000000000000000082529151600160a060020a03929092169250634c773795916004828101926020929190829003018188876161da5a03f115610002575050604051519250505090565b60408051918252519081900360200190f35b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156119c75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60408051600160a060020a03929092168252519081900360200190f35b820191906000526020600020905b815481529060010190602001808311611a0057829003601f168201915b505050505081565b565b600160a060020a031633600160a060020a0316141515611a4657610002565b8060026000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611aad57805160ff19168380011785555b50611add9291505b80821115611ae75760008155600101611a99565b82800160010185558215611a91579182015b82811115611a91578251826000505591602001919060010190611abf565b5050611aeb61145c565b5090565b5050565b5056",
+ "calls": [
+ {
+ "from": "0xc24431c1a1147456414355b1f1769de450e524da",
+ "gas": "0x12c54b",
+ "gasUsed": "0x106",
+ "to": "0x1d11e5eae3112dbd44f99266872ff1d07c77dce8",
+ "input": "0x38cc4831",
+ "output": "0x000000000000000000000000f631e3b3aafa084bc51c714825aacf505d2059be",
+ "value": "0x0",
+ "type": "CALL"
+ },
+ {
+ "from": "0xc24431c1a1147456414355b1f1769de450e524da",
+ "gas": "0x12",
+ "gasUsed": "0x12",
+ "to": "0x0000000000000000000000000000000000000004",
+ "input": "0x55524c",
+ "output": "0x55524c",
+ "value": "0x0",
+ "type": "CALL"
+ },
+ {
+ "from": "0xc24431c1a1147456414355b1f1769de450e524da",
+ "gas": "0x127270",
+ "gasUsed": "0x26b",
+ "to": "0xf631e3b3aafa084bc51c714825aacf505d2059be",
+ "input": "0x2ef3accc00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000030d41000000000000000000000000000000000000000000000000000000000000000355524c0000000000000000000000000000000000000000000000000000000000",
+ "output": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "value": "0x0",
+ "type": "CALL"
+ },
+ {
+ "from": "0xc24431c1a1147456414355b1f1769de450e524da",
+ "gas": "0x12",
+ "gasUsed": "0x12",
+ "to": "0x0000000000000000000000000000000000000004",
+ "input": "0x55524c",
+ "output": "0x55524c",
+ "value": "0x0",
+ "type": "CALL"
+ },
+ {
+ "from": "0xc24431c1a1147456414355b1f1769de450e524da",
+ "gas": "0x18",
+ "gasUsed": "0x18",
+ "to": "0x0000000000000000000000000000000000000004",
+ "input": "0x6a736f6e2868747470733a2f2f6170692e6b72616b656e2e636f6d2f302f7075626c69632f5469636b65723f706169723d455448584254292e726573756c742e58455448585842542e632e30",
+ "output": "0x6a736f6e2868747470733a2f2f6170692e6b72616b656e2e636f6d2f302f7075626c69632f5469636b65723f706169723d455448584254292e726573756c742e58455448585842542e632e30",
+ "value": "0x0",
+ "type": "CALL"
+ },
+ {
+ "from": "0xc24431c1a1147456414355b1f1769de450e524da",
+ "gas": "0x124995",
+ "gasUsed": "0x78f5",
+ "to": "0xf631e3b3aafa084bc51c714825aacf505d2059be",
+ "input": "0x385928320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000030d41000000000000000000000000000000000000000000000000000000000000000355524c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c6a736f6e2868747470733a2f2f6170692e6b72616b656e2e636f6d2f302f7075626c69632f5469636b65723f706169723d455448584254292e726573756c742e58455448585842542e632e300000000000000000000000000000000000000000",
+ "output": "0x55bc8431ce52389ac668a9b14a0943290cb7263732251186e960bc8b249b5f32",
+ "calls": [
+ {
+ "from": "0xf631e3b3aafa084bc51c714825aacf505d2059be",
+ "gas": "0x0",
+ "gasUsed": "0x0",
+ "to": "0xf65b3b60010d57d0bb8478aa6ced15fe720621b4",
+ "input": "0x",
+ "value": "0x0",
+ "type": "CALL"
+ },
+ {
+ "from": "0xf631e3b3aafa084bc51c714825aacf505d2059be",
+ "gas": "0x12",
+ "gasUsed": "0x12",
+ "to": "0x0000000000000000000000000000000000000004",
+ "input": "0x55524c",
+ "output": "0x55524c",
+ "value": "0x0",
+ "type": "CALL"
+ },
+ {
+ "from": "0xf631e3b3aafa084bc51c714825aacf505d2059be",
+ "gas": "0x18",
+ "gasUsed": "0x18",
+ "to": "0x0000000000000000000000000000000000000004",
+ "input": "0x6a736f6e2868747470733a2f2f6170692e6b72616b656e2e636f6d2f302f7075626c69632f5469636b65723f706169723d455448584254292e726573756c742e58455448585842542e632e30",
+ "output": "0x6a736f6e2868747470733a2f2f6170692e6b72616b656e2e636f6d2f302f7075626c69632f5469636b65723f706169723d455448584254292e726573756c742e58455448585842542e632e30",
+ "value": "0x0",
+ "type": "CALL"
+ }
+ ],
+ "logs": [
+ {
+ "address": "0xf631e3b3aafa084bc51c714825aacf505d2059be",
+ "topics": [
+ "0x1f28d876aff267c3302a63cd25ebcca53e6f60691049df42275b6d06ab455c67"
+ ],
+ "data": "0x55bc8431ce52389ac668a9b14a0943290cb7263732251186e960bc8b249b5f32000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000030d41000000000000000000000000000000000000000000000000000000000000000355524c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c6a736f6e2868747470733a2f2f6170692e6b72616b656e2e636f6d2f302f7075626c69632f5469636b65723f706169723d455448584254292e726573756c742e58455448585842542e632e300000000000000000000000000000000000000000",
+ "position": "0x3"
+ }
+ ],
+ "value": "0x0",
+ "type": "CALL"
+ }
+ ],
+ "logs": [
+ {
+ "address": "0x0000000000000000000000000000000000001010",
+ "topics": [
+ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63",
+ "0x0000000000000000000000000000000000000000000000000000000000001010",
+ "0x0000000000000000000000000047a8033cc6d6ca2ed5044674fd421f44884de8",
+ "0x000000000000000000000000e48430c4e88a929bba0ee3dce284866a9937b609"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000006a8fb3d104cc0000000000000000000000000000000000000000000000000044f5ced08fe37cf70000000000000000000000000000000000000000000000026758774d51d8677a000000000000000000000000000000000000000000000000448b3f1cbedeb0f700000000000000000000000000000000000000000000000267c3070122dd337a",
+ "position": "0x6"
+ }
+ ],
+ "value": "0x0",
+ "type": "CREATE"
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multi_contracts.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multi_contracts.json
index 263e88d6e1..0797f11834 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multi_contracts.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multi_contracts.json
@@ -713,6 +713,19 @@
"gasUsed": "0x4e91",
"to": "0xad3ecf23c0c8983b07163708be6d763b5f056193",
"input": "0x",
+ "logs": [
+ {
+ "address": "0x0000000000000000000000000000000000001010",
+ "topics": [
+ "0xe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c4",
+ "0x0000000000000000000000000000000000000000000000000000000000001010",
+ "0x0000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc",
+ "0x000000000000000000000000ad3ecf23c0c8983b07163708be6d763b5f056193"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000004563918244f400000000000000000000000000000000000000000000000000004563918244f40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004563918244f400000",
+ "position": "0x0"
+ }
+ ],
"value": "0x4563918244f400000",
"type": "CALL"
},
@@ -887,6 +900,19 @@
"type": "CALL"
}
],
+ "logs": [
+ {
+ "address": "0x0000000000000000000000000000000000001010",
+ "topics": [
+ "0xe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c4",
+ "0x0000000000000000000000000000000000000000000000000000000000001010",
+ "0x000000000000000000000000ad3ecf23c0c8983b07163708be6d763b5f056193",
+ "0x0000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc"
+ ],
+ "data": "0x0000000000000000000000000000000000000000000000022b1c8c12279fffff0000000000000000000000000000000000000000000000022b1c8c1227a000010000000000000000000000000000000000000000000000022b1c8c12279fffff0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000004563918244f3ffffe",
+ "position": "0x0"
+ }
+ ],
"value": "0x22b1c8c12279fffff",
"type": "CALL"
}
@@ -910,6 +936,19 @@
"type": "CALL"
}
],
+ "logs": [
+ {
+ "address": "0x0000000000000000000000000000000000001010",
+ "topics": [
+ "0xe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c4",
+ "0x0000000000000000000000000000000000000000000000000000000000001010",
+ "0x000000000000000000000000ad3ecf23c0c8983b07163708be6d763b5f056193",
+ "0x0000000000000000000000006e715ab4f598eacf0016b9b35ef33e4141844ccc"
+ ],
+ "data": "0x0000000000000000000000000000000000000000000000022b1c8c12279fffff000000000000000000000000000000000000000000000004563918244f40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022b1c8c1227a000010000000000000000000000000000000000000000000000022b1c8c12279fffff",
+ "position": "0x0"
+ }
+ ],
"value": "0x22b1c8c12279fffff",
"type": "CALL"
}
@@ -2321,6 +2360,19 @@
"type": "CALL"
}
],
+ "logs": [
+ {
+ "address": "0x0000000000000000000000000000000000001010",
+ "topics": [
+ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63",
+ "0x0000000000000000000000000000000000000000000000000000000000001010",
+ "0x000000000000000000000000be3ae5cb97c253dda67181c6e34e43f5c275e08b",
+ "0x000000000000000000000000ea674fdde714fd979de3edf0f56aa9716b898ec8"
+ ],
+ "data": "0x00000000000000000000000000000000000000000000000000e25384e63aa60000000000000000000000000000000000000000000000000167d285b38143c04f00000000000000000000000000000000000000000000004ab3566739e7b2437100000000000000000000000000000000000000000000000166f0322e9b091a4f00000000000000000000000000000000000000000000004ab438babecdece971",
+ "position": "0x23"
+ }
+ ],
"value": "0x0",
"type": "CALL"
}
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multilogs.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multilogs.json
index 66d4582008..2f5a473cfe 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multilogs.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/multilogs.json
@@ -173,6 +173,17 @@
"input": "0xe021fadb000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000d4000000000000000000000000000000000000000000000000000000000000013a00000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002ff000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000002fd000000000000000000000000000000000000000000000000000000000000034300000000000000000000000000000000000000000000000000000000000002fd0000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003900000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b00000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c00000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000039000000000000000000000000000000000000000000000000000000000000003900000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035000000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b00000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c00000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033000000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000032fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffebebebffffffffffffffffffffffffffffffffffffffffffffffffffffffffff888888ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb3b3b3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcfcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe3e3e3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3e3e3effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbdbdbfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f4f4fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfbfbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb0b0b0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0a0a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b5b5bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbababaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeaeaeaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa9a9a9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb9b9b9fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfbfbfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbababaffffffffffffffffffffffffffffffffffffffffffffffffffffffffff636363fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9f9f9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeaeaeaffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c9c9cfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8f8f8fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcfcfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4d4e53ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f494b00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e080000000000000000000000000000000000000000000000000000011c37937e08000",
"output": "0x0000000000000000000000000000000000000000000000000000000000000001",
"logs": [
+ {
+ "address": "0x0000000000000000000000000000000000001010",
+ "topics": [
+ "0xe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c4",
+ "0x0000000000000000000000000000000000000000000000000000000000001010",
+ "0x0000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08",
+ "0x000000000000000000000000350e0ffc780a6a75b44cc52e1ff9092870668945"
+ ],
+ "data": "0x00000000000000000000000000000000000000000000000003782dace9d9000000000000000000000000000000000000000000000000000067f963ad0ca28400000000000000000000000000000000000000000000000000e37111b7c79406c00000000000000000000000000000000000000000000000006481360022c98400000000000000000000000000000000000000000000000000e6e93f64b16d06c0",
+ "position": "0x0"
+ },
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
"topics": [
@@ -355,7 +366,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -363,7 +374,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0a0a00000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -371,7 +382,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b5b5b0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -379,7 +390,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbababa0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -387,7 +398,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -395,7 +406,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeaeaea0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -403,7 +414,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa9a9a90000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -411,7 +422,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb9b9b90000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -419,7 +430,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfbfb0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -427,7 +438,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -435,7 +446,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefefe0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -443,7 +454,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbababa0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -451,7 +462,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6363630000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -459,7 +470,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -467,7 +478,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9f9f90000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -475,7 +486,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeaeaea0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -483,7 +494,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c9c9c0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -491,7 +502,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8f8f80000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -499,7 +510,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -507,7 +518,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfd0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -515,7 +526,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -523,7 +534,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -531,7 +542,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x000000000000000000000000000000000000000000000000000000000000034200000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcfcfc0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -539,7 +550,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x00000000000000000000000000000000000000000000000000000000000002fe000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfd0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -547,7 +558,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x0000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -555,7 +566,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4d4e530000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -563,7 +574,7 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x000000000000000000000000000000000000000000000000000000000000034300000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
},
{
"address": "0x350e0ffc780a6a75b44cc52e1ff9092870668945",
@@ -571,7 +582,18 @@
"0xcacb62d8acea4678658eb5dc4aaa889b34d893b967c96a5f8c066e6549fa3f42"
],
"data": "0x00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f494b0000000000000000000000000000000000000000000000000011c37937e08000",
- "position": "0x0"
+ "position": "0x0"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000001010",
+ "topics": [
+ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63",
+ "0x0000000000000000000000000000000000000000000000000000000000001010",
+ "0x0000000000000000000000003fcb0342353c541e210013aaddc2e740b9a33d08",
+ "0x0000000000000000000000002a65aca4d5fc5b5c859090a6c34d164135398226"
+ ],
+ "data": "0x00000000000000000000000000000000000000000000000001b3dd214f1b8c000000000000000000000000000000000000000000000000006a0e4be198f18400000000000000000000000000000000000000000000000044dc051cccdfd2e132000000000000000000000000000000000000000000000000685a6ec049d5f800000000000000000000000000000000000000000000000044ddb8f9ee2eee6d32",
+ "position": "0x0"
}
],
"value": "0x3782dace9d90000",
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/notopic.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/notopic.json
index 762ccbe58f..9c5a0af33f 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/notopic.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/notopic.json
@@ -261,6 +261,17 @@
}
],
"logs": [
+ {
+ "address": "0x0000000000000000000000000000000000001010",
+ "topics": [
+ "0xe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c4",
+ "0x0000000000000000000000000000000000000000000000000000000000001010",
+ "0x00000000000000000000000050739060a2c32dc076e507ae1a893aab28ecfe68",
+ "0x00000000000000000000000088e1315687aec48a72786c6b3b3f075208b62713"
+ ],
+ "data": "0x00000000000000000000000000000000000000000000000000179d63013c5654000000000000000000000000000000000000000000000006ad16c019b81a414100000000000000000000000000000000000000000000000024b9f2c5dc266dc6000000000000000000000000000000000000000000000006acff22b6b6ddeaed00000000000000000000000000000000000000000000000024d19028dd62c41a",
+ "position": "0x0"
+ },
{
"address": "0x88e1315687aec48a72786c6b3b3f075208b62713",
"topics": [
@@ -275,11 +286,33 @@
}
],
"logs": [
+ {
+ "address": "0x0000000000000000000000000000000000001010",
+ "topics": [
+ "0xe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c4",
+ "0x0000000000000000000000000000000000000000000000000000000000001010",
+ "0x0000000000000000000000006412becf35cc7e2a9e7e47966e443f295e1e4f4a",
+ "0x00000000000000000000000050739060a2c32dc076e507ae1a893aab28ecfe68"
+ ],
+ "data": "0x0000000000000000000000000000000000000000000000000429d069189e00000000000000000000000000000000000000000000000000000fa6f01b59360e70000000000000000000000000000000000000000000000006a8ecefb09f7c41410000000000000000000000000000000000000000000000000b7d1fb240980e70000000000000000000000000000000000000000000000006ad16c019b81a4141",
+ "position": "0x0"
+ },
{
"address": "0x50739060a2c32dc076e507ae1a893aab28ecfe68",
"topics": [],
"data": "0x62616e6b726f6c6c5f6d69736d61746368",
"position": "0x2"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000001010",
+ "topics": [
+ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63",
+ "0x0000000000000000000000000000000000000000000000000000000000001010",
+ "0x0000000000000000000000006412becf35cc7e2a9e7e47966e443f295e1e4f4a",
+ "0x00000000000000000000000061c808d82a3ac53231750dadc13c777b59310bd9"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000b30d0148e06000000000000000000000000000000000000000000000000000fb5dbfc0d448e7000000000000000000000000000000000000000000000012f621ea72fef44f8480000000000000000000000000000000000000000000000000faaab2bf8b6887000000000000000000000000000000000000000000000012f6229d80003d2fe48",
+ "position": "0x9"
}
],
"value": "0x429d069189e0000",
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/simple.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/simple.json
index 64941dd4db..ceaf1ca8d8 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/simple.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/simple.json
@@ -77,6 +77,17 @@
],
"data": "0x0000000000000000000000000000000000000000000000000000000000989680",
"position": "0x0"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000001010",
+ "topics": [
+ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63",
+ "0x0000000000000000000000000000000000000000000000000000000000001010",
+ "0x000000000000000000000000d1220a0cf47c7b9be7a2e6ba89f429762e7b9adb",
+ "0x000000000000000000000000e2fe6b13287f28e193333fdfe7fedf2f6df6124a"
+ ],
+ "data": "0x00000000000000000000000000000000000000000000000000090886d609c4000000000000000000000000000000000000000000000000014203bee2ea6fbe8c0000000000000000000000000000000000000000000002717a9c870a286f435000000000000000000000000000000000000000000000000141fab65c1465fa8c0000000000000000000000000000000000000000000002717aa58f90fe790750",
+ "position": "0x0"
}
],
"value": "0x0",
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_partial_failed.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_partial_failed.json
index 6faf898a0f..4df4fdc291 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_partial_failed.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/tx_partial_failed.json
@@ -100,6 +100,17 @@
],
"data": "0x00000000000000000000000001115b41bd2731353dd3e6abf44818fdc035aaf10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bb9bc244d798123fde783fcc1c72d3bb8c1894130000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008861393035396362623030303030303030303030303030303030303030303030303930643363313831326465323636396266383037626437373538636562316533343937616337653430303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303031633662663532363334303030",
"position": "0x0"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000001010",
+ "topics": [
+ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63",
+ "0x0000000000000000000000000000000000000000000000000000000000001010",
+ "0x00000000000000000000000001115b41bd2731353dd3e6abf44818fdc035aaf1",
+ "0x00000000000000000000000061c808d82a3ac53231750dadc13c777b59310bd9"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000bcd242cec0800000000000000000000000000000000000000000000000000016d99e16e80900000000000000000000000000000000000000000000000006a636960e34bd696f40000000000000000000000000000000000000000000000000161ccbd4194880000000000000000000000000000000000000000000000006a63752e0778c29ef4",
+ "position": "0x1"
}
],
"value": "0x0",
diff --git a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/with_onlyTopCall.json b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/with_onlyTopCall.json
index e73081107f..87d360352f 100644
--- a/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/with_onlyTopCall.json
+++ b/eth/tracers/internal/tracetest/testdata/call_tracer_withLog/with_onlyTopCall.json
@@ -83,6 +83,30 @@
"to": "0x200edd17f30485a8735878661960cd7a9a95733f",
"input": "0xba51a6df0000000000000000000000000000000000000000000000000000000000000000",
"output": "0xba51a6df00000000000000000000000000000000000000000000000000000000",
+ "logs": [
+ {
+ "address": "0x0000000000000000000000000000000000001010",
+ "topics": [
+ "0xe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c4",
+ "0x0000000000000000000000000000000000000000000000000000000000001010",
+ "0x0000000000000000000000004f5777744b500616697cb655dcb02ee6cd51deb5",
+ "0x000000000000000000000000200edd17f30485a8735878661960cd7a9a95733f"
+ ],
+ "data": "0x0000000000000000000000000000000000000000000000008ac7230489e80000000000000000000000000000000000000000000000000000b0767db57cd070aa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025af5ab0f2e870aa0000000000000000000000000000000000000000000000008ac7230489e80000",
+ "position": "0x0"
+ },
+ {
+ "address": "0x0000000000000000000000000000000000001010",
+ "topics": [
+ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63",
+ "0x0000000000000000000000000000000000000000000000000000000000001010",
+ "0x0000000000000000000000004f5777744b500616697cb655dcb02ee6cd51deb5",
+ "0x000000000000000000000000f8b483dba2c3b7176a3da549ad41a48bb3121069"
+ ],
+ "data": "0x00000000000000000000000000000000000000000000000000119b54eb98e126000000000000000000000000000000000000000000000000b0983f1b83eec29000000000000000000000000000000000000000000000016969a0ba2c2d384d07000000000000000000000000000000000000000000000000b086a3c69855e16a00000000000000000000000000000000000000000000016969b2558118d12e2d",
+ "position": "0x0"
+ }
+ ],
"value": "0x8ac7230489e80000",
"type": "CALL"
}
diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_create.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_create.json
new file mode 100644
index 0000000000..7ccea917e6
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_create.json
@@ -0,0 +1,70 @@
+{
+ "genesis": {
+ "baseFeePerGas": "875000000",
+ "difficulty": "0",
+ "extraData": "0xd983010d05846765746888676f312e32312e318664617277696e",
+ "gasLimit": "11511229",
+ "hash": "0xd462585c6c5a3b3bf14850ebcde71b6615b9aaf6541403f9a0457212dd0502e0",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "mixHash": "0xfa51e868d6a7c0728f18800e4cc8d4cc1c87430cc9975e947eb6c9c03599b4e2",
+ "nonce": "0x0000000000000000",
+ "number": "1",
+ "stateRoot": "0xd2ebe0a7f3572ffe3e5b4c78147376d3fca767f236e4dd23f9151acfec7cb0d1",
+ "timestamp": "1699617692",
+ "totalDifficulty": "0",
+ "withdrawals": [],
+ "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
+ "alloc": {
+ "0x0000000000000000000000000000000000000000": {
+ "balance": "0x5208"
+ },
+ "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266": {
+ "balance": "0x8ac7230489e80000"
+ }
+ },
+ "config": {
+ "chainId": 1337,
+ "homesteadBlock": 0,
+ "eip150Block": 0,
+ "eip155Block": 0,
+ "eip158Block": 0,
+ "byzantiumBlock": 0,
+ "constantinopleBlock": 0,
+ "petersburgBlock": 0,
+ "istanbulBlock": 0,
+ "muirGlacierBlock": 0,
+ "berlinBlock": 0,
+ "londonBlock": 0,
+ "arrowGlacierBlock": 0,
+ "grayGlacierBlock": 0,
+ "shanghaiTime": 0,
+ "terminalTotalDifficulty": 0,
+ "terminalTotalDifficultyPassed": true,
+ "isDev": true,
+ "bor": {
+ "validatorContract": "0x0000000000000000000000000000000000001000",
+ "stateReceiverContract": "0x0000000000000000000000000000000000001001",
+ "burntContract": {
+ "0": "0x00000000000000000000000000000000000000000"
+ }
+ }
+ }
+ },
+ "context": {
+ "number": "2",
+ "difficulty": "0",
+ "timestamp": "1699617847",
+ "gasLimit": "11522469",
+ "miner": "0x0000000000000000000000000000000000000000",
+ "baseFeePerGas": "765625000"
+ },
+ "input": "0x02f902b48205398084b2d05e0085011b1f3f8083031ca88080b90258608060405234801561001057600080fd5b5060405161001d906100e3565b604051809103906000f080158015610039573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b039290921691821781556040517fc66247bafd1305823857fb4c3e651e684d918df8554ef560bbbcb025fdd017039190a26000546040516360fe47b160e01b8152600560048201526001600160a01b03909116906360fe47b190602401600060405180830381600087803b1580156100c657600080fd5b505af11580156100da573d6000803e3d6000fd5b505050506100ef565b60ca8061018e83390190565b6091806100fd6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806380de699314602d575b600080fd5b600054603f906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f3fea2646970667358221220dab781465e7f4cf20304cc388130a763508e20edd25b4bc8ea8f57743a0de8da64736f6c634300081700336080604052348015600f57600080fd5b5060ac8061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806360fe47b11460375780636d4ce63c146049575b600080fd5b60476042366004605e565b600055565b005b60005460405190815260200160405180910390f35b600060208284031215606f57600080fd5b503591905056fea264697066735822122049e09da6320793487d58eaa7b97f802618a062cbc35f08ca1ce92c17349141f864736f6c63430008170033c080a01d4fce93ad08bf413052645721f20e6136830cf5a2759fa57e76a134e90899a7a0399a72832d52118991dc04c4f9e1c0fec3d5e441ad7d4b055f0cf03130d8f815",
+ "result": {
+ "0x0000000000000000000000000000000000000000": {
+ "balance": "0x5208"
+ },
+ "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266": {
+ "balance": "0x8ac7230489e80000"
+ }
+ }
+}
\ No newline at end of file
diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_post_eip158.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_post_eip158.json
new file mode 100644
index 0000000000..eab239a50d
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer/create_post_eip158.json
@@ -0,0 +1,72 @@
+{
+ "genesis": {
+ "baseFeePerGas": "7",
+ "difficulty": "2",
+ "extraData": "0xd983010d0e846765746888676f312e32312e318664617277696e0000000000001713699f05f79a59abec177c7a87b90ceda79b72ff5edc9197dd7627a447cde45b079bbc3765a236cdf680e2d4d2247135d0e6bb6fd92b50638b92504ddb274f00",
+ "gasLimit": "30000000",
+ "hash": "0x6ad5258175c66f4e883d238a92a08428d8ebcbeac631ab7b972634cc05effab3",
+ "miner": "0x2445e8c26a2bf3d1e59f1bb9b1d442caf90768e0",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "number": "39137",
+ "stateRoot": "0x715f00df764dbadd4863247a215ac44b5420beafde3ec458b15db7aafa89be0c",
+ "timestamp": "1709022192",
+ "totalDifficulty": "78275",
+ "alloc": {
+ "0x2445e8c26a2bf3d1e59f1bb9b1d442caf90768e0": {
+ "balance": "0x10f06447a8d44dba190",
+ "nonce": "2"
+ },
+ "0x82211934c340b29561381392348d48413e15adc8": {
+ "balance": "0x6abd7a808913ed2",
+ "nonce": "64"
+ }
+ },
+ "config": {
+ "chainId": 12345,
+ "homesteadBlock": 0,
+ "eip150Block": 0,
+ "eip155Block": 0,
+ "eip158Block": 0,
+ "byzantiumBlock": 0,
+ "constantinopleBlock": 0,
+ "petersburgBlock": 0,
+ "istanbulBlock": 0,
+ "muirGlacierBlock": 0,
+ "berlinBlock": 0,
+ "londonBlock": 0,
+ "arrowGlacierBlock": 0,
+ "grayGlacierBlock": 0,
+ "clique": {
+ "period": 5,
+ "epoch": 30000
+ },
+ "bor": {
+ "validatorContract": "0x0000000000000000000000000000000000001000",
+ "stateReceiverContract": "0x0000000000000000000000000000000000001001",
+ "burntContract": {
+ "0": "0x00000000000000000000000000000000000000000"
+ }
+ }
+ }
+ },
+ "context": {
+ "number": "39138",
+ "difficulty": "2",
+ "timestamp": "1709022197",
+ "gasLimit": "30000000",
+ "miner": "0x2445e8c26a2bf3d1e59f1bb9b1d442caf90768e0",
+ "baseFeePerGas": "7"
+ },
+ "input": "0x02f902af823039408459682f008459682f088302b3538080b90254608060405234801561001057600080fd5b50610234806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806309ce9ccb1461003b5780633fb5c1cb14610059575b600080fd5b610043610075565b60405161005091906100e2565b60405180910390f35b610073600480360381019061006e919061012e565b61007b565b005b60005481565b80600081905550600a8111156100c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906101de565b60405180910390fd5b50565b6000819050919050565b6100dc816100c9565b82525050565b60006020820190506100f760008301846100d3565b92915050565b600080fd5b61010b816100c9565b811461011657600080fd5b50565b60008135905061012881610102565b92915050565b600060208284031215610144576101436100fd565b5b600061015284828501610119565b91505092915050565b600082825260208201905092915050565b7f4e756d6265722069732067726561746572207468616e2031302c207472616e7360008201527f616374696f6e2072657665727465642e00000000000000000000000000000000602082015250565b60006101c860308361015b565b91506101d38261016c565b604082019050919050565b600060208201905081810360008301526101f7816101bb565b905091905056fea264697066735822122069018995fecf03bda91a88b6eafe41641709dee8b4a706fe301c8a569fe8c1b364736f6c63430008130033c001a0a8cf4729b7e4664687abb3e2559853d7d489eb441519be2a17493061fb4c3a03a04b5a904ba8a6e59c6c40049c4d14a73233aeb8a45b38403199f304630dc0d453",
+ "result": {
+ "0x2445e8c26a2bf3d1e59f1bb9b1d442caf90768e0": {
+ "balance": "0x10f06447a8d44dba190",
+ "nonce": 2
+ },
+ "0x82211934c340b29561381392348d48413e15adc8": {
+ "balance": "0x6abd7a808913ed2",
+ "nonce": 64
+ }
+ }
+}
diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_failed.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_failed.json
index 2f6e08e707..88eafbd737 100644
--- a/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_failed.json
+++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_failed.json
@@ -1,6 +1,6 @@
{
"genesis": {
- "baseFeePerGas": "51088069741",
+ "baseFeePerGas": "4573728117",
"difficulty": "14315558652874667",
"extraData": "0xd883010a10846765746888676f312e31362e35856c696e7578",
"gasLimit": "30058590",
@@ -71,7 +71,8 @@
"difficulty": "14322823549655084",
"timestamp": "1651623279",
"gasLimit": "30029237",
- "miner": "0x8f03f1a3f10c05e7cccf75c1fd10168e06659be7"
+ "miner": "0x8f03f1a3f10c05e7cccf75c1fd10168e06659be7",
+ "baseFeePerGas": "4002012103"
},
"input": "0x02f8b4018312acfc8459682f00851a46bcf47a8302b1a194ffa397285ce46fb78c588a9e993286aac68c37cd80b844fb90b3200000000000000000000000002a549b4af9ec39b03142da6dc32221fc390b553300000000000000000000000000000000000000000000000000000000000cb3d5c001a03002079d2873f7963c4278200c43aa71efad262b2150bc8524480acfc38b5faaa077d44aa09d56b9cf99443c7f55aaad1bbae9cfb5bbb9de31eaf7a8f9e623e980",
"tracerConfig": {
@@ -90,7 +91,7 @@
},
"post": {
"0x808b4da0be6c9512e948521452227efc619bea52": {
- "balance": "0x2cd72a36dd031f089",
+ "balance": "0x2cdb5f8e62cc9ad1c",
"nonce": 1223933
},
"0x8f03f1a3f10c05e7cccf75c1fd10168e06659be7": {
diff --git a/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_post_eip158.json b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_post_eip158.json
new file mode 100644
index 0000000000..a14e6c0211
--- /dev/null
+++ b/eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_post_eip158.json
@@ -0,0 +1,90 @@
+{
+ "genesis": {
+ "baseFeePerGas": "7",
+ "difficulty": "2",
+ "extraData": "0xd983010d0e846765746888676f312e32312e318664617277696e0000000000001713699f05f79a59abec177c7a87b90ceda79b72ff5edc9197dd7627a447cde45b079bbc3765a236cdf680e2d4d2247135d0e6bb6fd92b50638b92504ddb274f00",
+ "gasLimit": "30000000",
+ "hash": "0x6ad5258175c66f4e883d238a92a08428d8ebcbeac631ab7b972634cc05effab3",
+ "miner": "0x2445e8c26a2bf3d1e59f1bb9b1d442caf90768e0",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "nonce": "0x0000000000000000",
+ "number": "39137",
+ "stateRoot": "0x715f00df764dbadd4863247a215ac44b5420beafde3ec458b15db7aafa89be0c",
+ "timestamp": "1709022192",
+ "totalDifficulty": "78275",
+ "alloc": {
+ "0x2445e8c26a2bf3d1e59f1bb9b1d442caf90768e0": {
+ "balance": "0x10f06447a8d44dba190",
+ "nonce": "2"
+ },
+ "0x82211934c340b29561381392348d48413e15adc8": {
+ "balance": "0x6abd7a808913ed2",
+ "nonce": "64"
+ }
+ },
+ "config": {
+ "chainId": 12345,
+ "homesteadBlock": 0,
+ "eip150Block": 0,
+ "eip155Block": 0,
+ "eip158Block": 0,
+ "byzantiumBlock": 0,
+ "constantinopleBlock": 0,
+ "petersburgBlock": 0,
+ "istanbulBlock": 0,
+ "muirGlacierBlock": 0,
+ "berlinBlock": 0,
+ "londonBlock": 0,
+ "arrowGlacierBlock": 0,
+ "grayGlacierBlock": 0,
+ "clique": {
+ "period": 5,
+ "epoch": 30000
+ },
+ "bor": {
+ "validatorContract": "0x0000000000000000000000000000000000001000",
+ "stateReceiverContract": "0x0000000000000000000000000000000000001001",
+ "burntContract": {
+ "0": "0x00000000000000000000000000000000000000000"
+ }
+ }
+ }
+ },
+ "context": {
+ "number": "39138",
+ "difficulty": "2",
+ "timestamp": "1709022197",
+ "gasLimit": "30000000",
+ "miner": "0x2445e8c26a2bf3d1e59f1bb9b1d442caf90768e0",
+ "baseFeePerGas": "7"
+ },
+ "input": "0x02f902af823039408459682f008459682f088302b3538080b90254608060405234801561001057600080fd5b50610234806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806309ce9ccb1461003b5780633fb5c1cb14610059575b600080fd5b610043610075565b60405161005091906100e2565b60405180910390f35b610073600480360381019061006e919061012e565b61007b565b005b60005481565b80600081905550600a8111156100c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906101de565b60405180910390fd5b50565b6000819050919050565b6100dc816100c9565b82525050565b60006020820190506100f760008301846100d3565b92915050565b600080fd5b61010b816100c9565b811461011657600080fd5b50565b60008135905061012881610102565b92915050565b600060208284031215610144576101436100fd565b5b600061015284828501610119565b91505092915050565b600082825260208201905092915050565b7f4e756d6265722069732067726561746572207468616e2031302c207472616e7360008201527f616374696f6e2072657665727465642e00000000000000000000000000000000602082015250565b60006101c860308361015b565b91506101d38261016c565b604082019050919050565b600060208201905081810360008301526101f7816101bb565b905091905056fea264697066735822122069018995fecf03bda91a88b6eafe41641709dee8b4a706fe301c8a569fe8c1b364736f6c63430008130033c001a0a8cf4729b7e4664687abb3e2559853d7d489eb441519be2a17493061fb4c3a03a04b5a904ba8a6e59c6c40049c4d14a73233aeb8a45b38403199f304630dc0d453",
+ "tracerConfig": {
+ "diffMode": true
+ },
+ "result": {
+ "post": {
+ "0x1bda2f8e4735507930bd6cfe873bf0bf0f4ab1de": {
+ "code": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806309ce9ccb1461003b5780633fb5c1cb14610059575b600080fd5b610043610075565b60405161005091906100e2565b60405180910390f35b610073600480360381019061006e919061012e565b61007b565b005b60005481565b80600081905550600a8111156100c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906101de565b60405180910390fd5b50565b6000819050919050565b6100dc816100c9565b82525050565b60006020820190506100f760008301846100d3565b92915050565b600080fd5b61010b816100c9565b811461011657600080fd5b50565b60008135905061012881610102565b92915050565b600060208284031215610144576101436100fd565b5b600061015284828501610119565b91505092915050565b600082825260208201905092915050565b7f4e756d6265722069732067726561746572207468616e2031302c207472616e7360008201527f616374696f6e2072657665727465642e00000000000000000000000000000000602082015250565b60006101c860308361015b565b91506101d38261016c565b604082019050919050565b600060208201905081810360008301526101f7816101bb565b905091905056fea264697066735822122069018995fecf03bda91a88b6eafe41641709dee8b4a706fe301c8a569fe8c1b364736f6c63430008130033",
+ "nonce": 1
+ },
+ "0x2445e8c26a2bf3d1e59f1bb9b1d442caf90768e0": {
+ "balance": "0x10f0645688331eb5690"
+ },
+ "0x82211934c340b29561381392348d48413e15adc8": {
+ "balance": "0x6aae9b21b6ee855",
+ "nonce": 65
+ }
+ },
+ "pre": {
+ "0x2445e8c26a2bf3d1e59f1bb9b1d442caf90768e0": {
+ "balance": "0x10f06447a8d44dba190",
+ "nonce": 2
+ },
+ "0x82211934c340b29561381392348d48413e15adc8": {
+ "balance": "0x6abd7a808913ed2",
+ "nonce": 64
+ }
+ }
+ }
+}
diff --git a/eth/tracers/internal/tracetest/util.go b/eth/tracers/internal/tracetest/util.go
index 73a8ec3ffa..6c1adef5e6 100644
--- a/eth/tracers/internal/tracetest/util.go
+++ b/eth/tracers/internal/tracetest/util.go
@@ -1,67 +1,21 @@
package tracetest
import (
+ "math/big"
"strings"
"unicode"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/vm"
+
// Force-load native and js packages, to trigger registration
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
_ "github.com/ethereum/go-ethereum/eth/tracers/native"
)
-// To generate a new callTracer test, copy paste the makeTest method below into
-// a Geth console and call it with a transaction hash you which to export.
-
-/*
-// makeTest generates a callTracer test by running a prestate reassembled and a
-// call trace run, assembling all the gathered information into a test case.
-var makeTest = function(tx, rewind) {
- // Generate the genesis block from the block, transaction and prestate data
- var block = eth.getBlock(eth.getTransaction(tx).blockHash);
- var genesis = eth.getBlock(block.parentHash);
-
- delete genesis.gasUsed;
- delete genesis.logsBloom;
- delete genesis.parentHash;
- delete genesis.receiptsRoot;
- delete genesis.sha3Uncles;
- delete genesis.size;
- delete genesis.transactions;
- delete genesis.transactionsRoot;
- delete genesis.uncles;
-
- genesis.gasLimit = genesis.gasLimit.toString();
- genesis.number = genesis.number.toString();
- genesis.timestamp = genesis.timestamp.toString();
-
- genesis.alloc = debug.traceTransaction(tx, {tracer: "prestateTracer", rewind: rewind});
- for (var key in genesis.alloc) {
- var nonce = genesis.alloc[key].nonce;
- if (nonce) {
- genesis.alloc[key].nonce = nonce.toString();
- }
- }
- genesis.config = admin.nodeInfo.protocols.eth.config;
-
- // Generate the call trace and produce the test input
- var result = debug.traceTransaction(tx, {tracer: "callTracer", rewind: rewind});
- delete result.time;
-
- console.log(JSON.stringify({
- genesis: genesis,
- context: {
- number: block.number.toString(),
- difficulty: block.difficulty,
- timestamp: block.timestamp.toString(),
- gasLimit: block.gasLimit.toString(),
- miner: block.miner,
- },
- input: eth.getRawTransaction(tx),
- result: result,
- }, null, 2));
-}
-*/
-
// camel converts a snake cased input string into a camel cased output.
func camel(str string) string {
pieces := strings.Split(str, "_")
@@ -71,3 +25,32 @@ func camel(str string) string {
return strings.Join(pieces, "")
}
+
+type callContext struct {
+ Number math.HexOrDecimal64 `json:"number"`
+ Difficulty *math.HexOrDecimal256 `json:"difficulty"`
+ Time math.HexOrDecimal64 `json:"timestamp"`
+ GasLimit math.HexOrDecimal64 `json:"gasLimit"`
+ Miner common.Address `json:"miner"`
+ BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"`
+}
+
+func (c *callContext) toBlockContext(genesis *core.Genesis) vm.BlockContext {
+ context := vm.BlockContext{
+ CanTransfer: core.CanTransfer,
+ Transfer: core.Transfer,
+ Coinbase: c.Miner,
+ BlockNumber: new(big.Int).SetUint64(uint64(c.Number)),
+ Time: uint64(c.Time),
+ Difficulty: (*big.Int)(c.Difficulty),
+ GasLimit: uint64(c.GasLimit),
+ }
+ if genesis.Config.IsLondon(context.BlockNumber) {
+ context.BaseFee = (*big.Int)(c.BaseFee)
+ }
+ if genesis.ExcessBlobGas != nil && genesis.BlobGasUsed != nil {
+ excessBlobGas := eip4844.CalcExcessBlobGas(*genesis.ExcessBlobGas, *genesis.BlobGasUsed)
+ context.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas)
+ }
+ return context
+}
diff --git a/eth/tracers/internal/util.go b/eth/tracers/internal/util.go
new file mode 100644
index 0000000000..347af43d51
--- /dev/null
+++ b/eth/tracers/internal/util.go
@@ -0,0 +1,81 @@
+// Copyright 2023 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 internal
+
+import (
+ "errors"
+ "fmt"
+
+ "github.com/holiman/uint256"
+)
+
+const (
+ memoryPadLimit = 1024 * 1024
+)
+
+// GetMemoryCopyPadded returns offset + size as a new slice.
+// It zero-pads the slice if it extends beyond memory bounds.
+func GetMemoryCopyPadded(m []byte, offset, size int64) ([]byte, error) {
+ if offset < 0 || size < 0 {
+ return nil, errors.New("offset or size must not be negative")
+ }
+ length := int64(len(m))
+ if offset+size < length { // slice fully inside memory
+ return memoryCopy(m, offset, size), nil
+ }
+ paddingNeeded := offset + size - length
+ if paddingNeeded > memoryPadLimit {
+ return nil, fmt.Errorf("reached limit for padding memory slice: %d", paddingNeeded)
+ }
+ cpy := make([]byte, size)
+ if overlap := length - offset; overlap > 0 {
+ copy(cpy, MemoryPtr(m, offset, overlap))
+ }
+ return cpy, nil
+}
+
+func memoryCopy(m []byte, offset, size int64) (cpy []byte) {
+ if size == 0 {
+ return nil
+ }
+
+ if len(m) > int(offset) {
+ cpy = make([]byte, size)
+ copy(cpy, m[offset:offset+size])
+
+ return
+ }
+
+ return
+}
+
+// MemoryPtr returns a pointer to a slice of memory.
+func MemoryPtr(m []byte, offset, size int64) []byte {
+ if size == 0 {
+ return nil
+ }
+
+ if len(m) > int(offset) {
+ return m[offset : offset+size]
+ }
+
+ return nil
+}
+
+// StackBack returns the n'th item in stack
+func StackBack(st []uint256.Int, n int) *uint256.Int {
+ return &st[len(st)-n-1]
+}
diff --git a/eth/tracers/internal/util_test.go b/eth/tracers/internal/util_test.go
new file mode 100644
index 0000000000..6a467314cc
--- /dev/null
+++ b/eth/tracers/internal/util_test.go
@@ -0,0 +1,60 @@
+// Copyright 2023 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 internal
+
+import (
+ "testing"
+
+ "github.com/ethereum/go-ethereum/core/vm"
+)
+
+func TestMemCopying(t *testing.T) {
+ for i, tc := range []struct {
+ memsize int64
+ offset int64
+ size int64
+ wantErr string
+ wantSize int
+ }{
+ {0, 0, 100, "", 100}, // Should pad up to 100
+ {0, 100, 0, "", 0}, // No need to pad (0 size)
+ {100, 50, 100, "", 100}, // Should pad 100-150
+ {100, 50, 5, "", 5}, // Wanted range fully within memory
+ {100, -50, 0, "offset or size must not be negative", 0}, // Error
+ {0, 1, 1024*1024 + 1, "reached limit for padding memory slice: 1048578", 0}, // Error
+ {10, 0, 1024*1024 + 100, "reached limit for padding memory slice: 1048666", 0}, // Error
+
+ } {
+ mem := vm.NewMemory()
+ mem.Resize(uint64(tc.memsize))
+ cpy, err := GetMemoryCopyPadded(mem.Data(), tc.offset, tc.size)
+ if want := tc.wantErr; want != "" {
+ if err == nil {
+ t.Fatalf("test %d: want '%v' have no error", i, want)
+ }
+ if have := err.Error(); want != have {
+ t.Fatalf("test %d: want '%v' have '%v'", i, want, have)
+ }
+ continue
+ }
+ if err != nil {
+ t.Fatalf("test %d: unexpected error: %v", i, err)
+ }
+ if want, have := tc.wantSize, len(cpy); have != want {
+ t.Fatalf("test %d: want %v have %v", i, want, have)
+ }
+ }
+}
diff --git a/eth/tracers/js/goja.go b/eth/tracers/js/goja.go
index 040e900744..b74294d311 100644
--- a/eth/tracers/js/goja.go
+++ b/eth/tracers/js/goja.go
@@ -21,14 +21,19 @@ import (
"errors"
"fmt"
"math/big"
+ "slices"
"github.com/dop251/goja"
+ "github.com/ethereum/go-ethereum/core/tracing"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/eth/tracers"
+ "github.com/ethereum/go-ethereum/eth/tracers/internal"
+ "github.com/holiman/uint256"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/eth/tracers"
jsassets "github.com/ethereum/go-ethereum/eth/tracers/js/internal/tracers"
)
@@ -42,11 +47,9 @@ func init() {
if err != nil {
panic(err)
}
-
- type ctorFn = func(*tracers.Context, json.RawMessage) (tracers.Tracer, error)
-
+ type ctorFn = func(*tracers.Context, json.RawMessage) (*tracers.Tracer, error)
lookup := func(code string) ctorFn {
- return func(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) {
+ return func(ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer, error) {
return newJsTracer(code, ctx, cfg)
}
}
@@ -103,7 +106,7 @@ func fromBuf(vm *goja.Runtime, bufType goja.Value, buf goja.Value, allowString b
// JS functions on the relevant EVM hooks. It uses Goja as its JS engine.
type jsTracer struct {
vm *goja.Runtime
- env *vm.EVM
+ env *tracing.VMContext
toBig toBigFn // Converts a hex string into a JS bigint
toBuf toBufFn // Converts a []byte into a JS buffer
fromBuf fromBufFn // Converts an array, hex string or Uint8Array to a []byte
@@ -111,7 +114,6 @@ type jsTracer struct {
activePrecompiles []common.Address // List of active precompiles at current block
traceStep bool // True if tracer object exposes a `step()` method
traceFrame bool // True if tracer object exposes the `enter()` and `exit()` methods
- gasLimit uint64 // Amount of gas bought for the whole tx
err error // Any error that should stop tracing
obj *goja.Object // Trace object
@@ -141,7 +143,7 @@ type jsTracer struct {
// The methods `result` and `fault` are required to be present.
// The methods `step`, `enter`, and `exit` are optional, but note that
// `enter` and `exit` always go together.
-func newJsTracer(code string, ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) {
+func newJsTracer(code string, ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer, error) {
vm := goja.New()
// By default field names are exported to JS as is, i.e. capitalized.
vm.SetFieldNameMapper(goja.UncapFieldNameMapper())
@@ -235,31 +237,61 @@ func newJsTracer(code string, ctx *tracers.Context, cfg json.RawMessage) (tracer
t.frameResultValue = t.frameResult.setupObject()
t.logValue = t.log.setupObject()
- return t, nil
-}
-
-// CaptureTxStart implements the Tracer interface and is invoked at the beginning of
+ return &tracers.Tracer{
+ Hooks: &tracing.Hooks{
+ OnTxStart: t.OnTxStart,
+ OnTxEnd: t.OnTxEnd,
+ OnEnter: t.OnEnter,
+ OnExit: t.OnExit,
+ OnOpcode: t.OnOpcode,
+ OnFault: t.OnFault,
+ },
+ GetResult: t.GetResult,
+ Stop: t.Stop,
+ }, nil
+}
+
+// OnTxStart implements the Tracer interface and is invoked at the beginning of
// transaction processing.
-func (t *jsTracer) CaptureTxStart(gasLimit uint64) {
- t.gasLimit = gasLimit
+func (t *jsTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
+ t.env = env
+ // Need statedb access for db object
+ db := &dbObj{db: env.StateDB, vm: t.vm, toBig: t.toBig, toBuf: t.toBuf, fromBuf: t.fromBuf}
+ t.dbValue = db.setupObject()
+ // Update list of precompiles based on current block
+ rules := env.ChainConfig.Rules(env.BlockNumber, env.Random != nil, env.Time)
+ t.activePrecompiles = vm.ActivePrecompiles(rules)
+ t.ctx["block"] = t.vm.ToValue(t.env.BlockNumber.Uint64())
+ t.ctx["gas"] = t.vm.ToValue(tx.Gas())
+ gasPriceBig, err := t.toBig(t.vm, env.GasPrice.String())
+ if err != nil {
+ t.err = err
+ return
+ }
+ t.ctx["gasPrice"] = gasPriceBig
}
-// CaptureTxEnd implements the Tracer interface and is invoked at the end of
+// OnTxEnd implements the Tracer interface and is invoked at the end of
// transaction processing.
-func (t *jsTracer) CaptureTxEnd(restGas uint64) {
- t.ctx["gasUsed"] = t.vm.ToValue(t.gasLimit - restGas)
+func (t *jsTracer) OnTxEnd(receipt *types.Receipt, err error) {
+ if t.err != nil {
+ return
+ }
+ if err != nil {
+ // Don't override vm error
+ if _, ok := t.ctx["error"]; !ok {
+ t.ctx["error"] = t.vm.ToValue(err.Error())
+ }
+ return
+ }
+ t.ctx["gasUsed"] = t.vm.ToValue(receipt.GasUsed)
}
-// CaptureStart implements the Tracer interface to initialize the tracing operation.
-func (t *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
- cancel := func(err error) {
- t.err = err
- t.env.Cancel()
+// onStart implements the Tracer interface to initialize the tracing operation.
+func (t *jsTracer) onStart(from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+ if t.err != nil {
+ return
}
- t.env = env
- db := &dbObj{db: env.StateDB, vm: t.vm, toBig: t.toBig, toBuf: t.toBuf, fromBuf: t.fromBuf}
- t.dbValue = db.setupObject()
-
if create {
t.ctx["type"] = t.vm.ToValue("CREATE")
} else {
@@ -267,45 +299,34 @@ func (t *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Addr
}
fromVal, err := t.toBuf(t.vm, from.Bytes())
if err != nil {
- cancel(err)
+ t.err = err
return
}
t.ctx["from"] = fromVal
toVal, err := t.toBuf(t.vm, to.Bytes())
if err != nil {
- cancel(err)
+ t.err = err
return
}
t.ctx["to"] = toVal
inputVal, err := t.toBuf(t.vm, input)
if err != nil {
- cancel(err)
+ t.err = err
return
}
t.ctx["input"] = inputVal
- t.ctx["gas"] = t.vm.ToValue(t.gasLimit)
- gasPriceBig, err := t.toBig(t.vm, env.TxContext.GasPrice.String())
- if err != nil {
- cancel(err)
- return
- }
- t.ctx["gasPrice"] = gasPriceBig
valueBig, err := t.toBig(t.vm, value.String())
if err != nil {
- cancel(err)
+ t.err = err
return
}
t.ctx["value"] = valueBig
- t.ctx["block"] = t.vm.ToValue(env.Context.BlockNumber.Uint64())
- // Update list of precompiles based on current block
- rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time)
- t.activePrecompiles = vm.ActivePrecompiles(rules)
}
-// CaptureState implements the Tracer interface to trace a single step of VM execution.
-func (t *jsTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+// OnOpcode implements the Tracer interface to trace a single step of VM execution.
+func (t *jsTracer) OnOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
if !t.traceStep {
return
}
@@ -315,10 +336,10 @@ func (t *jsTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope
}
log := t.log
- log.op.op = op
- log.memory.memory = scope.Memory
- log.stack.stack = scope.Stack
- log.contract.contract = scope.Contract
+ log.op.op = vm.OpCode(op)
+ log.memory.memory = scope.MemoryData()
+ log.stack.stack = scope.StackData()
+ log.contract.scope = scope
log.pc = pc
log.gas = gas
log.cost = cost
@@ -331,20 +352,23 @@ func (t *jsTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope
}
}
-// CaptureFault implements the Tracer interface to trace an execution fault
-func (t *jsTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
+// OnFault implements the Tracer interface to trace an execution fault
+func (t *jsTracer) OnFault(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, depth int, err error) {
if t.err != nil {
return
}
- // Other log fields have been already set as part of the last CaptureState.
+ // Other log fields have been already set as part of the last OnOpcode.
t.log.err = err
if _, err := t.fault(t.obj, t.logValue, t.dbValue); err != nil {
t.onError("fault", err)
}
}
-// CaptureEnd is called after the call finishes to finalize the tracing.
-func (t *jsTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
+// onEnd is called after the call finishes to finalize the tracing.
+func (t *jsTracer) onEnd(output []byte, gasUsed uint64, err error, reverted bool) {
+ if t.err != nil {
+ return
+ }
if err != nil {
t.ctx["error"] = t.vm.ToValue(err.Error())
}
@@ -356,17 +380,20 @@ func (t *jsTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
t.ctx["output"] = outputVal
}
-// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
-func (t *jsTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
- if !t.traceFrame {
+// OnEnter is called when EVM enters a new scope (via call, create or selfdestruct).
+func (t *jsTracer) OnEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+ if t.err != nil {
return
}
-
- if t.err != nil {
+ if depth == 0 {
+ t.onStart(from, to, vm.OpCode(typ) == vm.CREATE, input, gas, value)
+ return
+ }
+ if !t.traceFrame {
return
}
- t.frame.typ = typ.String()
+ t.frame.typ = vm.OpCode(typ).String()
t.frame.from = from
t.frame.to = to
t.frame.input = common.CopyBytes(input)
@@ -382,9 +409,16 @@ func (t *jsTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Ad
}
}
-// CaptureExit is called when EVM exits a scope, even if the scope didn't
+// OnExit is called when EVM exits a scope, even if the scope didn't
// execute any code.
-func (t *jsTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
+func (t *jsTracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
+ if t.err != nil {
+ return
+ }
+ if depth == 0 {
+ t.onEnd(output, gasUsed, err, reverted)
+ return
+ }
if !t.traceFrame {
return
}
@@ -400,6 +434,9 @@ func (t *jsTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
// GetResult calls the Javascript 'result' function and returns its value, or any accumulated error
func (t *jsTracer) GetResult() (json.RawMessage, error) {
+ if t.err != nil {
+ return nil, t.err
+ }
ctx := t.vm.ToValue(t.ctx)
res, err := t.result(t.obj, ctx, t.dbValue)
@@ -412,8 +449,7 @@ func (t *jsTracer) GetResult() (json.RawMessage, error) {
if err != nil {
return nil, err
}
-
- return json.RawMessage(encoded), t.err
+ return encoded, t.err
}
// Stop terminates execution of the tracer at the first opportune moment.
@@ -426,9 +462,6 @@ func (t *jsTracer) Stop(err error) {
// execution.
func (t *jsTracer) onError(context string, err error) {
t.err = wrapError(context, err)
- // `env` is set on CaptureStart which comes before any JS execution.
- // So it should be non-nil.
- t.env.Cancel()
}
func wrapError(context string, err error) error {
@@ -536,15 +569,7 @@ func (t *jsTracer) setBuiltinFunctions() {
vm.Interrupt(err)
return false
}
-
- addr := common.BytesToAddress(a)
- for _, p := range t.activePrecompiles {
- if p == addr {
- return true
- }
- }
-
- return false
+ return slices.Contains(t.activePrecompiles, common.BytesToAddress(a))
})
vm.Set("slice", func(slice goja.Value, start, end int64) goja.Value {
b, err := t.fromBuf(vm, slice, false)
@@ -630,7 +655,7 @@ func (o *opObj) setupObject() *goja.Object {
}
type memoryObj struct {
- memory *vm.Memory
+ memory []byte
vm *goja.Runtime
toBig toBigFn
toBuf toBufFn
@@ -662,9 +687,7 @@ func (mo *memoryObj) slice(begin, end int64) ([]byte, error) {
if end < begin || begin < 0 {
return nil, fmt.Errorf("tracer accessed out of bound memory: offset %d, end %d", begin, end)
}
-
- slice, err := tracers.GetMemoryCopyPadded(mo.memory, begin, end-begin)
-
+ slice, err := internal.GetMemoryCopyPadded(mo.memory, begin, end-begin)
if err != nil {
return nil, err
}
@@ -691,28 +714,26 @@ func (mo *memoryObj) GetUint(addr int64) goja.Value {
// getUint returns the 32 bytes at the specified address interpreted as a uint.
func (mo *memoryObj) getUint(addr int64) (*big.Int, error) {
- if mo.memory.Len() < int(addr)+32 || addr < 0 {
- return nil, fmt.Errorf("tracer accessed out of bound memory: available %d, offset %d, size %d", mo.memory.Len(), addr, 32)
+ if len(mo.memory) < int(addr)+32 || addr < 0 {
+ return nil, fmt.Errorf("tracer accessed out of bound memory: available %d, offset %d, size %d", len(mo.memory), addr, 32)
}
-
- return new(big.Int).SetBytes(mo.memory.GetPtr(addr, 32)), nil
+ return new(big.Int).SetBytes(internal.MemoryPtr(mo.memory, addr, 32)), nil
}
func (mo *memoryObj) Length() int {
- return mo.memory.Len()
+ return len(mo.memory)
}
-func (m *memoryObj) setupObject() *goja.Object {
- o := m.vm.NewObject()
- _ = o.Set("slice", m.vm.ToValue(m.Slice))
- _ = o.Set("getUint", m.vm.ToValue(m.GetUint))
- _ = o.Set("length", m.vm.ToValue(m.Length))
-
+func (mo *memoryObj) setupObject() *goja.Object {
+ o := mo.vm.NewObject()
+ o.Set("slice", mo.vm.ToValue(mo.Slice))
+ o.Set("getUint", mo.vm.ToValue(mo.GetUint))
+ o.Set("length", mo.vm.ToValue(mo.Length))
return o
}
type stackObj struct {
- stack *vm.Stack
+ stack []uint256.Int
vm *goja.Runtime
toBig toBigFn
}
@@ -736,15 +757,14 @@ func (s *stackObj) Peek(idx int) goja.Value {
// peek returns the nth-from-the-top element of the stack.
func (s *stackObj) peek(idx int) (*big.Int, error) {
- if len(s.stack.Data()) <= idx || idx < 0 {
- return nil, fmt.Errorf("tracer accessed out of bound stack: size %d, index %d", len(s.stack.Data()), idx)
+ if len(s.stack) <= idx || idx < 0 {
+ return nil, fmt.Errorf("tracer accessed out of bound stack: size %d, index %d", len(s.stack), idx)
}
-
- return s.stack.Back(idx).ToBig(), nil
+ return internal.StackBack(s.stack, idx).ToBig(), nil
}
func (s *stackObj) Length() int {
- return len(s.stack.Data())
+ return len(s.stack)
}
func (s *stackObj) setupObject() *goja.Object {
@@ -756,7 +776,7 @@ func (s *stackObj) setupObject() *goja.Object {
}
type dbObj struct {
- db vm.StateDB
+ db tracing.StateDB
vm *goja.Runtime
toBig toBigFn
toBuf toBufFn
@@ -864,14 +884,14 @@ func (do *dbObj) setupObject() *goja.Object {
}
type contractObj struct {
- contract *vm.Contract
- vm *goja.Runtime
- toBig toBigFn
- toBuf toBufFn
+ scope tracing.OpContext
+ vm *goja.Runtime
+ toBig toBigFn
+ toBuf toBufFn
}
func (co *contractObj) GetCaller() goja.Value {
- caller := co.contract.Caller().Bytes()
+ caller := co.scope.Caller().Bytes()
res, err := co.toBuf(co.vm, caller)
if err != nil {
@@ -883,7 +903,7 @@ func (co *contractObj) GetCaller() goja.Value {
}
func (co *contractObj) GetAddress() goja.Value {
- addr := co.contract.Address().Bytes()
+ addr := co.scope.Address().Bytes()
res, err := co.toBuf(co.vm, addr)
if err != nil {
@@ -895,7 +915,7 @@ func (co *contractObj) GetAddress() goja.Value {
}
func (co *contractObj) GetValue() goja.Value {
- value := co.contract.Value()
+ value := co.scope.CallValue()
res, err := co.toBig(co.vm, value.String())
if err != nil {
@@ -907,7 +927,7 @@ func (co *contractObj) GetValue() goja.Value {
}
func (co *contractObj) GetInput() goja.Value {
- input := common.CopyBytes(co.contract.Input)
+ input := common.CopyBytes(co.scope.CallInput())
res, err := co.toBuf(co.vm, input)
if err != nil {
@@ -918,13 +938,12 @@ func (co *contractObj) GetInput() goja.Value {
return res
}
-func (c *contractObj) setupObject() *goja.Object {
- o := c.vm.NewObject()
- _ = o.Set("getCaller", c.vm.ToValue(c.GetCaller))
- _ = o.Set("getAddress", c.vm.ToValue(c.GetAddress))
- _ = o.Set("getValue", c.vm.ToValue(c.GetValue))
- _ = o.Set("getInput", c.vm.ToValue(c.GetInput))
-
+func (co *contractObj) setupObject() *goja.Object {
+ o := co.vm.NewObject()
+ o.Set("getCaller", co.vm.ToValue(co.GetCaller))
+ o.Set("getAddress", co.vm.ToValue(co.GetAddress))
+ o.Set("getValue", co.vm.ToValue(co.GetValue))
+ o.Set("getInput", co.vm.ToValue(co.GetInput))
return o
}
diff --git a/eth/tracers/js/tracer_test.go b/eth/tracers/js/tracer_test.go
index d3f7a79cbb..394029f8cf 100644
--- a/eth/tracers/js/tracer_test.go
+++ b/eth/tracers/js/tracer_test.go
@@ -26,9 +26,11 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
type account struct{}
@@ -37,9 +39,9 @@ func (account) SubBalance(amount *big.Int) {}
func (account) AddBalance(amount *big.Int) {}
func (account) SetAddress(common.Address) {}
func (account) Value() *big.Int { return nil }
-func (account) SetBalance(*big.Int) {}
+func (account) SetBalance(*uint256.Int) {}
func (account) SetNonce(uint64) {}
-func (account) Balance() *big.Int { return nil }
+func (account) Balance() *uint256.Int { return nil }
func (account) Address() common.Address { return common.Address{} }
func (account) SetCode(common.Hash, []byte) {}
func (account) ForEachStorage(cb func(key, value common.Hash) bool) {}
@@ -48,8 +50,8 @@ type dummyStatedb struct {
state.StateDB
}
-func (*dummyStatedb) GetRefund() uint64 { return 1337 }
-func (*dummyStatedb) GetBalance(addr common.Address) *big.Int { return new(big.Int) }
+func (*dummyStatedb) GetRefund() uint64 { return 1337 }
+func (*dummyStatedb) GetBalance(addr common.Address) *uint256.Int { return new(uint256.Int) }
type vmContext struct {
blockCtx vm.BlockContext
@@ -60,12 +62,12 @@ func testCtx() *vmContext {
return &vmContext{blockCtx: vm.BlockContext{BlockNumber: big.NewInt(1)}, txCtx: vm.TxContext{GasPrice: big.NewInt(100000)}}
}
-func runTrace(tracer tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainConfig, contractCode []byte) (json.RawMessage, error) {
+func runTrace(tracer *tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainConfig, contractCode []byte) (json.RawMessage, error) {
var (
- env = vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, chaincfg, vm.Config{Tracer: tracer})
+ env = vm.NewEVM(vmctx.blockCtx, vmctx.txCtx, &dummyStatedb{}, chaincfg, vm.Config{Tracer: tracer.Hooks})
gasLimit uint64 = 31000
startGas uint64 = 10000
- value = big.NewInt(0)
+ value = uint256.NewInt(0)
contract = vm.NewContract(account{}, account{}, value, startGas)
)
@@ -75,13 +77,12 @@ func runTrace(tracer tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainCon
contract.Code = contractCode
}
- tracer.CaptureTxStart(gasLimit)
- tracer.CaptureStart(env, contract.Caller(), contract.Address(), false, []byte{}, startGas, value)
+ tracer.OnTxStart(env.GetVMContext(), types.NewTx(&types.LegacyTx{Gas: gasLimit}), contract.Caller())
+ tracer.OnEnter(0, byte(vm.CALL), contract.Caller(), contract.Address(), []byte{}, startGas, value.ToBig())
ret, err := env.Interpreter().Run(contract, []byte{}, false, nil)
- tracer.CaptureEnd(ret, startGas-contract.Gas, err)
+ tracer.OnExit(0, ret, startGas-contract.Gas, err, true)
// Rest gas assumes no refund
- tracer.CaptureTxEnd(contract.Gas)
-
+ tracer.OnTxEnd(&types.Receipt{GasUsed: gasLimit - contract.Gas}, nil)
if err != nil {
return nil, err
}
@@ -190,18 +191,16 @@ func TestHaltBetweenSteps(t *testing.T) {
if err != nil {
t.Fatal(err)
}
-
- env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: tracer})
scope := &vm.ScopeContext{
- Contract: vm.NewContract(&account{}, &account{}, big.NewInt(0), 0),
+ Contract: vm.NewContract(&account{}, &account{}, uint256.NewInt(0), 0),
}
-
- tracer.CaptureStart(env, common.Address{}, common.Address{}, false, []byte{}, 0, big.NewInt(0))
- tracer.CaptureState(0, 0, 0, 0, scope, nil, 0, nil)
-
+ env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: tracer.Hooks})
+ tracer.OnTxStart(env.GetVMContext(), types.NewTx(&types.LegacyTx{}), common.Address{})
+ tracer.OnEnter(0, byte(vm.CALL), common.Address{}, common.Address{}, []byte{}, 0, big.NewInt(0))
+ tracer.OnOpcode(0, 0, 0, 0, scope, nil, 0, nil)
timeout := errors.New("stahp")
tracer.Stop(timeout)
- tracer.CaptureState(0, 0, 0, 0, scope, nil, 0, nil)
+ tracer.OnOpcode(0, 0, 0, 0, scope, nil, 0, nil)
if _, err := tracer.GetResult(); !strings.Contains(err.Error(), timeout.Error()) {
t.Errorf("Expected timeout error, got %v", err)
@@ -218,11 +217,10 @@ func TestNoStepExec(t *testing.T) {
if err != nil {
t.Fatal(err)
}
-
- env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(100)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: tracer})
- tracer.CaptureStart(env, common.Address{}, common.Address{}, false, []byte{}, 1000, big.NewInt(0))
- tracer.CaptureEnd(nil, 0, nil)
-
+ env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(100)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: tracer.Hooks})
+ tracer.OnTxStart(env.GetVMContext(), types.NewTx(&types.LegacyTx{}), common.Address{})
+ tracer.OnEnter(0, byte(vm.CALL), common.Address{}, common.Address{}, []byte{}, 1000, big.NewInt(0))
+ tracer.OnExit(0, nil, 0, nil, false)
ret, err := tracer.GetResult()
if err != nil {
t.Fatal(err)
@@ -297,10 +295,10 @@ func TestEnterExit(t *testing.T) {
}
scope := &vm.ScopeContext{
- Contract: vm.NewContract(&account{}, &account{}, big.NewInt(0), 0),
+ Contract: vm.NewContract(&account{}, &account{}, uint256.NewInt(0), 0),
}
- tracer.CaptureEnter(vm.CALL, scope.Contract.Caller(), scope.Contract.Address(), []byte{}, 1000, new(big.Int))
- tracer.CaptureExit([]byte{}, 400, nil)
+ tracer.OnEnter(1, byte(vm.CALL), scope.Contract.Caller(), scope.Contract.Address(), []byte{}, 1000, new(big.Int))
+ tracer.OnExit(1, []byte{}, 400, nil, false)
have, err := tracer.GetResult()
if err != nil {
diff --git a/eth/tracers/live.go b/eth/tracers/live.go
new file mode 100644
index 0000000000..ffb2303af4
--- /dev/null
+++ b/eth/tracers/live.go
@@ -0,0 +1,31 @@
+package tracers
+
+import (
+ "encoding/json"
+ "errors"
+
+ "github.com/ethereum/go-ethereum/core/tracing"
+)
+
+type ctorFunc func(config json.RawMessage) (*tracing.Hooks, error)
+
+// LiveDirectory is the collection of tracers which can be used
+// during normal block import operations.
+var LiveDirectory = liveDirectory{elems: make(map[string]ctorFunc)}
+
+type liveDirectory struct {
+ elems map[string]ctorFunc
+}
+
+// Register registers a tracer constructor by name.
+func (d *liveDirectory) Register(name string, f ctorFunc) {
+ d.elems[name] = f
+}
+
+// New instantiates a tracer by name.
+func (d *liveDirectory) New(name string, config json.RawMessage) (*tracing.Hooks, error) {
+ if f, ok := d.elems[name]; ok {
+ return f(config)
+ }
+ return nil, errors.New("not found")
+}
diff --git a/eth/tracers/live/gen_supplyinfoburn.go b/eth/tracers/live/gen_supplyinfoburn.go
new file mode 100644
index 0000000000..d01eda3975
--- /dev/null
+++ b/eth/tracers/live/gen_supplyinfoburn.go
@@ -0,0 +1,49 @@
+// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
+
+package live
+
+import (
+ "encoding/json"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common/hexutil"
+)
+
+var _ = (*supplyInfoBurnMarshaling)(nil)
+
+// MarshalJSON marshals as JSON.
+func (s supplyInfoBurn) MarshalJSON() ([]byte, error) {
+ type supplyInfoBurn struct {
+ EIP1559 *hexutil.Big `json:"1559,omitempty"`
+ Blob *hexutil.Big `json:"blob,omitempty"`
+ Misc *hexutil.Big `json:"misc,omitempty"`
+ }
+ var enc supplyInfoBurn
+ enc.EIP1559 = (*hexutil.Big)(s.EIP1559)
+ enc.Blob = (*hexutil.Big)(s.Blob)
+ enc.Misc = (*hexutil.Big)(s.Misc)
+ return json.Marshal(&enc)
+}
+
+// UnmarshalJSON unmarshals from JSON.
+func (s *supplyInfoBurn) UnmarshalJSON(input []byte) error {
+ type supplyInfoBurn struct {
+ EIP1559 *hexutil.Big `json:"1559,omitempty"`
+ Blob *hexutil.Big `json:"blob,omitempty"`
+ Misc *hexutil.Big `json:"misc,omitempty"`
+ }
+ var dec supplyInfoBurn
+ if err := json.Unmarshal(input, &dec); err != nil {
+ return err
+ }
+ if dec.EIP1559 != nil {
+ s.EIP1559 = (*big.Int)(dec.EIP1559)
+ }
+ if dec.Blob != nil {
+ s.Blob = (*big.Int)(dec.Blob)
+ }
+ if dec.Misc != nil {
+ s.Misc = (*big.Int)(dec.Misc)
+ }
+ return nil
+}
diff --git a/eth/tracers/live/gen_supplyinfoissuance.go b/eth/tracers/live/gen_supplyinfoissuance.go
new file mode 100644
index 0000000000..e2536ee325
--- /dev/null
+++ b/eth/tracers/live/gen_supplyinfoissuance.go
@@ -0,0 +1,49 @@
+// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
+
+package live
+
+import (
+ "encoding/json"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common/hexutil"
+)
+
+var _ = (*supplyInfoIssuanceMarshaling)(nil)
+
+// MarshalJSON marshals as JSON.
+func (s supplyInfoIssuance) MarshalJSON() ([]byte, error) {
+ type supplyInfoIssuance struct {
+ GenesisAlloc *hexutil.Big `json:"genesisAlloc,omitempty"`
+ Reward *hexutil.Big `json:"reward,omitempty"`
+ Withdrawals *hexutil.Big `json:"withdrawals,omitempty"`
+ }
+ var enc supplyInfoIssuance
+ enc.GenesisAlloc = (*hexutil.Big)(s.GenesisAlloc)
+ enc.Reward = (*hexutil.Big)(s.Reward)
+ enc.Withdrawals = (*hexutil.Big)(s.Withdrawals)
+ return json.Marshal(&enc)
+}
+
+// UnmarshalJSON unmarshals from JSON.
+func (s *supplyInfoIssuance) UnmarshalJSON(input []byte) error {
+ type supplyInfoIssuance struct {
+ GenesisAlloc *hexutil.Big `json:"genesisAlloc,omitempty"`
+ Reward *hexutil.Big `json:"reward,omitempty"`
+ Withdrawals *hexutil.Big `json:"withdrawals,omitempty"`
+ }
+ var dec supplyInfoIssuance
+ if err := json.Unmarshal(input, &dec); err != nil {
+ return err
+ }
+ if dec.GenesisAlloc != nil {
+ s.GenesisAlloc = (*big.Int)(dec.GenesisAlloc)
+ }
+ if dec.Reward != nil {
+ s.Reward = (*big.Int)(dec.Reward)
+ }
+ if dec.Withdrawals != nil {
+ s.Withdrawals = (*big.Int)(dec.Withdrawals)
+ }
+ return nil
+}
diff --git a/eth/tracers/live/noop.go b/eth/tracers/live/noop.go
new file mode 100644
index 0000000000..7433c28840
--- /dev/null
+++ b/eth/tracers/live/noop.go
@@ -0,0 +1,96 @@
+package live
+
+import (
+ "encoding/json"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/tracing"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/eth/tracers"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+func init() {
+ tracers.LiveDirectory.Register("noop", newNoopTracer)
+}
+
+// noop is a no-op live tracer. It's there to
+// catch changes in the tracing interface, as well as
+// for testing live tracing performance. Can be removed
+// as soon as we have a real live tracer.
+type noop struct{}
+
+func newNoopTracer(_ json.RawMessage) (*tracing.Hooks, error) {
+ t := &noop{}
+ return &tracing.Hooks{
+ OnTxStart: t.OnTxStart,
+ OnTxEnd: t.OnTxEnd,
+ OnEnter: t.OnEnter,
+ OnExit: t.OnExit,
+ OnOpcode: t.OnOpcode,
+ OnFault: t.OnFault,
+ OnGasChange: t.OnGasChange,
+ OnBlockchainInit: t.OnBlockchainInit,
+ OnBlockStart: t.OnBlockStart,
+ OnBlockEnd: t.OnBlockEnd,
+ OnSkippedBlock: t.OnSkippedBlock,
+ OnGenesisBlock: t.OnGenesisBlock,
+ OnBalanceChange: t.OnBalanceChange,
+ OnNonceChange: t.OnNonceChange,
+ OnCodeChange: t.OnCodeChange,
+ OnStorageChange: t.OnStorageChange,
+ OnLog: t.OnLog,
+ }, nil
+}
+
+func (t *noop) OnOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
+}
+
+func (t *noop) OnFault(pc uint64, op byte, gas, cost uint64, _ tracing.OpContext, depth int, err error) {
+}
+
+func (t *noop) OnEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+}
+
+func (t *noop) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
+}
+
+func (t *noop) OnTxStart(vm *tracing.VMContext, tx *types.Transaction, from common.Address) {
+}
+
+func (t *noop) OnTxEnd(receipt *types.Receipt, err error) {
+}
+
+func (t *noop) OnBlockStart(ev tracing.BlockEvent) {
+}
+
+func (t *noop) OnBlockEnd(err error) {
+}
+
+func (t *noop) OnSkippedBlock(ev tracing.BlockEvent) {}
+
+func (t *noop) OnBlockchainInit(chainConfig *params.ChainConfig) {
+}
+
+func (t *noop) OnGenesisBlock(b *types.Block, alloc types.GenesisAlloc) {
+}
+
+func (t *noop) OnBalanceChange(a common.Address, prev, new *big.Int, reason tracing.BalanceChangeReason) {
+}
+
+func (t *noop) OnNonceChange(a common.Address, prev, new uint64) {
+}
+
+func (t *noop) OnCodeChange(a common.Address, prevCodeHash common.Hash, prev []byte, codeHash common.Hash, code []byte) {
+}
+
+func (t *noop) OnStorageChange(a common.Address, k, prev, new common.Hash) {
+}
+
+func (t *noop) OnLog(l *types.Log) {
+
+}
+
+func (t *noop) OnGasChange(old, new uint64, reason tracing.GasChangeReason) {
+}
diff --git a/eth/tracers/live/supply.go b/eth/tracers/live/supply.go
new file mode 100644
index 0000000000..1adcacbb27
--- /dev/null
+++ b/eth/tracers/live/supply.go
@@ -0,0 +1,308 @@
+package live
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "math/big"
+ "path/filepath"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
+ "github.com/ethereum/go-ethereum/core/tracing"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/eth/tracers"
+ "github.com/ethereum/go-ethereum/log"
+ lumberjack "gopkg.in/natefinch/lumberjack.v2"
+)
+
+func init() {
+ tracers.LiveDirectory.Register("supply", newSupply)
+}
+
+type supplyInfoIssuance struct {
+ GenesisAlloc *big.Int `json:"genesisAlloc,omitempty"`
+ Reward *big.Int `json:"reward,omitempty"`
+ Withdrawals *big.Int `json:"withdrawals,omitempty"`
+}
+
+//go:generate go run github.com/fjl/gencodec -type supplyInfoIssuance -field-override supplyInfoIssuanceMarshaling -out gen_supplyinfoissuance.go
+type supplyInfoIssuanceMarshaling struct {
+ GenesisAlloc *hexutil.Big
+ Reward *hexutil.Big
+ Withdrawals *hexutil.Big
+}
+
+type supplyInfoBurn struct {
+ EIP1559 *big.Int `json:"1559,omitempty"`
+ Blob *big.Int `json:"blob,omitempty"`
+ Misc *big.Int `json:"misc,omitempty"`
+}
+
+//go:generate go run github.com/fjl/gencodec -type supplyInfoBurn -field-override supplyInfoBurnMarshaling -out gen_supplyinfoburn.go
+type supplyInfoBurnMarshaling struct {
+ EIP1559 *hexutil.Big
+ Blob *hexutil.Big
+ Misc *hexutil.Big
+}
+
+type supplyInfo struct {
+ Issuance *supplyInfoIssuance `json:"issuance,omitempty"`
+ Burn *supplyInfoBurn `json:"burn,omitempty"`
+
+ // Block info
+ Number uint64 `json:"blockNumber"`
+ Hash common.Hash `json:"hash"`
+ ParentHash common.Hash `json:"parentHash"`
+}
+
+type supplyTxCallstack struct {
+ calls []supplyTxCallstack
+ burn *big.Int
+}
+
+type supply struct {
+ delta supplyInfo
+ txCallstack []supplyTxCallstack // Callstack for current transaction
+ logger *lumberjack.Logger
+}
+
+type supplyTracerConfig struct {
+ Path string `json:"path"` // Path to the directory where the tracer logs will be stored
+ MaxSize int `json:"maxSize"` // MaxSize is the maximum size in megabytes of the tracer log file before it gets rotated. It defaults to 100 megabytes.
+}
+
+func newSupply(cfg json.RawMessage) (*tracing.Hooks, error) {
+ var config supplyTracerConfig
+ if cfg != nil {
+ if err := json.Unmarshal(cfg, &config); err != nil {
+ return nil, fmt.Errorf("failed to parse config: %v", err)
+ }
+ }
+ if config.Path == "" {
+ return nil, errors.New("supply tracer output path is required")
+ }
+
+ // Store traces in a rotating file
+ logger := &lumberjack.Logger{
+ Filename: filepath.Join(config.Path, "supply.jsonl"),
+ }
+ if config.MaxSize > 0 {
+ logger.MaxSize = config.MaxSize
+ }
+
+ t := &supply{
+ delta: newSupplyInfo(),
+ logger: logger,
+ }
+ return &tracing.Hooks{
+ OnBlockStart: t.OnBlockStart,
+ OnBlockEnd: t.OnBlockEnd,
+ OnGenesisBlock: t.OnGenesisBlock,
+ OnTxStart: t.OnTxStart,
+ OnBalanceChange: t.OnBalanceChange,
+ OnEnter: t.OnEnter,
+ OnExit: t.OnExit,
+ OnClose: t.OnClose,
+ }, nil
+}
+
+func newSupplyInfo() supplyInfo {
+ return supplyInfo{
+ Issuance: &supplyInfoIssuance{
+ GenesisAlloc: big.NewInt(0),
+ Reward: big.NewInt(0),
+ Withdrawals: big.NewInt(0),
+ },
+ Burn: &supplyInfoBurn{
+ EIP1559: big.NewInt(0),
+ Blob: big.NewInt(0),
+ Misc: big.NewInt(0),
+ },
+
+ Number: 0,
+ Hash: common.Hash{},
+ ParentHash: common.Hash{},
+ }
+}
+
+func (s *supply) resetDelta() {
+ s.delta = newSupplyInfo()
+}
+
+func (s *supply) OnBlockStart(ev tracing.BlockEvent) {
+ s.resetDelta()
+
+ s.delta.Number = ev.Block.NumberU64()
+ s.delta.Hash = ev.Block.Hash()
+ s.delta.ParentHash = ev.Block.ParentHash()
+
+ // Calculate Burn for this block
+ if ev.Block.BaseFee() != nil {
+ burn := new(big.Int).Mul(new(big.Int).SetUint64(ev.Block.GasUsed()), ev.Block.BaseFee())
+ s.delta.Burn.EIP1559 = burn
+ }
+ // Blob burnt gas
+ if blobGas := ev.Block.BlobGasUsed(); blobGas != nil && *blobGas > 0 && ev.Block.ExcessBlobGas() != nil {
+ var (
+ excess = *ev.Block.ExcessBlobGas()
+ baseFee = eip4844.CalcBlobFee(excess)
+ burn = new(big.Int).Mul(new(big.Int).SetUint64(*blobGas), baseFee)
+ )
+ s.delta.Burn.Blob = burn
+ }
+}
+
+func (s *supply) OnBlockEnd(err error) {
+ s.write(s.delta)
+}
+
+func (s *supply) OnGenesisBlock(b *types.Block, alloc types.GenesisAlloc) {
+ s.resetDelta()
+
+ s.delta.Number = b.NumberU64()
+ s.delta.Hash = b.Hash()
+ s.delta.ParentHash = b.ParentHash()
+
+ // Initialize supply with total allocation in genesis block
+ for _, account := range alloc {
+ s.delta.Issuance.GenesisAlloc.Add(s.delta.Issuance.GenesisAlloc, account.Balance)
+ }
+
+ s.write(s.delta)
+}
+
+func (s *supply) OnBalanceChange(a common.Address, prevBalance, newBalance *big.Int, reason tracing.BalanceChangeReason) {
+ diff := new(big.Int).Sub(newBalance, prevBalance)
+
+ // NOTE: don't handle "BalanceIncreaseGenesisBalance" because it is handled in OnGenesisBlock
+ switch reason {
+ case tracing.BalanceIncreaseRewardMineUncle:
+ case tracing.BalanceIncreaseRewardMineBlock:
+ s.delta.Issuance.Reward.Add(s.delta.Issuance.Reward, diff)
+ case tracing.BalanceIncreaseWithdrawal:
+ s.delta.Issuance.Withdrawals.Add(s.delta.Issuance.Withdrawals, diff)
+ case tracing.BalanceDecreaseSelfdestructBurn:
+ // BalanceDecreaseSelfdestructBurn is non-reversible as it happens
+ // at the end of the transaction.
+ s.delta.Burn.Misc.Sub(s.delta.Burn.Misc, diff)
+ default:
+ return
+ }
+}
+
+func (s *supply) OnTxStart(vm *tracing.VMContext, tx *types.Transaction, from common.Address) {
+ s.txCallstack = make([]supplyTxCallstack, 0, 1)
+}
+
+// internalTxsHandler handles internal transactions burned amount
+func (s *supply) internalTxsHandler(call *supplyTxCallstack) {
+ // Handle Burned amount
+ if call.burn != nil {
+ s.delta.Burn.Misc.Add(s.delta.Burn.Misc, call.burn)
+ }
+
+ // Recursively handle internal calls
+ for _, call := range call.calls {
+ callCopy := call
+ s.internalTxsHandler(&callCopy)
+ }
+}
+
+func (s *supply) OnEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+ call := supplyTxCallstack{
+ calls: make([]supplyTxCallstack, 0),
+ }
+
+ // This is a special case of burned amount which has to be handled here
+ // which happens when type == selfdestruct and from == to.
+ if vm.OpCode(typ) == vm.SELFDESTRUCT && from == to && value.Cmp(common.Big0) == 1 {
+ call.burn = value
+ }
+
+ // Append call to the callstack, so we can fill the details in CaptureExit
+ s.txCallstack = append(s.txCallstack, call)
+}
+
+func (s *supply) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
+ if depth == 0 {
+ // No need to handle Burned amount if transaction is reverted
+ if !reverted {
+ s.internalTxsHandler(&s.txCallstack[0])
+ }
+ return
+ }
+
+ size := len(s.txCallstack)
+ if size <= 1 {
+ return
+ }
+ // Pop call
+ call := s.txCallstack[size-1]
+ s.txCallstack = s.txCallstack[:size-1]
+ size -= 1
+
+ // In case of a revert, we can drop the call and all its subcalls.
+ // Caution, that this has to happen after popping the call from the stack.
+ if reverted {
+ return
+ }
+ s.txCallstack[size-1].calls = append(s.txCallstack[size-1].calls, call)
+}
+
+func (s *supply) OnClose() {
+ if err := s.logger.Close(); err != nil {
+ log.Warn("failed to close supply tracer log file", "error", err)
+ }
+}
+
+func (s *supply) write(data any) {
+ supply, ok := data.(supplyInfo)
+ if !ok {
+ log.Warn("failed to cast supply tracer data on write to log file")
+ return
+ }
+
+ // Remove empty fields
+ if supply.Issuance.GenesisAlloc.Sign() == 0 {
+ supply.Issuance.GenesisAlloc = nil
+ }
+
+ if supply.Issuance.Reward.Sign() == 0 {
+ supply.Issuance.Reward = nil
+ }
+
+ if supply.Issuance.Withdrawals.Sign() == 0 {
+ supply.Issuance.Withdrawals = nil
+ }
+
+ if supply.Issuance.GenesisAlloc == nil && supply.Issuance.Reward == nil && supply.Issuance.Withdrawals == nil {
+ supply.Issuance = nil
+ }
+
+ if supply.Burn.EIP1559.Sign() == 0 {
+ supply.Burn.EIP1559 = nil
+ }
+
+ if supply.Burn.Blob.Sign() == 0 {
+ supply.Burn.Blob = nil
+ }
+
+ if supply.Burn.Misc.Sign() == 0 {
+ supply.Burn.Misc = nil
+ }
+
+ if supply.Burn.EIP1559 == nil && supply.Burn.Blob == nil && supply.Burn.Misc == nil {
+ supply.Burn = nil
+ }
+
+ out, _ := json.Marshal(supply)
+ if _, err := s.logger.Write(out); err != nil {
+ log.Warn("failed to write to supply tracer log file", "error", err)
+ }
+ if _, err := s.logger.Write([]byte{'\n'}); err != nil {
+ log.Warn("failed to write to supply tracer log file", "error", err)
+ }
+}
diff --git a/eth/tracers/logger/access_list_tracer.go b/eth/tracers/logger/access_list_tracer.go
index 766a800618..0f150ae005 100644
--- a/eth/tracers/logger/access_list_tracer.go
+++ b/eth/tracers/logger/access_list_tracer.go
@@ -17,9 +17,10 @@
package logger
import (
- "math/big"
+ "maps"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
)
@@ -72,23 +73,15 @@ func (al accessList) equal(other accessList) bool {
// Accounts match, cross reference the storage slots too
for addr, slots := range al {
otherslots := other[addr]
-
- if len(slots) != len(otherslots) {
+ if !maps.Equal(slots, otherslots) {
return false
}
- // Given that len(slots) == len(otherslots), we only need to check that
- // all the items from slots are in otherslots.
- for hash := range slots {
- if _, ok := otherslots[hash]; !ok {
- return false
- }
- }
}
return true
}
-// accesslist converts the accesslist to a types.AccessList.
+// accessList converts the accesslist to a types.AccessList.
func (al accessList) accessList() types.AccessList {
acl := make(types.AccessList, 0, len(al))
@@ -140,18 +133,20 @@ func NewAccessListTracer(acl types.AccessList, from, to common.Address, precompi
}
}
-func (a *AccessListTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+func (a *AccessListTracer) Hooks() *tracing.Hooks {
+ return &tracing.Hooks{
+ OnOpcode: a.OnOpcode,
+ }
}
-// CaptureState captures all opcodes that touch storage or addresses and adds them to the accesslist.
-func (a *AccessListTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
- stack := scope.Stack
- stackData := stack.Data()
+// OnOpcode captures all opcodes that touch storage or addresses and adds them to the accesslist.
+func (a *AccessListTracer) OnOpcode(pc uint64, opcode byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
+ stackData := scope.StackData()
stackLen := len(stackData)
-
+ op := vm.OpCode(opcode)
if (op == vm.SLOAD || op == vm.SSTORE) && stackLen >= 1 {
slot := common.Hash(stackData[stackLen-1].Bytes32())
- a.list.addSlot(scope.Contract.Address(), slot)
+ a.list.addSlot(scope.Address(), slot)
}
if (op == vm.EXTCODECOPY || op == vm.EXTCODEHASH || op == vm.EXTCODESIZE || op == vm.BALANCE || op == vm.SELFDESTRUCT) && stackLen >= 1 {
@@ -169,20 +164,6 @@ func (a *AccessListTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint6
}
}
-func (*AccessListTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
-}
-
-func (*AccessListTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {}
-
-func (*AccessListTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
-}
-
-func (*AccessListTracer) CaptureExit(output []byte, gasUsed uint64, err error) {}
-
-func (*AccessListTracer) CaptureTxStart(gasLimit uint64) {}
-
-func (*AccessListTracer) CaptureTxEnd(restGas uint64) {}
-
// AccessList returns the current accesslist maintained by the tracer.
func (a *AccessListTracer) AccessList() types.AccessList {
return a.list.accessList()
diff --git a/eth/tracers/logger/gen_callframe.go b/eth/tracers/logger/gen_callframe.go
new file mode 100644
index 0000000000..b7b2cc2881
--- /dev/null
+++ b/eth/tracers/logger/gen_callframe.go
@@ -0,0 +1,65 @@
+// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
+
+package logger
+
+import (
+ "encoding/json"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/common/math"
+)
+
+var _ = (*callFrameMarshaling)(nil)
+
+// MarshalJSON marshals as JSON.
+func (c callFrame) MarshalJSON() ([]byte, error) {
+ type callFrame struct {
+ From common.Address `json:"from"`
+ To common.Address `json:"to"`
+ Input hexutil.Bytes `json:"input,omitempty"`
+ Gas math.HexOrDecimal64 `json:"gas"`
+ Value *hexutil.Big `json:"value"`
+ Type string `json:"type"`
+ }
+ var enc callFrame
+ enc.From = c.From
+ enc.To = c.To
+ enc.Input = c.Input
+ enc.Gas = math.HexOrDecimal64(c.Gas)
+ enc.Value = (*hexutil.Big)(c.Value)
+ enc.Type = c.Type()
+ return json.Marshal(&enc)
+}
+
+// UnmarshalJSON unmarshals from JSON.
+func (c *callFrame) UnmarshalJSON(input []byte) error {
+ type callFrame struct {
+ From *common.Address `json:"from"`
+ To *common.Address `json:"to"`
+ Input *hexutil.Bytes `json:"input,omitempty"`
+ Gas *math.HexOrDecimal64 `json:"gas"`
+ Value *hexutil.Big `json:"value"`
+ }
+ var dec callFrame
+ if err := json.Unmarshal(input, &dec); err != nil {
+ return err
+ }
+ if dec.From != nil {
+ c.From = *dec.From
+ }
+ if dec.To != nil {
+ c.To = *dec.To
+ }
+ if dec.Input != nil {
+ c.Input = *dec.Input
+ }
+ if dec.Gas != nil {
+ c.Gas = uint64(*dec.Gas)
+ }
+ if dec.Value != nil {
+ c.Value = (*big.Int)(dec.Value)
+ }
+ return nil
+}
diff --git a/eth/tracers/logger/logger.go b/eth/tracers/logger/logger.go
index fff52372a7..e36ea0d545 100644
--- a/eth/tracers/logger/logger.go
+++ b/eth/tracers/logger/logger.go
@@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
@@ -110,14 +111,13 @@ func (s *StructLog) ErrorString() string {
// contract their storage.
type StructLogger struct {
cfg Config
- env *vm.EVM
+ env *tracing.VMContext
- storage map[common.Address]Storage
- logs []StructLog
- output []byte
- err error
- gasLimit uint64
- usedGas uint64
+ storage map[common.Address]Storage
+ logs []StructLog
+ output []byte
+ err error
+ usedGas uint64
interrupt atomic.Bool // Atomic flag to signal execution interruption
reason error // Textual reason for the interruption
@@ -135,6 +135,15 @@ func NewStructLogger(cfg *Config) *StructLogger {
return logger
}
+func (l *StructLogger) Hooks() *tracing.Hooks {
+ return &tracing.Hooks{
+ OnTxStart: l.OnTxStart,
+ OnTxEnd: l.OnTxEnd,
+ OnExit: l.OnExit,
+ OnOpcode: l.OnOpcode,
+ }
+}
+
// Reset clears the data held by the logger.
func (l *StructLogger) Reset() {
l.storage = make(map[common.Address]Storage)
@@ -143,15 +152,10 @@ func (l *StructLogger) Reset() {
l.err = nil
}
-// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
-func (l *StructLogger) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
- l.env = env
-}
-
-// CaptureState logs a new structured log message and pushes it out to the environment
+// OnOpcode logs a new structured log message and pushes it out to the environment
//
-// CaptureState also tracks SLOAD/SSTORE ops to track storage change.
-func (l *StructLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+// OnOpcode also tracks SLOAD/SSTORE ops to track storage change.
+func (l *StructLogger) OnOpcode(pc uint64, opcode byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
// If tracing was interrupted, set the error and stop
if l.interrupt.Load() {
return
@@ -161,52 +165,47 @@ func (l *StructLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, s
return
}
- memory := scope.Memory
- stack := scope.Stack
- contract := scope.Contract
+ op := vm.OpCode(opcode)
+ memory := scope.MemoryData()
+ stack := scope.StackData()
// Copy a snapshot of the current memory state to a new buffer
var mem []byte
if l.cfg.EnableMemory {
- mem = make([]byte, len(memory.Data()))
- copy(mem, memory.Data())
+ mem = make([]byte, len(memory))
+ copy(mem, memory)
}
// Copy a snapshot of the current stack state to a new buffer
var stck []uint256.Int
if !l.cfg.DisableStack {
- stck = make([]uint256.Int, len(stack.Data()))
- for i, item := range stack.Data() {
- stck[i] = item
- }
+ stck = make([]uint256.Int, len(stack))
+ copy(stck, stack)
}
-
- stackData := stack.Data()
- stackLen := len(stackData)
+ contractAddr := scope.Address()
+ stackLen := len(stack)
// Copy a snapshot of the current storage to a new container
var storage Storage
if !l.cfg.DisableStorage && (op == vm.SLOAD || op == vm.SSTORE) {
// initialise new changed values storage container for this contract
// if not present.
- if l.storage[contract.Address()] == nil {
- l.storage[contract.Address()] = make(Storage)
+ if l.storage[contractAddr] == nil {
+ l.storage[contractAddr] = make(Storage)
}
// capture SLOAD opcodes and record the read entry in the local storage
if op == vm.SLOAD && stackLen >= 1 {
var (
- address = common.Hash(stackData[stackLen-1].Bytes32())
- value = l.env.StateDB.GetState(contract.Address(), address)
+ address = common.Hash(stack[stackLen-1].Bytes32())
+ value = l.env.StateDB.GetState(contractAddr, address)
)
-
- l.storage[contract.Address()][address] = value
- storage = l.storage[contract.Address()].Copy()
+ l.storage[contractAddr][address] = value
+ storage = l.storage[contractAddr].Copy()
} else if op == vm.SSTORE && stackLen >= 2 {
// capture SSTORE opcodes and record the written entry in the local storage.
var (
- value = common.Hash(stackData[stackLen-2].Bytes32())
- address = common.Hash(stackData[stackLen-1].Bytes32())
+ value = common.Hash(stack[stackLen-2].Bytes32())
+ address = common.Hash(stack[stackLen-1].Bytes32())
)
-
- l.storage[contract.Address()][address] = value
- storage = l.storage[contract.Address()].Copy()
+ l.storage[contractAddr][address] = value
+ storage = l.storage[contractAddr].Copy()
}
}
@@ -216,17 +215,15 @@ func (l *StructLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, s
copy(rdata, rData)
}
// create a new snapshot of the EVM.
- log := StructLog{pc, op, gas, cost, mem, memory.Len(), stck, rdata, storage, depth, l.env.StateDB.GetRefund(), err}
+ log := StructLog{pc, op, gas, cost, mem, len(memory), stck, rdata, storage, depth, l.env.StateDB.GetRefund(), err}
l.logs = append(l.logs, log)
}
-// CaptureFault implements the EVMLogger interface to trace an execution fault
-// while running an opcode.
-func (l *StructLogger) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
-}
-
-// CaptureEnd is called after the call finishes to finalize the tracing.
-func (l *StructLogger) CaptureEnd(output []byte, gasUsed uint64, err error) {
+// OnExit is called a call frame finishes processing.
+func (l *StructLogger) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
+ if depth != 0 {
+ return
+ }
l.output = output
l.err = err
@@ -239,12 +236,6 @@ func (l *StructLogger) CaptureEnd(output []byte, gasUsed uint64, err error) {
}
}
-func (l *StructLogger) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
-}
-
-func (l *StructLogger) CaptureExit(output []byte, gasUsed uint64, err error) {
-}
-
func (l *StructLogger) GetResult() (json.RawMessage, error) {
// Tracing aborted
if l.reason != nil {
@@ -273,12 +264,19 @@ func (l *StructLogger) Stop(err error) {
l.interrupt.Store(true)
}
-func (l *StructLogger) CaptureTxStart(gasLimit uint64) {
- l.gasLimit = gasLimit
+func (l *StructLogger) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
+ l.env = env
}
-func (l *StructLogger) CaptureTxEnd(restGas uint64) {
- l.usedGas = l.gasLimit - restGas
+func (l *StructLogger) OnTxEnd(receipt *types.Receipt, err error) {
+ if err != nil {
+ // Don't override vm error
+ if l.err == nil {
+ l.err = err
+ }
+ return
+ }
+ l.usedGas = receipt.GasUsed
}
// StructLogs returns the captured log entries.
@@ -348,7 +346,7 @@ func WriteLogs(writer io.Writer, logs []*types.Log) {
type mdLogger struct {
out io.Writer
cfg *Config
- env *vm.EVM
+ env *tracing.VMContext
}
// NewMarkdownLogger creates a logger which outputs information in a format adapted
@@ -362,8 +360,25 @@ func NewMarkdownLogger(cfg *Config, writer io.Writer) *mdLogger {
return l
}
-func (t *mdLogger) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+func (t *mdLogger) Hooks() *tracing.Hooks {
+ return &tracing.Hooks{
+ OnTxStart: t.OnTxStart,
+ OnEnter: t.OnEnter,
+ OnExit: t.OnExit,
+ OnOpcode: t.OnOpcode,
+ OnFault: t.OnFault,
+ }
+}
+
+func (t *mdLogger) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
t.env = env
+}
+
+func (t *mdLogger) OnEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+ if depth != 0 {
+ return
+ }
+ create := vm.OpCode(typ) == vm.CREATE
if !create {
fmt.Fprintf(t.out, "From: `%v`\nTo: `%v`\nData: `%#x`\nGas: `%d`\nValue `%v` wei\n",
from.String(), to.String(),
@@ -380,16 +395,22 @@ func (t *mdLogger) CaptureStart(env *vm.EVM, from common.Address, to common.Addr
`)
}
-// CaptureState also tracks SLOAD/SSTORE ops to track storage change.
-func (t *mdLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
- stack := scope.Stack
+func (t *mdLogger) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
+ if depth == 0 {
+ fmt.Fprintf(t.out, "\nOutput: `%#x`\nConsumed gas: `%d`\nError: `%v`\n",
+ output, gasUsed, err)
+ }
+}
+// OnOpcode also tracks SLOAD/SSTORE ops to track storage change.
+func (t *mdLogger) OnOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
+ stack := scope.StackData()
fmt.Fprintf(t.out, "| %4d | %10v | %3d |", pc, op, cost)
if !t.cfg.DisableStack {
// format stack
var a []string
- for _, elem := range stack.Data() {
+ for _, elem := range stack {
a = append(a, elem.Hex())
}
@@ -405,24 +426,10 @@ func (t *mdLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope
}
}
-func (t *mdLogger) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
+func (t *mdLogger) OnFault(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, depth int, err error) {
fmt.Fprintf(t.out, "\nError: at pc=%d, op=%v: %v\n", pc, op, err)
}
-func (t *mdLogger) CaptureEnd(output []byte, gasUsed uint64, err error) {
- fmt.Fprintf(t.out, "\nOutput: `%#x`\nConsumed gas: `%d`\nError: `%v`\n",
- output, gasUsed, err)
-}
-
-func (t *mdLogger) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
-}
-
-func (t *mdLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
-
-func (*mdLogger) CaptureTxStart(gasLimit uint64) {}
-
-func (*mdLogger) CaptureTxEnd(restGas uint64) {}
-
// ExecutionResult groups all structured logs emitted by the EVM
// while replaying a transaction in debug mode as well as transaction
// execution status, the amount of gas used and the return value
diff --git a/eth/tracers/logger/logger_json.go b/eth/tracers/logger/logger_json.go
index 1d693f9a8b..99678e5578 100644
--- a/eth/tracers/logger/logger_json.go
+++ b/eth/tracers/logger/logger_json.go
@@ -22,57 +22,105 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/core/tracing"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
)
-type JSONLogger struct {
+//go:generate go run github.com/fjl/gencodec -type callFrame -field-override callFrameMarshaling -out gen_callframe.go
+
+// overrides for gencodec
+type callFrameMarshaling struct {
+ Input hexutil.Bytes
+ Gas math.HexOrDecimal64
+ Value *hexutil.Big
+ Type string `json:"type"` // adds call to Type() in MarshalJSON
+}
+
+// callFrame is emitted every call frame entered.
+type callFrame struct {
+ op vm.OpCode
+ From common.Address `json:"from"`
+ To common.Address `json:"to"`
+ Input []byte `json:"input,omitempty"`
+ Gas uint64 `json:"gas"`
+ Value *big.Int `json:"value"`
+}
+
+// Type formats the call type in a human-readable format.
+func (c *callFrame) Type() string {
+ return c.op.String()
+}
+
+type jsonLogger struct {
encoder *json.Encoder
cfg *Config
- env *vm.EVM
+ env *tracing.VMContext
+ hooks *tracing.Hooks
}
// NewJSONLogger creates a new EVM tracer that prints execution steps as JSON objects
// into the provided stream.
-func NewJSONLogger(cfg *Config, writer io.Writer) *JSONLogger {
- l := &JSONLogger{encoder: json.NewEncoder(writer), cfg: cfg}
+func NewJSONLogger(cfg *Config, writer io.Writer) *tracing.Hooks {
+ l := &jsonLogger{encoder: json.NewEncoder(writer), cfg: cfg}
if l.cfg == nil {
l.cfg = &Config{}
}
-
- return l
+ l.hooks = &tracing.Hooks{
+ OnTxStart: l.OnTxStart,
+ OnSystemCallStart: l.onSystemCallStart,
+ OnExit: l.OnEnd,
+ OnOpcode: l.OnOpcode,
+ OnFault: l.OnFault,
+ }
+ return l.hooks
}
-func (l *JSONLogger) CaptureStart(env *vm.EVM, from, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
- l.env = env
+// NewJSONLoggerWithCallFrames creates a new EVM tracer that prints execution steps as JSON objects
+// into the provided stream. It also includes call frames in the output.
+func NewJSONLoggerWithCallFrames(cfg *Config, writer io.Writer) *tracing.Hooks {
+ l := &jsonLogger{encoder: json.NewEncoder(writer), cfg: cfg}
+ if l.cfg == nil {
+ l.cfg = &Config{}
+ }
+ l.hooks = &tracing.Hooks{
+ OnTxStart: l.OnTxStart,
+ OnSystemCallStart: l.onSystemCallStart,
+ OnEnter: l.OnEnter,
+ OnExit: l.OnExit,
+ OnOpcode: l.OnOpcode,
+ OnFault: l.OnFault,
+ }
+ return l.hooks
}
-func (l *JSONLogger) CaptureFault(pc uint64, op vm.OpCode, gas uint64, cost uint64, scope *vm.ScopeContext, depth int, err error) {
+func (l *jsonLogger) OnFault(pc uint64, op byte, gas uint64, cost uint64, scope tracing.OpContext, depth int, err error) {
// TODO: Add rData to this interface as well
- l.CaptureState(pc, op, gas, cost, scope, nil, depth, err)
+ l.OnOpcode(pc, op, gas, cost, scope, nil, depth, err)
}
-// CaptureState outputs state information on the logger.
-func (l *JSONLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
- memory := scope.Memory
- stack := scope.Stack
+func (l *jsonLogger) OnOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
+ memory := scope.MemoryData()
+ stack := scope.StackData()
log := StructLog{
Pc: pc,
- Op: op,
+ Op: vm.OpCode(op),
Gas: gas,
GasCost: cost,
- MemorySize: memory.Len(),
+ MemorySize: len(memory),
Depth: depth,
RefundCounter: l.env.StateDB.GetRefund(),
Err: err,
}
if l.cfg.EnableMemory {
- log.Memory = memory.Data()
+ log.Memory = memory
}
if !l.cfg.DisableStack {
- log.Stack = stack.Data()
+ log.Stack = stack
}
if l.cfg.EnableReturnData {
@@ -82,8 +130,39 @@ func (l *JSONLogger) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, sco
l.encoder.Encode(log)
}
-// CaptureEnd is triggered at end of execution.
-func (l *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, err error) {
+func (l *jsonLogger) onSystemCallStart() {
+ // Process no events while in system call.
+ hooks := *l.hooks
+ *l.hooks = tracing.Hooks{
+ OnSystemCallEnd: func() {
+ *l.hooks = hooks
+ },
+ }
+}
+
+// OnEnter is not enabled by default.
+func (l *jsonLogger) OnEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+ frame := callFrame{
+ op: vm.OpCode(typ),
+ From: from,
+ To: to,
+ Gas: gas,
+ Value: value,
+ }
+ if l.cfg.EnableMemory {
+ frame.Input = input
+ }
+ l.encoder.Encode(frame)
+}
+
+func (l *jsonLogger) OnEnd(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
+ if depth > 0 {
+ return
+ }
+ l.OnExit(depth, output, gasUsed, err, false)
+}
+
+func (l *jsonLogger) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
type endLog struct {
Output string `json:"output"`
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
@@ -99,11 +178,6 @@ func (l *JSONLogger) CaptureEnd(output []byte, gasUsed uint64, err error) {
_ = l.encoder.Encode(endLog{common.Bytes2Hex(output), math.HexOrDecimal64(gasUsed), errMsg})
}
-func (l *JSONLogger) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+func (l *jsonLogger) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
+ l.env = env
}
-
-func (l *JSONLogger) CaptureExit(output []byte, gasUsed uint64, err error) {}
-
-func (l *JSONLogger) CaptureTxStart(gasLimit uint64) {}
-
-func (l *JSONLogger) CaptureTxEnd(restGas uint64) {}
diff --git a/eth/tracers/logger/logger_test.go b/eth/tracers/logger/logger_test.go
index a239530542..7346abe988 100644
--- a/eth/tracers/logger/logger_test.go
+++ b/eth/tracers/logger/logger_test.go
@@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
+ "github.com/holiman/uint256"
)
type dummyContractRef struct {
@@ -56,17 +57,15 @@ func (*dummyStatedb) AddAddressToAccessList(address common.Address) {}
func TestStoreCapture(t *testing.T) {
var (
logger = NewStructLogger(nil)
- env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: logger})
- contract = vm.NewContract(&dummyContractRef{}, &dummyContractRef{}, new(big.Int), 100000)
+ env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: logger.Hooks()})
+ contract = vm.NewContract(&dummyContractRef{}, &dummyContractRef{}, new(uint256.Int), 100000)
)
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)}
var index common.Hash
-
- logger.CaptureStart(env, common.Address{}, contract.Address(), false, nil, 0, nil)
-
- _, err := env.Interpreter().PreRun(contract, []byte{}, false, nil)
+ logger.OnTxStart(env.GetVMContext(), nil, common.Address{})
+ _, err := env.Interpreter().Run(contract, []byte{}, false, nil)
if err != nil {
t.Fatal(err)
}
diff --git a/eth/tracers/native/4byte.go b/eth/tracers/native/4byte.go
index f6dec92ea0..e6cd42c489 100644
--- a/eth/tracers/native/4byte.go
+++ b/eth/tracers/native/4byte.go
@@ -23,6 +23,8 @@ import (
"sync/atomic"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/tracing"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers"
)
@@ -46,21 +48,26 @@ func init() {
// 0xc281d19e-0: 1
// }
type fourByteTracer struct {
- noopTracer
ids map[string]int // ids aggregates the 4byte ids found
interrupt atomic.Bool // Atomic flag to signal execution interruption
reason error // Textual reason for the interruption
- activePrecompiles []common.Address // Updated on CaptureStart based on given rules
+ activePrecompiles []common.Address // Updated on tx start based on given rules
}
// newFourByteTracer returns a native go tracer which collects
// 4 byte-identifiers of a tx, and implements vm.EVMLogger.
-func newFourByteTracer(ctx *tracers.Context, _ json.RawMessage) (tracers.Tracer, error) {
+func newFourByteTracer(ctx *tracers.Context, _ json.RawMessage) (*tracers.Tracer, error) {
t := &fourByteTracer{
ids: make(map[string]int),
}
-
- return t, nil
+ return &tracers.Tracer{
+ Hooks: &tracing.Hooks{
+ OnTxStart: t.OnTxStart,
+ OnEnter: t.OnEnter,
+ },
+ GetResult: t.GetResult,
+ Stop: t.Stop,
+ }, nil
}
// isPrecompiled returns whether the addr is a precompile. Logic borrowed from newJsTracer in eth/tracers/js/tracer.go
@@ -80,20 +87,14 @@ func (t *fourByteTracer) store(id []byte, size int) {
t.ids[key] += 1
}
-// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
-func (t *fourByteTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+func (t *fourByteTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
// Update list of precompiles based on current block
- rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time)
+ rules := env.ChainConfig.Rules(env.BlockNumber, env.Random != nil, env.Time)
t.activePrecompiles = vm.ActivePrecompiles(rules)
-
- // Save the outer calldata also
- if len(input) >= 4 {
- t.store(input[0:4], len(input)-4)
- }
}
-// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
-func (t *fourByteTracer) CaptureEnter(op vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+// OnEnter is called when EVM enters a new scope (via call, create or selfdestruct).
+func (t *fourByteTracer) OnEnter(depth int, opcode byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
// Skip if tracing was interrupted
if t.interrupt.Load() {
return
@@ -102,6 +103,7 @@ func (t *fourByteTracer) CaptureEnter(op vm.OpCode, from common.Address, to comm
if len(input) < 4 {
return
}
+ op := vm.OpCode(opcode)
// primarily we want to avoid CREATE/CREATE2/SELFDESTRUCT
if op != vm.DELEGATECALL && op != vm.STATICCALL &&
op != vm.CALL && op != vm.CALLCODE {
diff --git a/eth/tracers/native/call.go b/eth/tracers/native/call.go
index db7bb781d6..b5233c645e 100644
--- a/eth/tracers/native/call.go
+++ b/eth/tracers/native/call.go
@@ -25,9 +25,10 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/core/tracing"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers"
- "github.com/ethereum/go-ethereum/log"
)
//go:generate go run github.com/fjl/gencodec -type callFrame -field-override callFrameMarshaling -out gen_callframe_json.go
@@ -59,7 +60,8 @@ type callFrame struct {
Logs []callLog `json:"logs,omitempty" rlp:"optional"`
// Placed at end on purpose. The RLP will be decoded to 0 instead of
// nil if there are non-empty elements after in the struct.
- Value *big.Int `json:"value,omitempty" rlp:"optional"`
+ Value *big.Int `json:"value,omitempty" rlp:"optional"`
+ revertedSnapshot bool
}
func (f callFrame) TypeString() string {
@@ -67,18 +69,23 @@ func (f callFrame) TypeString() string {
}
func (f callFrame) failed() bool {
- return len(f.Error) > 0
+ return len(f.Error) > 0 && f.revertedSnapshot
}
-func (f *callFrame) processOutput(output []byte, err error) {
+func (f *callFrame) processOutput(output []byte, err error, reverted bool) {
output = common.CopyBytes(output)
+ // Clear error if tx wasn't reverted. This happened
+ // for pre-homestead contract storage OOG.
+ if err != nil && !reverted {
+ err = nil
+ }
if err == nil {
f.Output = output
return
}
f.Error = err.Error()
-
+ f.revertedSnapshot = reverted
if f.Type == vm.CREATE || f.Type == vm.CREATE2 {
f.To = nil
}
@@ -108,10 +115,10 @@ type callFrameMarshaling struct {
}
type callTracer struct {
- noopTracer
callstack []callFrame
config callTracerConfig
gasLimit uint64
+ depth int
interrupt atomic.Bool // Atomic flag to signal execution interruption
reason error // Textual reason for the interruption
}
@@ -123,7 +130,25 @@ type callTracerConfig struct {
// newCallTracer returns a native go tracer which tracks
// call frames of a tx, and implements vm.EVMLogger.
-func newCallTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) {
+func newCallTracer(ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer, error) {
+ t, err := newCallTracerObject(ctx, cfg)
+ if err != nil {
+ return nil, err
+ }
+ return &tracers.Tracer{
+ Hooks: &tracing.Hooks{
+ OnTxStart: t.OnTxStart,
+ OnTxEnd: t.OnTxEnd,
+ OnEnter: t.OnEnter,
+ OnExit: t.OnExit,
+ OnLog: t.OnLog,
+ },
+ GetResult: t.GetResult,
+ Stop: t.Stop,
+ }, nil
+}
+
+func newCallTracerObject(ctx *tracers.Context, cfg json.RawMessage) (*callTracer, error) {
var config callTracerConfig
if cfg != nil {
if err := json.Unmarshal(cfg, &config); err != nil {
@@ -132,42 +157,12 @@ func newCallTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, e
}
// First callframe contains tx context info
// and is populated on start and end.
- return &callTracer{callstack: make([]callFrame, 1), config: config}, nil
-}
-
-// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
-func (t *callTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
- toCopy := to
-
- t.callstack[0] = callFrame{
- Type: vm.CALL,
- From: from,
- To: &toCopy,
- Input: common.CopyBytes(input),
- Gas: t.gasLimit,
- Value: value,
- }
- if create {
- t.callstack[0].Type = vm.CREATE
- }
-}
-
-// CaptureEnd is called after the call finishes to finalize the tracing.
-func (t *callTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
- t.callstack[0].processOutput(output, err)
+ return &callTracer{callstack: make([]callFrame, 0, 1), config: config}, nil
}
-// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
-func (t *callTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
- // skip if the previous op caused an error
- if err != nil {
- return
- }
- // Only logs need to be captured via opcode processing
- if !t.config.WithLog {
- return
- }
- // Avoid processing nested calls when only caring about top call
+// OnEnter is called when EVM enters a new scope (via call, create or selfdestruct).
+func (t *callTracer) OnEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+ t.depth = depth
if t.config.OnlyTopCall && depth > 0 {
return
}
@@ -176,66 +171,30 @@ func (t *callTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, sco
return
}
- // nolint : exhaustive
- switch op {
- case vm.LOG0, vm.LOG1, vm.LOG2, vm.LOG3, vm.LOG4:
- size := int(op - vm.LOG0)
-
- stack := scope.Stack
- stackData := stack.Data()
-
- // Don't modify the stack
- mStart := stackData[len(stackData)-1]
- mSize := stackData[len(stackData)-2]
- topics := make([]common.Hash, size)
-
- for i := 0; i < size; i++ {
- topic := stackData[len(stackData)-2-(i+1)]
- topics[i] = common.Hash(topic.Bytes32())
- }
-
- data, err := tracers.GetMemoryCopyPadded(scope.Memory, int64(mStart.Uint64()), int64(mSize.Uint64()))
- if err != nil {
- // mSize was unrealistically large
- log.Warn("failed to copy CREATE2 input", "err", err, "tracer", "callTracer", "offset", mStart, "size", mSize)
- return
- }
-
- log := callLog{
- Address: scope.Contract.Address(),
- Topics: topics,
- Data: hexutil.Bytes(data),
- Position: hexutil.Uint(len(t.callstack[len(t.callstack)-1].Calls)),
- }
- t.callstack[len(t.callstack)-1].Logs = append(t.callstack[len(t.callstack)-1].Logs, log)
- }
-}
-
-// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
-func (t *callTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
- if t.config.OnlyTopCall {
- return
- }
- // Skip if tracing was interrupted
- if t.interrupt.Load() {
- return
- }
-
toCopy := to
call := callFrame{
- Type: typ,
+ Type: vm.OpCode(typ),
From: from,
To: &toCopy,
Input: common.CopyBytes(input),
Gas: gas,
Value: value,
}
+ if depth == 0 {
+ call.Gas = t.gasLimit
+ }
t.callstack = append(t.callstack, call)
}
-// CaptureExit is called when EVM exits a scope, even if the scope didn't
+// OnExit is called when EVM exits a scope, even if the scope didn't
// execute any code.
-func (t *callTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
+func (t *callTracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
+ if depth == 0 {
+ t.captureEnd(output, gasUsed, err, reverted)
+ return
+ }
+
+ t.depth = depth - 1
if t.config.OnlyTopCall {
return
}
@@ -244,28 +203,62 @@ func (t *callTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
if size <= 1 {
return
}
- // pop call
+ // Pop call.
call := t.callstack[size-1]
t.callstack = t.callstack[:size-1]
size -= 1
call.GasUsed = gasUsed
- call.processOutput(output, err)
+ call.processOutput(output, err, reverted)
+ // Nest call into parent.
t.callstack[size-1].Calls = append(t.callstack[size-1].Calls, call)
}
-func (t *callTracer) CaptureTxStart(gasLimit uint64) {
- t.gasLimit = gasLimit
+func (t *callTracer) captureEnd(output []byte, gasUsed uint64, err error, reverted bool) {
+ if len(t.callstack) != 1 {
+ return
+ }
+ t.callstack[0].processOutput(output, err, reverted)
+}
+
+func (t *callTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
+ t.gasLimit = tx.Gas()
}
-func (t *callTracer) CaptureTxEnd(restGas uint64) {
- t.callstack[0].GasUsed = t.gasLimit - restGas
+func (t *callTracer) OnTxEnd(receipt *types.Receipt, err error) {
+ // Error happened during tx validation.
+ if err != nil {
+ return
+ }
+ t.callstack[0].GasUsed = receipt.GasUsed
if t.config.WithLog {
// Logs are not emitted when the call fails
clearFailedLogs(&t.callstack[0], false)
}
}
+func (t *callTracer) OnLog(log *types.Log) {
+ // Only logs need to be captured via opcode processing
+ if !t.config.WithLog {
+ return
+ }
+ // Avoid processing nested calls when only caring about top call
+ if t.config.OnlyTopCall && t.depth > 0 {
+ return
+ }
+ // Skip if tracing was interrupted
+ if t.interrupt.Load() {
+ return
+ }
+ l := callLog{
+ Address: log.Address,
+ Topics: log.Topics,
+ Data: log.Data,
+ Position: hexutil.Uint(len(t.callstack[len(t.callstack)-1].Calls)),
+ }
+ t.callstack[len(t.callstack)-1].Logs = append(t.callstack[len(t.callstack)-1].Logs, l)
+}
+
// GetResult returns the json-encoded nested list of call traces, and any
// error arising from the encoding or forceful termination (via `Stop`).
func (t *callTracer) GetResult() (json.RawMessage, error) {
@@ -278,7 +271,7 @@ func (t *callTracer) GetResult() (json.RawMessage, error) {
return nil, err
}
- return json.RawMessage(res), t.reason
+ return res, t.reason
}
// Stop terminates execution of the tracer at the first opportune moment.
diff --git a/eth/tracers/native/call_flat.go b/eth/tracers/native/call_flat.go
index d23d8be4b2..c7287b15ca 100644
--- a/eth/tracers/native/call_flat.go
+++ b/eth/tracers/native/call_flat.go
@@ -21,10 +21,14 @@ import (
"errors"
"fmt"
"math/big"
+ "slices"
"strings"
+ "sync/atomic"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/core/tracing"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers"
)
@@ -111,8 +115,8 @@ type flatCallTracer struct {
tracer *callTracer
config flatCallTracerConfig
ctx *tracers.Context // Holds tracer context data
- reason error // Textual reason for the interruption
- activePrecompiles []common.Address // Updated on CaptureStart based on given rules
+ interrupt atomic.Bool // Atomic flag to signal execution interruption
+ activePrecompiles []common.Address // Updated on tx start based on given rules
}
type flatCallTracerConfig struct {
@@ -121,7 +125,7 @@ type flatCallTracerConfig struct {
}
// newFlatCallTracer returns a new flatCallTracer.
-func newFlatCallTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) {
+func newFlatCallTracer(ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer, error) {
var config flatCallTracerConfig
if cfg != nil {
if err := json.Unmarshal(cfg, &config); err != nil {
@@ -131,47 +135,34 @@ func newFlatCallTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Trace
// Create inner call tracer with default configuration, don't forward
// the OnlyTopCall or WithLog to inner for now
- tracer, err := tracers.DefaultDirectory.New("callTracer", ctx, nil)
+ t, err := newCallTracerObject(ctx, nil)
if err != nil {
return nil, err
}
- t, ok := tracer.(*callTracer)
-
- if !ok {
- return nil, errors.New("internal error: embedded tracer has wrong type")
- }
-
- return &flatCallTracer{tracer: t, ctx: ctx, config: config}, nil
-}
-
-// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
-func (t *flatCallTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
- t.tracer.CaptureStart(env, from, to, create, input, gas, value)
- // Update list of precompiles based on current block
- rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time)
- t.activePrecompiles = vm.ActivePrecompiles(rules)
-}
-
-// CaptureEnd is called after the call finishes to finalize the tracing.
-func (t *flatCallTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
- t.tracer.CaptureEnd(output, gasUsed, err)
-}
-
-// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
-func (t *flatCallTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
- t.tracer.CaptureState(pc, op, gas, cost, scope, rData, depth, err)
-}
-
-// CaptureFault implements the EVMLogger interface to trace an execution fault.
-func (t *flatCallTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
- t.tracer.CaptureFault(pc, op, gas, cost, scope, depth, err)
+ ft := &flatCallTracer{tracer: t, ctx: ctx, config: config}
+ return &tracers.Tracer{
+ Hooks: &tracing.Hooks{
+ OnTxStart: ft.OnTxStart,
+ OnTxEnd: ft.OnTxEnd,
+ OnEnter: ft.OnEnter,
+ OnExit: ft.OnExit,
+ },
+ Stop: ft.Stop,
+ GetResult: ft.GetResult,
+ }, nil
}
-// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
-func (t *flatCallTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
- t.tracer.CaptureEnter(typ, from, to, input, gas, value)
+// OnEnter is called when EVM enters a new scope (via call, create or selfdestruct).
+func (t *flatCallTracer) OnEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+ if t.interrupt.Load() {
+ return
+ }
+ t.tracer.OnEnter(depth, typ, from, to, input, gas, value)
+ if depth == 0 {
+ return
+ }
// Child calls must have a value, even if it's zero.
// Practically speaking, only STATICCALL has nil value. Set it to zero.
if t.tracer.callstack[len(t.tracer.callstack)-1].Value == nil && value == nil {
@@ -179,11 +170,17 @@ func (t *flatCallTracer) CaptureEnter(typ vm.OpCode, from common.Address, to com
}
}
-// CaptureExit is called when EVM exits a scope, even if the scope didn't
+// OnExit is called when EVM exits a scope, even if the scope didn't
// execute any code.
-func (t *flatCallTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
- t.tracer.CaptureExit(output, gasUsed, err)
+func (t *flatCallTracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
+ if t.interrupt.Load() {
+ return
+ }
+ t.tracer.OnExit(depth, output, gasUsed, err, reverted)
+ if depth == 0 {
+ return
+ }
// Parity traces don't include CALL/STATICCALLs to precompiles.
// By default we remove them from the callstack.
if t.config.IncludePrecompiles {
@@ -205,12 +202,21 @@ func (t *flatCallTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
}
}
-func (t *flatCallTracer) CaptureTxStart(gasLimit uint64) {
- t.tracer.CaptureTxStart(gasLimit)
+func (t *flatCallTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
+ if t.interrupt.Load() {
+ return
+ }
+ t.tracer.OnTxStart(env, tx, from)
+ // Update list of precompiles based on current block
+ rules := env.ChainConfig.Rules(env.BlockNumber, env.Random != nil, env.Time)
+ t.activePrecompiles = vm.ActivePrecompiles(rules)
}
-func (t *flatCallTracer) CaptureTxEnd(restGas uint64) {
- t.tracer.CaptureTxEnd(restGas)
+func (t *flatCallTracer) OnTxEnd(receipt *types.Receipt, err error) {
+ if t.interrupt.Load() {
+ return
+ }
+ t.tracer.OnTxEnd(receipt, err)
}
// GetResult returns an empty json object.
@@ -228,24 +234,18 @@ func (t *flatCallTracer) GetResult() (json.RawMessage, error) {
if err != nil {
return nil, err
}
-
- return res, t.reason
+ return res, t.tracer.reason
}
// Stop terminates execution of the tracer at the first opportune moment.
func (t *flatCallTracer) Stop(err error) {
t.tracer.Stop(err)
+ t.interrupt.Store(true)
}
// isPrecompiled returns whether the addr is a precompile.
func (t *flatCallTracer) isPrecompiled(addr common.Address) bool {
- for _, p := range t.activePrecompiles {
- if p == addr {
- return true
- }
- }
-
- return false
+ return slices.Contains(t.activePrecompiles, addr)
}
func flatFromNested(input *callFrame, traceAddress []int, convertErrs bool, ctx *tracers.Context) (output []flatCallFrame, err error) {
@@ -279,19 +279,14 @@ func flatFromNested(input *callFrame, traceAddress []int, convertErrs bool, ctx
}
output = append(output, *frame)
-
- if len(input.Calls) > 0 {
- for i, childCall := range input.Calls {
- childAddr := childTraceAddress(traceAddress, i)
- childCallCopy := childCall
- flat, err := flatFromNested(&childCallCopy, childAddr, convertErrs, ctx)
-
- if err != nil {
- return nil, err
- }
-
- output = append(output, flat...)
+ for i, childCall := range input.Calls {
+ childAddr := childTraceAddress(traceAddress, i)
+ childCallCopy := childCall
+ flat, err := flatFromNested(&childCallCopy, childAddr, convertErrs, ctx)
+ if err != nil {
+ return nil, err
}
+ output = append(output, flat...)
}
return output, nil
diff --git a/eth/tracers/native/call_flat_test.go b/eth/tracers/native/call_flat_test.go
new file mode 100644
index 0000000000..d5481b868b
--- /dev/null
+++ b/eth/tracers/native/call_flat_test.go
@@ -0,0 +1,64 @@
+// Copyright 2024 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 native_test
+
+import (
+ "errors"
+ "math/big"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/tracing"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/eth/tracers"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/stretchr/testify/require"
+)
+
+func TestCallFlatStop(t *testing.T) {
+ tracer, err := tracers.DefaultDirectory.New("flatCallTracer", &tracers.Context{}, nil)
+ require.NoError(t, err)
+
+ // this error should be returned by GetResult
+ stopError := errors.New("stop error")
+
+ // simulate a transaction
+ tx := types.NewTx(&types.LegacyTx{
+ Nonce: 0,
+ To: &common.Address{},
+ Value: big.NewInt(0),
+ Gas: 0,
+ GasPrice: big.NewInt(0),
+ Data: nil,
+ })
+
+ tracer.OnTxStart(&tracing.VMContext{
+ ChainConfig: params.MainnetChainConfig,
+ }, tx, common.Address{})
+
+ tracer.OnEnter(0, byte(vm.CALL), common.Address{}, common.Address{}, nil, 0, big.NewInt(0))
+
+ // stop before the transaction is finished
+ tracer.Stop(stopError)
+
+ tracer.OnTxEnd(&types.Receipt{GasUsed: 0}, nil)
+
+ // check that the error is returned by GetResult
+ _, tracerError := tracer.GetResult()
+ require.Equal(t, stopError, tracerError)
+}
diff --git a/eth/tracers/native/mux.go b/eth/tracers/native/mux.go
index df19bef9f3..345ab72d5b 100644
--- a/eth/tracers/native/mux.go
+++ b/eth/tracers/native/mux.go
@@ -21,7 +21,8 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/core/tracing"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/tracers"
)
@@ -33,11 +34,11 @@ func init() {
// runs multiple tracers in one go.
type muxTracer struct {
names []string
- tracers []tracers.Tracer
+ tracers []*tracers.Tracer
}
// newMuxTracer returns a new mux tracer.
-func newMuxTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) {
+func newMuxTracer(ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer, error) {
var config map[string]json.RawMessage
if cfg != nil {
if err := json.Unmarshal(cfg, &config); err != nil {
@@ -45,7 +46,7 @@ func newMuxTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, er
}
}
- objects := make([]tracers.Tracer, 0, len(config))
+ objects := make([]*tracers.Tracer, 0, len(config))
names := make([]string, 0, len(config))
for k, v := range config {
@@ -58,61 +59,120 @@ func newMuxTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, er
names = append(names, k)
}
- return &muxTracer{names: names, tracers: objects}, nil
+ t := &muxTracer{names: names, tracers: objects}
+ return &tracers.Tracer{
+ Hooks: &tracing.Hooks{
+ OnTxStart: t.OnTxStart,
+ OnTxEnd: t.OnTxEnd,
+ OnEnter: t.OnEnter,
+ OnExit: t.OnExit,
+ OnOpcode: t.OnOpcode,
+ OnFault: t.OnFault,
+ OnGasChange: t.OnGasChange,
+ OnBalanceChange: t.OnBalanceChange,
+ OnNonceChange: t.OnNonceChange,
+ OnCodeChange: t.OnCodeChange,
+ OnStorageChange: t.OnStorageChange,
+ OnLog: t.OnLog,
+ },
+ GetResult: t.GetResult,
+ Stop: t.Stop,
+ }, nil
}
-// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
-func (t *muxTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+func (t *muxTracer) OnOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
for _, t := range t.tracers {
- t.CaptureStart(env, from, to, create, input, gas, value)
+ if t.OnOpcode != nil {
+ t.OnOpcode(pc, op, gas, cost, scope, rData, depth, err)
+ }
+ }
+}
+
+func (t *muxTracer) OnFault(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, depth int, err error) {
+ for _, t := range t.tracers {
+ if t.OnFault != nil {
+ t.OnFault(pc, op, gas, cost, scope, depth, err)
+ }
+ }
+}
+
+func (t *muxTracer) OnGasChange(old, new uint64, reason tracing.GasChangeReason) {
+ for _, t := range t.tracers {
+ if t.OnGasChange != nil {
+ t.OnGasChange(old, new, reason)
+ }
+ }
+}
+
+func (t *muxTracer) OnEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+ for _, t := range t.tracers {
+ if t.OnEnter != nil {
+ t.OnEnter(depth, typ, from, to, input, gas, value)
+ }
+ }
+}
+
+func (t *muxTracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
+ for _, t := range t.tracers {
+ if t.OnExit != nil {
+ t.OnExit(depth, output, gasUsed, err, reverted)
+ }
}
}
-// CaptureEnd is called after the call finishes to finalize the tracing.
-func (t *muxTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
+func (t *muxTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
for _, t := range t.tracers {
- t.CaptureEnd(output, gasUsed, err)
+ if t.OnTxStart != nil {
+ t.OnTxStart(env, tx, from)
+ }
}
}
-// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
-func (t *muxTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+func (t *muxTracer) OnTxEnd(receipt *types.Receipt, err error) {
for _, t := range t.tracers {
- t.CaptureState(pc, op, gas, cost, scope, rData, depth, err)
+ if t.OnTxEnd != nil {
+ t.OnTxEnd(receipt, err)
+ }
}
}
-// CaptureFault implements the EVMLogger interface to trace an execution fault.
-func (t *muxTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
+func (t *muxTracer) OnBalanceChange(a common.Address, prev, new *big.Int, reason tracing.BalanceChangeReason) {
for _, t := range t.tracers {
- t.CaptureFault(pc, op, gas, cost, scope, depth, err)
+ if t.OnBalanceChange != nil {
+ t.OnBalanceChange(a, prev, new, reason)
+ }
}
}
-// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
-func (t *muxTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+func (t *muxTracer) OnNonceChange(a common.Address, prev, new uint64) {
for _, t := range t.tracers {
- t.CaptureEnter(typ, from, to, input, gas, value)
+ if t.OnNonceChange != nil {
+ t.OnNonceChange(a, prev, new)
+ }
}
}
-// CaptureExit is called when EVM exits a scope, even if the scope didn't
-// execute any code.
-func (t *muxTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
+func (t *muxTracer) OnCodeChange(a common.Address, prevCodeHash common.Hash, prev []byte, codeHash common.Hash, code []byte) {
for _, t := range t.tracers {
- t.CaptureExit(output, gasUsed, err)
+ if t.OnCodeChange != nil {
+ t.OnCodeChange(a, prevCodeHash, prev, codeHash, code)
+ }
}
}
-func (t *muxTracer) CaptureTxStart(gasLimit uint64) {
+func (t *muxTracer) OnStorageChange(a common.Address, k, prev, new common.Hash) {
for _, t := range t.tracers {
- t.CaptureTxStart(gasLimit)
+ if t.OnStorageChange != nil {
+ t.OnStorageChange(a, k, prev, new)
+ }
}
}
-func (t *muxTracer) CaptureTxEnd(restGas uint64) {
+func (t *muxTracer) OnLog(log *types.Log) {
for _, t := range t.tracers {
- t.CaptureTxEnd(restGas)
+ if t.OnLog != nil {
+ t.OnLog(log)
+ }
}
}
diff --git a/eth/tracers/native/noop.go b/eth/tracers/native/noop.go
index 3beecd8abf..f147134610 100644
--- a/eth/tracers/native/noop.go
+++ b/eth/tracers/native/noop.go
@@ -21,7 +21,8 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/core/tracing"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/tracers"
)
@@ -34,38 +35,58 @@ func init() {
type noopTracer struct{}
// newNoopTracer returns a new noop tracer.
-func newNoopTracer(ctx *tracers.Context, _ json.RawMessage) (tracers.Tracer, error) {
- return &noopTracer{}, nil
+func newNoopTracer(ctx *tracers.Context, _ json.RawMessage) (*tracers.Tracer, error) {
+ t := &noopTracer{}
+ return &tracers.Tracer{
+ Hooks: &tracing.Hooks{
+ OnTxStart: t.OnTxStart,
+ OnTxEnd: t.OnTxEnd,
+ OnEnter: t.OnEnter,
+ OnExit: t.OnExit,
+ OnOpcode: t.OnOpcode,
+ OnFault: t.OnFault,
+ OnGasChange: t.OnGasChange,
+ OnBalanceChange: t.OnBalanceChange,
+ OnNonceChange: t.OnNonceChange,
+ OnCodeChange: t.OnCodeChange,
+ OnStorageChange: t.OnStorageChange,
+ OnLog: t.OnLog,
+ },
+ GetResult: t.GetResult,
+ Stop: t.Stop,
+ }, nil
}
-// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
-func (t *noopTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
+func (t *noopTracer) OnOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
}
-// CaptureEnd is called after the call finishes to finalize the tracing.
-func (t *noopTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
+func (t *noopTracer) OnFault(pc uint64, op byte, gas, cost uint64, _ tracing.OpContext, depth int, err error) {
}
-// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
-func (t *noopTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+func (t *noopTracer) OnGasChange(old, new uint64, reason tracing.GasChangeReason) {}
+
+func (t *noopTracer) OnEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
}
-// CaptureFault implements the EVMLogger interface to trace an execution fault.
-func (t *noopTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, _ *vm.ScopeContext, depth int, err error) {
+func (t *noopTracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
}
-// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
-func (t *noopTracer) CaptureEnter(typ vm.OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
+func (*noopTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
}
-// CaptureExit is called when EVM exits a scope, even if the scope didn't
-// execute any code.
-func (t *noopTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
+func (*noopTracer) OnTxEnd(receipt *types.Receipt, err error) {}
+
+func (*noopTracer) OnBalanceChange(a common.Address, prev, new *big.Int, reason tracing.BalanceChangeReason) {
+}
+
+func (*noopTracer) OnNonceChange(a common.Address, prev, new uint64) {}
+
+func (*noopTracer) OnCodeChange(a common.Address, prevCodeHash common.Hash, prev []byte, codeHash common.Hash, code []byte) {
}
-func (*noopTracer) CaptureTxStart(gasLimit uint64) {}
+func (*noopTracer) OnStorageChange(a common.Address, k, prev, new common.Hash) {}
-func (*noopTracer) CaptureTxEnd(restGas uint64) {}
+func (*noopTracer) OnLog(log *types.Log) {}
// GetResult returns an empty json object.
func (t *noopTracer) GetResult() (json.RawMessage, error) {
diff --git a/eth/tracers/native/prestate.go b/eth/tracers/native/prestate.go
index 9351d044ab..520b73179f 100644
--- a/eth/tracers/native/prestate.go
+++ b/eth/tracers/native/prestate.go
@@ -24,9 +24,12 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/core/tracing"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/tracers"
+ "github.com/ethereum/go-ethereum/eth/tracers/internal"
"github.com/ethereum/go-ethereum/log"
)
@@ -36,13 +39,14 @@ func init() {
tracers.DefaultDirectory.Register("prestateTracer", newPrestateTracer, false)
}
-type state = map[common.Address]*account
+type stateMap = map[common.Address]*account
type account struct {
Balance *big.Int `json:"balance,omitempty"`
Code []byte `json:"code,omitempty"`
Nonce uint64 `json:"nonce,omitempty"`
Storage map[common.Hash]common.Hash `json:"storage,omitempty"`
+ empty bool
}
func (a *account) exists() bool {
@@ -55,13 +59,10 @@ type accountMarshaling struct {
}
type prestateTracer struct {
- noopTracer
- env *vm.EVM
- pre state
- post state
- create bool
+ env *tracing.VMContext
+ pre stateMap
+ post stateMap
to common.Address
- gasLimit uint64 // Amount of gas bought for the whole tx
config prestateTracerConfig
interrupt atomic.Bool // Atomic flag to signal execution interruption
reason error // Textual reason for the interruption
@@ -73,68 +74,33 @@ type prestateTracerConfig struct {
DiffMode bool `json:"diffMode"` // If true, this tracer will return state modifications
}
-func newPrestateTracer(ctx *tracers.Context, cfg json.RawMessage) (tracers.Tracer, error) {
+func newPrestateTracer(ctx *tracers.Context, cfg json.RawMessage) (*tracers.Tracer, error) {
var config prestateTracerConfig
if cfg != nil {
if err := json.Unmarshal(cfg, &config); err != nil {
return nil, err
}
}
-
- return &prestateTracer{
- pre: state{},
- post: state{},
+ t := &prestateTracer{
+ pre: stateMap{},
+ post: stateMap{},
config: config,
created: make(map[common.Address]bool),
deleted: make(map[common.Address]bool),
- }, nil
-}
-
-// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
-func (t *prestateTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
- t.env = env
- t.create = create
- t.to = to
-
- t.lookupAccount(from)
- t.lookupAccount(to)
- t.lookupAccount(env.Context.Coinbase)
-
- // The recipient balance includes the value transferred.
- toBal := new(big.Int).Sub(t.pre[to].Balance, value)
- t.pre[to].Balance = toBal
-
- // The sender balance is after reducing: value and gasLimit.
- // We need to re-add them to get the pre-tx balance.
- fromBal := new(big.Int).Set(t.pre[from].Balance)
- gasPrice := env.TxContext.GasPrice
- consumedGas := new(big.Int).Mul(gasPrice, new(big.Int).SetUint64(t.gasLimit))
- fromBal.Add(fromBal, new(big.Int).Add(value, consumedGas))
- t.pre[from].Balance = fromBal
- t.pre[from].Nonce--
-
- if create && t.config.DiffMode {
- t.created[to] = true
- }
-}
-
-// CaptureEnd is called after the call finishes to finalize the tracing.
-func (t *prestateTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
- if t.config.DiffMode {
- return
- }
-
- if t.create {
- // Keep existing account prior to contract creation at that address
- if s := t.pre[t.to]; s != nil && !s.exists() {
- // Exclude newly created contract.
- delete(t.pre, t.to)
- }
}
+ return &tracers.Tracer{
+ Hooks: &tracing.Hooks{
+ OnTxStart: t.OnTxStart,
+ OnTxEnd: t.OnTxEnd,
+ OnOpcode: t.OnOpcode,
+ },
+ GetResult: t.GetResult,
+ Stop: t.Stop,
+ }, nil
}
-// CaptureState implements the EVMLogger interface to trace a single step of VM execution.
-func (t *prestateTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
+// OnOpcode implements the EVMLogger interface to trace a single step of VM execution.
+func (t *prestateTracer) OnOpcode(pc uint64, opcode byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) {
if err != nil {
return
}
@@ -142,12 +108,10 @@ func (t *prestateTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64,
if t.interrupt.Load() {
return
}
-
- stack := scope.Stack
- stackData := stack.Data()
+ op := vm.OpCode(opcode)
+ stackData := scope.StackData()
stackLen := len(stackData)
- caller := scope.Contract.Address()
-
+ caller := scope.Address()
switch {
case stackLen >= 1 && (op == vm.SLOAD || op == vm.SSTORE):
slot := common.Hash(stackData[stackLen-1].Bytes32())
@@ -170,7 +134,7 @@ func (t *prestateTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64,
case stackLen >= 4 && op == vm.CREATE2:
offset := stackData[stackLen-2]
size := stackData[stackLen-3]
- init, err := tracers.GetMemoryCopyPadded(scope.Memory, int64(offset.Uint64()), int64(size.Uint64()))
+ init, err := internal.GetMemoryCopyPadded(scope.MemoryData(), int64(offset.Uint64()), int64(size.Uint64()))
if err != nil {
log.Warn("failed to copy CREATE2 input", "err", err, "tracer", "prestateTracer", "offset", offset, "size", size)
return
@@ -183,15 +147,62 @@ func (t *prestateTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64,
}
}
-func (t *prestateTracer) CaptureTxStart(gasLimit uint64) {
- t.gasLimit = gasLimit
+func (t *prestateTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction, from common.Address) {
+ t.env = env
+ if tx.To() == nil {
+ t.to = crypto.CreateAddress(from, env.StateDB.GetNonce(from))
+ t.created[t.to] = true
+ } else {
+ t.to = *tx.To()
+ }
+
+ t.lookupAccount(from)
+ t.lookupAccount(t.to)
+ t.lookupAccount(env.Coinbase)
}
-func (t *prestateTracer) CaptureTxEnd(restGas uint64) {
- if !t.config.DiffMode {
+func (t *prestateTracer) OnTxEnd(receipt *types.Receipt, err error) {
+ if err != nil {
return
}
+ if t.config.DiffMode {
+ t.processDiffState()
+ }
+ // the new created contracts' prestate were empty, so delete them
+ for a := range t.created {
+ // the created contract maybe exists in statedb before the creating tx
+ if s := t.pre[a]; s != nil && s.empty {
+ delete(t.pre, a)
+ }
+ }
+}
+
+// GetResult returns the json-encoded nested list of call traces, and any
+// error arising from the encoding or forceful termination (via `Stop`).
+func (t *prestateTracer) GetResult() (json.RawMessage, error) {
+ var res []byte
+ var err error
+ if t.config.DiffMode {
+ res, err = json.Marshal(struct {
+ Post stateMap `json:"post"`
+ Pre stateMap `json:"pre"`
+ }{t.post, t.pre})
+ } else {
+ res, err = json.Marshal(t.pre)
+ }
+ if err != nil {
+ return nil, err
+ }
+ return json.RawMessage(res), t.reason
+}
+
+// Stop terminates execution of the tracer at the first opportune moment.
+func (t *prestateTracer) Stop(err error) {
+ t.reason = err
+ t.interrupt.Store(true)
+}
+func (t *prestateTracer) processDiffState() {
for addr, state := range t.pre {
// The deleted account's state is pruned from `post` but kept in `pre`
if _, ok := t.deleted[addr]; ok {
@@ -200,7 +211,7 @@ func (t *prestateTracer) CaptureTxEnd(restGas uint64) {
modified := false
postAccount := &account{Storage: make(map[common.Hash]common.Hash)}
- newBalance := t.env.StateDB.GetBalance(addr)
+ newBalance := t.env.StateDB.GetBalance(addr).ToBig()
newNonce := t.env.StateDB.GetNonce(addr)
newCode := t.env.StateDB.GetCode(addr)
@@ -245,42 +256,6 @@ func (t *prestateTracer) CaptureTxEnd(restGas uint64) {
delete(t.pre, addr)
}
}
- // the new created contracts' prestate were empty, so delete them
- for a := range t.created {
- // the created contract maybe exists in statedb before the creating tx
- if s := t.pre[a]; s != nil && !s.exists() {
- delete(t.pre, a)
- }
- }
-}
-
-// GetResult returns the json-encoded nested list of call traces, and any
-// error arising from the encoding or forceful termination (via `Stop`).
-func (t *prestateTracer) GetResult() (json.RawMessage, error) {
- var res []byte
-
- var err error
-
- if t.config.DiffMode {
- res, err = json.Marshal(struct {
- Post state `json:"post"`
- Pre state `json:"pre"`
- }{t.post, t.pre})
- } else {
- res, err = json.Marshal(t.pre)
- }
-
- if err != nil {
- return nil, err
- }
-
- return json.RawMessage(res), t.reason
-}
-
-// Stop terminates execution of the tracer at the first opportune moment.
-func (t *prestateTracer) Stop(err error) {
- t.reason = err
- t.interrupt.Store(true)
}
// lookupAccount fetches details of an account and adds it to the prestate
@@ -290,12 +265,16 @@ func (t *prestateTracer) lookupAccount(addr common.Address) {
return
}
- t.pre[addr] = &account{
- Balance: t.env.StateDB.GetBalance(addr),
+ acc := &account{
+ Balance: t.env.StateDB.GetBalance(addr).ToBig(),
Nonce: t.env.StateDB.GetNonce(addr),
Code: t.env.StateDB.GetCode(addr),
Storage: make(map[common.Hash]common.Hash),
}
+ if !acc.exists() {
+ acc.empty = true
+ }
+ t.pre[addr] = acc
}
// lookupStorage fetches the requested storage slot and adds
diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go
index ac4af25aa7..1ec25ffd00 100644
--- a/eth/tracers/tracers_test.go
+++ b/eth/tracers/tracers_test.go
@@ -64,7 +64,7 @@ func BenchmarkTransactionTrace(b *testing.B) {
GasLimit: gas,
BaseFee: big.NewInt(8),
}
- alloc := core.GenesisAlloc{}
+ alloc := types.GenesisAlloc{}
// The code pushes 'deadbeef' into memory, then the other params, and calls CREATE2, then returns
// the address
loop := []byte{
@@ -72,18 +72,18 @@ func BenchmarkTransactionTrace(b *testing.B) {
byte(vm.PUSH1), 0, // jumpdestination
byte(vm.JUMP),
}
- alloc[common.HexToAddress("0x00000000000000000000000000000000deadbeef")] = core.GenesisAccount{
+ alloc[common.HexToAddress("0x00000000000000000000000000000000deadbeef")] = types.Account{
Nonce: 1,
Code: loop,
Balance: big.NewInt(1),
}
- alloc[from] = core.GenesisAccount{
+ alloc[from] = types.Account{
Nonce: 1,
Code: []byte{},
Balance: big.NewInt(500000000000000),
}
- triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), alloc, false, rawdb.HashScheme)
- defer triedb.Close()
+ state := tests.MakePreState(rawdb.NewMemoryDatabase(), alloc, false, rawdb.HashScheme)
+ defer state.Close()
// Create the tracer, the EVM environment and run it
tracer := logger.NewStructLogger(&logger.Config{
@@ -92,9 +92,8 @@ func BenchmarkTransactionTrace(b *testing.B) {
//EnableMemory: false,
//EnableReturnData: false,
})
- evm := vm.NewEVM(blockContext, txContext, statedb, params.AllEthashProtocolChanges, vm.Config{Tracer: tracer})
-
- msg, err := core.TransactionToMessage(tx, signer, nil)
+ evm := vm.NewEVM(blockContext, txContext, state.StateDB, params.AllEthashProtocolChanges, vm.Config{Tracer: tracer.Hooks()})
+ msg, err := core.TransactionToMessage(tx, signer, blockContext.BaseFee)
if err != nil {
b.Fatalf("failed to prepare transaction for tracing: %v", err)
}
@@ -103,7 +102,7 @@ func BenchmarkTransactionTrace(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
- snap := statedb.Snapshot()
+ snap := state.StateDB.Snapshot()
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
_, err = st.TransitionDb(context.Background())
@@ -111,7 +110,7 @@ func BenchmarkTransactionTrace(b *testing.B) {
b.Fatal(err)
}
- statedb.RevertToSnapshot(snap)
+ state.StateDB.RevertToSnapshot(snap)
if have, want := len(tracer.StructLogs()), 244752; have != want {
b.Fatalf("trace wrong, want %d steps, have %d", want, have)
@@ -120,48 +119,3 @@ func BenchmarkTransactionTrace(b *testing.B) {
tracer.Reset()
}
}
-
-func TestMemCopying(t *testing.T) {
- t.Parallel()
-
- for i, tc := range []struct {
- memsize int64
- offset int64
- size int64
- wantErr string
- wantSize int
- }{
- {0, 0, 100, "", 100}, // Should pad up to 100
- {0, 100, 0, "", 0}, // No need to pad (0 size)
- {100, 50, 100, "", 100}, // Should pad 100-150
- {100, 50, 5, "", 5}, // Wanted range fully within memory
- {100, -50, 0, "offset or size must not be negative", 0}, // Error
- {0, 1, 1024*1024 + 1, "reached limit for padding memory slice: 1048578", 0}, // Error
- {10, 0, 1024*1024 + 100, "reached limit for padding memory slice: 1048666", 0}, // Error
-
- } {
- mem := vm.NewMemory()
- mem.Resize(uint64(tc.memsize))
- cpy, err := GetMemoryCopyPadded(mem, tc.offset, tc.size)
-
- if want := tc.wantErr; want != "" {
- if err == nil {
- t.Fatalf("test %d: want '%v' have no error", i, want)
- }
-
- if have := err.Error(); want != have {
- t.Fatalf("test %d: want '%v' have '%v'", i, want, have)
- }
-
- continue
- }
-
- if err != nil {
- t.Fatalf("test %d: unexpected error: %v", i, err)
- }
-
- if want, have := tc.wantSize, len(cpy); have != want {
- t.Fatalf("test %d: want %v have %v", i, want, have)
- }
- }
-}
diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go
index 2745becbdb..24356d0fd5 100644
--- a/ethclient/ethclient.go
+++ b/ethclient/ethclient.go
@@ -134,25 +134,26 @@ type rpcBlock struct {
func (ec *Client) getBlock(ctx context.Context, method string, args ...interface{}) (*types.Block, error) {
var raw json.RawMessage
-
err := ec.c.CallContext(ctx, &raw, method, args...)
if err != nil {
return nil, err
- } else if len(raw) == 0 {
- return nil, ethereum.NotFound
}
+
// Decode header and transactions.
var head *types.Header
-
- var body rpcBlock
-
if err := json.Unmarshal(raw, &head); err != nil {
return nil, err
}
+ // When the block is not found, the API returns JSON null.
+ if head == nil {
+ return nil, ethereum.NotFound
+ }
+ var body rpcBlock
if err := json.Unmarshal(raw, &body); err != nil {
return nil, err
}
+
// Quick-verify transaction and uncle lists. This mostly helps with debugging the server.
if head.UncleHash == types.EmptyUncleHash && len(body.UncleHashes) > 0 {
return nil, errors.New("server returned non-empty uncle list but block header indicates no uncles")
@@ -205,8 +206,11 @@ func (ec *Client) getBlock(ctx context.Context, method string, args ...interface
txs[i] = tx.tx
}
-
- return types.NewBlockWithHeader(head).WithBody(txs, uncles), nil
+ return types.NewBlockWithHeader(head).WithBody(
+ types.Body{
+ Transactions: txs,
+ Uncles: uncles,
+ }), nil
}
// HeaderByHash returns the block header with the given hash.
@@ -339,10 +343,8 @@ func (ec *Client) TransactionReceipt(ctx context.Context, txHash common.Hash) (*
var r *types.Receipt
err := ec.c.CallContext(ctx, &r, "eth_getTransactionReceipt", txHash)
- if err == nil {
- if r == nil {
- return nil, ethereum.NotFound
- }
+ if err == nil && r == nil {
+ return nil, ethereum.NotFound
}
return r, err
@@ -721,6 +723,15 @@ func toCallArg(msg ethereum.CallMsg) interface{} {
if msg.GasTipCap != nil {
arg["maxPriorityFeePerGas"] = (*hexutil.Big)(msg.GasTipCap)
}
+ if msg.AccessList != nil {
+ arg["accessList"] = msg.AccessList
+ }
+ if msg.BlobGasFeeCap != nil {
+ arg["maxFeePerBlobGas"] = (*hexutil.Big)(msg.BlobGasFeeCap)
+ }
+ if msg.BlobHashes != nil {
+ arg["blobVersionedHashes"] = msg.BlobHashes
+ }
return arg
}
@@ -733,18 +744,20 @@ type rpcProgress struct {
PulledStates hexutil.Uint64
KnownStates hexutil.Uint64
- SyncedAccounts hexutil.Uint64
- SyncedAccountBytes hexutil.Uint64
- SyncedBytecodes hexutil.Uint64
- SyncedBytecodeBytes hexutil.Uint64
- SyncedStorage hexutil.Uint64
- SyncedStorageBytes hexutil.Uint64
- HealedTrienodes hexutil.Uint64
- HealedTrienodeBytes hexutil.Uint64
- HealedBytecodes hexutil.Uint64
- HealedBytecodeBytes hexutil.Uint64
- HealingTrienodes hexutil.Uint64
- HealingBytecode hexutil.Uint64
+ SyncedAccounts hexutil.Uint64
+ SyncedAccountBytes hexutil.Uint64
+ SyncedBytecodes hexutil.Uint64
+ SyncedBytecodeBytes hexutil.Uint64
+ SyncedStorage hexutil.Uint64
+ SyncedStorageBytes hexutil.Uint64
+ HealedTrienodes hexutil.Uint64
+ HealedTrienodeBytes hexutil.Uint64
+ HealedBytecodes hexutil.Uint64
+ HealedBytecodeBytes hexutil.Uint64
+ HealingTrienodes hexutil.Uint64
+ HealingBytecode hexutil.Uint64
+ TxIndexFinishedBlocks hexutil.Uint64
+ TxIndexRemainingBlocks hexutil.Uint64
}
func (p *rpcProgress) toSyncProgress() *ethereum.SyncProgress {
@@ -753,22 +766,24 @@ func (p *rpcProgress) toSyncProgress() *ethereum.SyncProgress {
}
return ðereum.SyncProgress{
- StartingBlock: uint64(p.StartingBlock),
- CurrentBlock: uint64(p.CurrentBlock),
- HighestBlock: uint64(p.HighestBlock),
- PulledStates: uint64(p.PulledStates),
- KnownStates: uint64(p.KnownStates),
- SyncedAccounts: uint64(p.SyncedAccounts),
- SyncedAccountBytes: uint64(p.SyncedAccountBytes),
- SyncedBytecodes: uint64(p.SyncedBytecodes),
- SyncedBytecodeBytes: uint64(p.SyncedBytecodeBytes),
- SyncedStorage: uint64(p.SyncedStorage),
- SyncedStorageBytes: uint64(p.SyncedStorageBytes),
- HealedTrienodes: uint64(p.HealedTrienodes),
- HealedTrienodeBytes: uint64(p.HealedTrienodeBytes),
- HealedBytecodes: uint64(p.HealedBytecodes),
- HealedBytecodeBytes: uint64(p.HealedBytecodeBytes),
- HealingTrienodes: uint64(p.HealingTrienodes),
- HealingBytecode: uint64(p.HealingBytecode),
+ StartingBlock: uint64(p.StartingBlock),
+ CurrentBlock: uint64(p.CurrentBlock),
+ HighestBlock: uint64(p.HighestBlock),
+ PulledStates: uint64(p.PulledStates),
+ KnownStates: uint64(p.KnownStates),
+ SyncedAccounts: uint64(p.SyncedAccounts),
+ SyncedAccountBytes: uint64(p.SyncedAccountBytes),
+ SyncedBytecodes: uint64(p.SyncedBytecodes),
+ SyncedBytecodeBytes: uint64(p.SyncedBytecodeBytes),
+ SyncedStorage: uint64(p.SyncedStorage),
+ SyncedStorageBytes: uint64(p.SyncedStorageBytes),
+ HealedTrienodes: uint64(p.HealedTrienodes),
+ HealedTrienodeBytes: uint64(p.HealedTrienodeBytes),
+ HealedBytecodes: uint64(p.HealedBytecodes),
+ HealedBytecodeBytes: uint64(p.HealedBytecodeBytes),
+ HealingTrienodes: uint64(p.HealingTrienodes),
+ HealingBytecode: uint64(p.HealingBytecode),
+ TxIndexFinishedBlocks: uint64(p.TxIndexFinishedBlocks),
+ TxIndexRemainingBlocks: uint64(p.TxIndexRemainingBlocks),
}
}
diff --git a/ethclient/ethclient_test.go b/ethclient/ethclient_test.go
index 22b3b244b0..637caf7ab8 100644
--- a/ethclient/ethclient_test.go
+++ b/ethclient/ethclient_test.go
@@ -176,7 +176,7 @@ func TestToFilterArg(t *testing.T) {
// var genesis = &core.Genesis{
// Config: params.AllEthashProtocolChanges,
-// Alloc: core.GenesisAlloc{testAddr: {Balance: testBalance}},
+// Alloc: types.GenesisAlloc{testAddr: {Balance: testBalance}},
// ExtraData: []byte("test genesis"),
// Timestamp: 9000,
// BaseFee: big.NewInt(params.InitialBaseFee),
diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go
index b97fe4f62e..e2071138c4 100644
--- a/ethclient/gethclient/gethclient.go
+++ b/ethclient/gethclient/gethclient.go
@@ -247,7 +247,21 @@ func toCallArg(msg ethereum.CallMsg) interface{} {
if msg.GasPrice != nil {
arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice)
}
-
+ if msg.GasFeeCap != nil {
+ arg["maxFeePerGas"] = (*hexutil.Big)(msg.GasFeeCap)
+ }
+ if msg.GasTipCap != nil {
+ arg["maxPriorityFeePerGas"] = (*hexutil.Big)(msg.GasTipCap)
+ }
+ if msg.AccessList != nil {
+ arg["accessList"] = msg.AccessList
+ }
+ if msg.BlobGasFeeCap != nil {
+ arg["maxFeePerBlobGas"] = (*hexutil.Big)(msg.BlobGasFeeCap)
+ }
+ if msg.BlobHashes != nil {
+ arg["blobVersionedHashes"] = msg.BlobHashes
+ }
return arg
}
diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go
index e062e45a93..99ad1e0f22 100644
--- a/ethclient/gethclient/gethclient_test.go
+++ b/ethclient/gethclient/gethclient_test.go
@@ -68,7 +68,7 @@ func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
n.RegisterAPIs([]rpc.API{{
Namespace: "eth",
- Service: filters.NewFilterAPI(filterSystem, false, config.BorLogs),
+ Service: filters.NewFilterAPI(filterSystem, config.BorLogs),
}})
// Import the test chain.
@@ -87,7 +87,7 @@ func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
func generateTestChain() (*core.Genesis, []*types.Block) {
genesis := &core.Genesis{
Config: params.AllEthashProtocolChanges,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
testAddr: {Balance: testBalance, Storage: map[common.Hash]common.Hash{testSlot: testValue}},
testContract: {Nonce: 1, Code: []byte{0x13, 0x37}},
testEmpty: {Balance: big.NewInt(1)},
@@ -161,7 +161,7 @@ func TestGethClient(t *testing.T) {
func(t *testing.T) { testCallContractWithBlockOverrides(t, client) },
},
// The testaccesslist is a bit time-sensitive: the newTestBackend imports
- // one block. The `testAcessList` fails if the miner has not yet created a
+ // one block. The `testAccessList` fails if the miner has not yet created a
// new pending-block after the import event.
// Hence: this test should be last, execute the tests serially.
{
@@ -191,7 +191,7 @@ func testAccessList(t *testing.T, client *rpc.Client) {
From: testAddr,
To: &common.Address{},
Gas: 21000,
- GasPrice: big.NewInt(765625000),
+ GasPrice: big.NewInt(875000000),
Value: big.NewInt(1),
}
@@ -331,7 +331,7 @@ func testGetProofNonExistent(t *testing.T, client *rpc.Client) {
t.Fatalf("invalid nonce, want: %v got: %v", 0, result.Nonce)
}
// test balance
- if result.Balance.Cmp(big.NewInt(0)) != 0 {
+ if result.Balance.Sign() != 0 {
t.Fatalf("invalid balance, want: %v got: %v", 0, result.Balance)
}
// test storage
diff --git a/ethclient/simulated/backend.go b/ethclient/simulated/backend.go
new file mode 100644
index 0000000000..7499622e35
--- /dev/null
+++ b/ethclient/simulated/backend.go
@@ -0,0 +1,193 @@
+// Copyright 2023 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 simulated
+
+import (
+ "errors"
+ "time"
+
+ "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/eth"
+ "github.com/ethereum/go-ethereum/eth/catalyst"
+ "github.com/ethereum/go-ethereum/eth/downloader"
+ "github.com/ethereum/go-ethereum/eth/ethconfig"
+ "github.com/ethereum/go-ethereum/eth/filters"
+ "github.com/ethereum/go-ethereum/ethclient"
+ "github.com/ethereum/go-ethereum/node"
+ "github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/rpc"
+)
+
+// Client exposes the methods provided by the Ethereum RPC client.
+type Client interface {
+ ethereum.BlockNumberReader
+ ethereum.ChainReader
+ ethereum.ChainStateReader
+ ethereum.ContractCaller
+ ethereum.GasEstimator
+ ethereum.GasPricer
+ ethereum.GasPricer1559
+ ethereum.FeeHistoryReader
+ ethereum.LogFilterer
+ ethereum.PendingStateReader
+ ethereum.PendingContractCaller
+ ethereum.TransactionReader
+ ethereum.TransactionSender
+ ethereum.ChainIDReader
+}
+
+// simClient wraps ethclient. This exists to prevent extracting ethclient.Client
+// from the Client interface returned by Backend.
+type simClient struct {
+ *ethclient.Client
+}
+
+// Backend is a simulated blockchain. You can use it to test your contracts or
+// other code that interacts with the Ethereum chain.
+type Backend struct {
+ node *node.Node
+ beacon *catalyst.SimulatedBeacon
+ client simClient
+}
+
+// NewBackend creates a new simulated blockchain that can be used as a backend for
+// contract bindings in unit tests.
+//
+// A simulated backend always uses chainID 1337.
+func NewBackend(alloc types.GenesisAlloc, options ...func(nodeConf *node.Config, ethConf *ethconfig.Config)) *Backend {
+ // Create the default configurations for the outer node shell and the Ethereum
+ // service to mutate with the options afterwards
+ nodeConf := node.DefaultConfig
+ nodeConf.DataDir = ""
+ nodeConf.P2P = p2p.Config{NoDiscovery: true}
+
+ ethConf := ethconfig.Defaults
+ ethConf.Genesis = &core.Genesis{
+ Config: params.AllDevChainProtocolChanges,
+ GasLimit: ethconfig.Defaults.Miner.GasCeil,
+ Alloc: alloc,
+ }
+ ethConf.SyncMode = downloader.FullSync
+ ethConf.TxPool.NoLocals = true
+
+ for _, option := range options {
+ option(&nodeConf, ðConf)
+ }
+ // Assemble the Ethereum stack to run the chain with
+ stack, err := node.New(&nodeConf)
+ if err != nil {
+ panic(err) // this should never happen
+ }
+ sim, err := newWithNode(stack, ðConf, 0)
+ if err != nil {
+ panic(err) // this should never happen
+ }
+ return sim
+}
+
+// newWithNode sets up a simulated backend on an existing node. The provided node
+// must not be started and will be started by this method.
+func newWithNode(stack *node.Node, conf *eth.Config, blockPeriod uint64) (*Backend, error) {
+ backend, err := eth.New(stack, conf)
+ if err != nil {
+ return nil, err
+ }
+ // Register the filter system
+ filterSystem := filters.NewFilterSystem(backend.APIBackend, filters.Config{})
+ stack.RegisterAPIs([]rpc.API{{
+ Namespace: "eth",
+ Service: filters.NewFilterAPI(filterSystem, true),
+ }})
+ // Start the node
+ if err := stack.Start(); err != nil {
+ return nil, err
+ }
+ // Set up the simulated beacon
+ beacon, err := catalyst.NewSimulatedBeacon(blockPeriod, backend)
+ if err != nil {
+ return nil, err
+ }
+ // Reorg our chain back to genesis
+ if err := beacon.Fork(backend.BlockChain().GetCanonicalHash(0)); err != nil {
+ return nil, err
+ }
+ return &Backend{
+ node: stack,
+ beacon: beacon,
+ client: simClient{ethclient.NewClient(stack.Attach())},
+ }, nil
+}
+
+// Close shuts down the simBackend.
+// The simulated backend can't be used afterwards.
+func (n *Backend) Close() error {
+ if n.client.Client != nil {
+ n.client.Close()
+ n.client = simClient{}
+ }
+ var err error
+ if n.beacon != nil {
+ err = n.beacon.Stop()
+ n.beacon = nil
+ }
+ if n.node != nil {
+ err = errors.Join(err, n.node.Close())
+ n.node = nil
+ }
+ return err
+}
+
+// Commit seals a block and moves the chain forward to a new empty block.
+func (n *Backend) Commit() common.Hash {
+ return n.beacon.Commit()
+}
+
+// Rollback removes all pending transactions, reverting to the last committed state.
+func (n *Backend) Rollback() {
+ n.beacon.Rollback()
+}
+
+// Fork creates a side-chain that can be used to simulate reorgs.
+//
+// This function should be called with the ancestor block where the new side
+// chain should be started. Transactions (old and new) can then be applied on
+// top and Commit-ed.
+//
+// Note, the side-chain will only become canonical (and trigger the events) when
+// it becomes longer. Until then CallContract will still operate on the current
+// canonical chain.
+//
+// There is a % chance that the side chain becomes canonical at the same length
+// to simulate live network behavior.
+func (n *Backend) Fork(parentHash common.Hash) error {
+ return n.beacon.Fork(parentHash)
+}
+
+// AdjustTime changes the block timestamp and creates a new block.
+// It can only be called on empty blocks.
+func (n *Backend) AdjustTime(adjustment time.Duration) error {
+ return n.beacon.AdjustTime(adjustment)
+}
+
+// Client returns a client that accesses the simulated chain.
+func (n *Backend) Client() Client {
+ return n.client
+}
diff --git a/ethclient/simulated/backend_test.go b/ethclient/simulated/backend_test.go
new file mode 100644
index 0000000000..8523b05808
--- /dev/null
+++ b/ethclient/simulated/backend_test.go
@@ -0,0 +1,314 @@
+// Copyright 2019 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 simulated
+
+import (
+ "context"
+ "crypto/ecdsa"
+ "math/big"
+ "math/rand"
+ "testing"
+ "time"
+
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+var _ bind.ContractBackend = (Client)(nil)
+
+var (
+ testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
+)
+
+func simTestBackend(testAddr common.Address) *Backend {
+ return NewBackend(
+ types.GenesisAlloc{
+ testAddr: {Balance: big.NewInt(10000000000000000)},
+ },
+ )
+}
+
+func newTx(sim *Backend, key *ecdsa.PrivateKey) (*types.Transaction, error) {
+ client := sim.Client()
+
+ // create a signed transaction to send
+ head, _ := client.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
+ gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(params.GWei))
+ addr := crypto.PubkeyToAddress(key.PublicKey)
+ chainid, _ := client.ChainID(context.Background())
+ nonce, err := client.PendingNonceAt(context.Background(), addr)
+ if err != nil {
+ return nil, err
+ }
+ tx := types.NewTx(&types.DynamicFeeTx{
+ ChainID: chainid,
+ Nonce: nonce,
+ GasTipCap: big.NewInt(params.GWei),
+ GasFeeCap: gasPrice,
+ Gas: 21000,
+ To: &addr,
+ })
+ return types.SignTx(tx, types.LatestSignerForChainID(chainid), key)
+}
+
+func TestNewBackend(t *testing.T) {
+ t.Skip("not relevant to bor")
+ sim := NewBackend(types.GenesisAlloc{})
+ defer sim.Close()
+
+ client := sim.Client()
+ num, err := client.BlockNumber(context.Background())
+ if err != nil {
+ t.Fatal(err)
+ }
+ if num != 0 {
+ t.Fatalf("expected 0 got %v", num)
+ }
+ // Create a block
+ sim.Commit()
+ num, err = client.BlockNumber(context.Background())
+ if err != nil {
+ t.Fatal(err)
+ }
+ if num != 1 {
+ t.Fatalf("expected 1 got %v", num)
+ }
+}
+
+func TestAdjustTime(t *testing.T) {
+ t.Skip("not relevant to bor")
+ sim := NewBackend(types.GenesisAlloc{})
+ defer sim.Close()
+
+ client := sim.Client()
+ block1, _ := client.BlockByNumber(context.Background(), nil)
+
+ // Create a block
+ if err := sim.AdjustTime(time.Minute); err != nil {
+ t.Fatal(err)
+ }
+ block2, _ := client.BlockByNumber(context.Background(), nil)
+ prevTime := block1.Time()
+ newTime := block2.Time()
+ if newTime-prevTime != uint64(time.Minute) {
+ t.Errorf("adjusted time not equal to 60 seconds. prev: %v, new: %v", prevTime, newTime)
+ }
+}
+
+func TestSendTransaction(t *testing.T) {
+ t.Skip("not relevant to bor")
+ sim := simTestBackend(testAddr)
+ defer sim.Close()
+
+ client := sim.Client()
+ ctx := context.Background()
+
+ signedTx, err := newTx(sim, testKey)
+ if err != nil {
+ t.Errorf("could not create transaction: %v", err)
+ }
+ // send tx to simulated backend
+ err = client.SendTransaction(ctx, signedTx)
+ if err != nil {
+ t.Errorf("could not add tx to pending block: %v", err)
+ }
+ sim.Commit()
+ block, err := client.BlockByNumber(ctx, big.NewInt(1))
+ if err != nil {
+ t.Errorf("could not get block at height 1: %v", err)
+ }
+
+ if signedTx.Hash() != block.Transactions()[0].Hash() {
+ t.Errorf("did not commit sent transaction. expected hash %v got hash %v", block.Transactions()[0].Hash(), signedTx.Hash())
+ }
+}
+
+// TestFork check that the chain length after a reorg is correct.
+// Steps:
+// 1. Save the current block which will serve as parent for the fork.
+// 2. Mine n blocks with n ∈ [0, 20].
+// 3. Assert that the chain length is n.
+// 4. Fork by using the parent block as ancestor.
+// 5. Mine n+1 blocks which should trigger a reorg.
+// 6. Assert that the chain length is n+1.
+// Since Commit() was called 2n+1 times in total,
+// having a chain length of just n+1 means that a reorg occurred.
+func TestFork(t *testing.T) {
+ t.Skip("not relevant to bor")
+ t.Parallel()
+ testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+ sim := simTestBackend(testAddr)
+ defer sim.Close()
+
+ client := sim.Client()
+ ctx := context.Background()
+
+ // 1.
+ parent, _ := client.HeaderByNumber(ctx, nil)
+
+ // 2.
+ n := int(rand.Int31n(21))
+ for i := 0; i < n; i++ {
+ sim.Commit()
+ }
+
+ // 3.
+ b, _ := client.BlockNumber(ctx)
+ if b != uint64(n) {
+ t.Error("wrong chain length")
+ }
+
+ // 4.
+ sim.Fork(parent.Hash())
+
+ // 5.
+ for i := 0; i < n+1; i++ {
+ sim.Commit()
+ }
+
+ // 6.
+ b, _ = client.BlockNumber(ctx)
+ if b != uint64(n+1) {
+ t.Error("wrong chain length")
+ }
+}
+
+// TestForkResendTx checks that re-sending a TX after a fork
+// is possible and does not cause a "nonce mismatch" panic.
+// Steps:
+// 1. Save the current block which will serve as parent for the fork.
+// 2. Send a transaction.
+// 3. Check that the TX is included in block 1.
+// 4. Fork by using the parent block as ancestor.
+// 5. Mine a block, Re-send the transaction and mine another one.
+// 6. Check that the TX is now included in block 2.
+func TestForkResendTx(t *testing.T) {
+ t.Skip("not relevant to bor")
+ t.Parallel()
+ testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+ sim := simTestBackend(testAddr)
+ defer sim.Close()
+
+ client := sim.Client()
+ ctx := context.Background()
+
+ // 1.
+ parent, _ := client.HeaderByNumber(ctx, nil)
+
+ // 2.
+ tx, err := newTx(sim, testKey)
+ if err != nil {
+ t.Fatalf("could not create transaction: %v", err)
+ }
+ client.SendTransaction(ctx, tx)
+ sim.Commit()
+
+ // 3.
+ receipt, _ := client.TransactionReceipt(ctx, tx.Hash())
+ if h := receipt.BlockNumber.Uint64(); h != 1 {
+ t.Errorf("TX included in wrong block: %d", h)
+ }
+
+ // 4.
+ if err := sim.Fork(parent.Hash()); err != nil {
+ t.Errorf("forking: %v", err)
+ }
+
+ // 5.
+ sim.Commit()
+ if err := client.SendTransaction(ctx, tx); err != nil {
+ t.Fatalf("sending transaction: %v", err)
+ }
+ sim.Commit()
+ receipt, _ = client.TransactionReceipt(ctx, tx.Hash())
+ if h := receipt.BlockNumber.Uint64(); h != 2 {
+ t.Errorf("TX included in wrong block: %d", h)
+ }
+}
+
+func TestCommitReturnValue(t *testing.T) {
+ t.Skip("not relevant to bor")
+ t.Parallel()
+ testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+ sim := simTestBackend(testAddr)
+ defer sim.Close()
+
+ client := sim.Client()
+ ctx := context.Background()
+
+ // Test if Commit returns the correct block hash
+ h1 := sim.Commit()
+ cur, _ := client.HeaderByNumber(ctx, nil)
+ if h1 != cur.Hash() {
+ t.Error("Commit did not return the hash of the last block.")
+ }
+
+ // Create a block in the original chain (containing a transaction to force different block hashes)
+ head, _ := client.HeaderByNumber(ctx, nil) // Should be child's, good enough
+ gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
+ _tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
+ tx, _ := types.SignTx(_tx, types.HomesteadSigner{}, testKey)
+ client.SendTransaction(ctx, tx)
+
+ h2 := sim.Commit()
+
+ // Create another block in the original chain
+ sim.Commit()
+
+ // Fork at the first bock
+ if err := sim.Fork(h1); err != nil {
+ t.Errorf("forking: %v", err)
+ }
+
+ // Test if Commit returns the correct block hash after the reorg
+ h2fork := sim.Commit()
+ if h2 == h2fork {
+ t.Error("The block in the fork and the original block are the same block!")
+ }
+ if header, err := client.HeaderByHash(ctx, h2fork); err != nil || header == nil {
+ t.Error("Could not retrieve the just created block (side-chain)")
+ }
+}
+
+// TestAdjustTimeAfterFork ensures that after a fork, AdjustTime uses the pending fork
+// block's parent rather than the canonical head's parent.
+func TestAdjustTimeAfterFork(t *testing.T) {
+ t.Parallel()
+ testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+ sim := simTestBackend(testAddr)
+ defer sim.Close()
+
+ client := sim.Client()
+ ctx := context.Background()
+
+ sim.Commit() // h1
+ h1, _ := client.HeaderByNumber(ctx, nil)
+
+ sim.Commit() // h2
+ sim.Fork(h1.Hash())
+ sim.AdjustTime(1 * time.Second)
+ sim.Commit()
+
+ head, _ := client.HeaderByNumber(ctx, nil)
+ if head.Number.Uint64() == 2 && head.ParentHash != h1.Hash() {
+ t.Errorf("failed to build block on fork")
+ }
+}
diff --git a/ethclient/simulated/options.go b/ethclient/simulated/options.go
new file mode 100644
index 0000000000..40bcb37bd1
--- /dev/null
+++ b/ethclient/simulated/options.go
@@ -0,0 +1,55 @@
+// Copyright 2024 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 simulated
+
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/eth/ethconfig"
+ "github.com/ethereum/go-ethereum/node"
+)
+
+// WithBlockGasLimit configures the simulated backend to target a specific gas limit
+// when producing blocks.
+func WithBlockGasLimit(gaslimit uint64) func(nodeConf *node.Config, ethConf *ethconfig.Config) {
+ return func(nodeConf *node.Config, ethConf *ethconfig.Config) {
+ ethConf.Genesis.GasLimit = gaslimit
+ ethConf.Miner.GasCeil = gaslimit
+ }
+}
+
+// WithCallGasLimit configures the simulated backend to cap eth_calls to a specific
+// gas limit when running client operations.
+func WithCallGasLimit(gaslimit uint64) func(nodeConf *node.Config, ethConf *ethconfig.Config) {
+ return func(nodeConf *node.Config, ethConf *ethconfig.Config) {
+ ethConf.RPCGasCap = gaslimit
+ }
+}
+
+// WithMinerMinTip configures the simulated backend to require a specific minimum
+// gas tip for a transaction to be included.
+//
+// 0 is not possible as a live Geth node would reject that due to DoS protection,
+// so the simulated backend will replicate that behavior for consistency.
+func WithMinerMinTip(tip *big.Int) func(nodeConf *node.Config, ethConf *ethconfig.Config) {
+ if tip == nil || tip.Sign() <= 0 {
+ panic("invalid miner minimum tip")
+ }
+ return func(nodeConf *node.Config, ethConf *ethconfig.Config) {
+ ethConf.Miner.GasPrice = tip
+ }
+}
diff --git a/ethclient/simulated/options_test.go b/ethclient/simulated/options_test.go
new file mode 100644
index 0000000000..a0182f77bd
--- /dev/null
+++ b/ethclient/simulated/options_test.go
@@ -0,0 +1,75 @@
+// Copyright 2024 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 simulated
+
+import (
+ "context"
+ "math/big"
+ "strings"
+ "testing"
+
+ "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+// Tests that the simulator starts with the initial gas limit in the genesis block,
+// and that it keeps the same target value.
+func TestWithBlockGasLimitOption(t *testing.T) {
+ t.Skip("not relevant to bor")
+ // Construct a simulator, targeting a different gas limit
+ sim := NewBackend(types.GenesisAlloc{}, WithBlockGasLimit(12_345_678))
+ defer sim.Close()
+
+ client := sim.Client()
+ genesis, err := client.BlockByNumber(context.Background(), big.NewInt(0))
+ if err != nil {
+ t.Fatalf("failed to retrieve genesis block: %v", err)
+ }
+ if genesis.GasLimit() != 12_345_678 {
+ t.Errorf("genesis gas limit mismatch: have %v, want %v", genesis.GasLimit(), 12_345_678)
+ }
+ // Produce a number of blocks and verify the locked in gas target
+ sim.Commit()
+ head, err := client.BlockByNumber(context.Background(), big.NewInt(1))
+ if err != nil {
+ t.Fatalf("failed to retrieve head block: %v", err)
+ }
+ if head.GasLimit() != 12_345_678 {
+ t.Errorf("head gas limit mismatch: have %v, want %v", head.GasLimit(), 12_345_678)
+ }
+}
+
+// Tests that the simulator honors the RPC call caps set by the options.
+func TestWithCallGasLimitOption(t *testing.T) {
+ // Construct a simulator, targeting a different gas limit
+ sim := NewBackend(types.GenesisAlloc{
+ testAddr: {Balance: big.NewInt(10000000000000000)},
+ }, WithCallGasLimit(params.TxGas-1))
+ defer sim.Close()
+
+ client := sim.Client()
+ _, err := client.CallContract(context.Background(), ethereum.CallMsg{
+ From: testAddr,
+ To: &testAddr,
+ Gas: 21000,
+ }, nil)
+ if !strings.Contains(err.Error(), core.ErrIntrinsicGas.Error()) {
+ t.Fatalf("error mismatch: have %v, want %v", err, core.ErrIntrinsicGas)
+ }
+}
diff --git a/ethdb/database.go b/ethdb/database.go
index 4add13e79f..67df498f8f 100644
--- a/ethdb/database.go
+++ b/ethdb/database.go
@@ -39,8 +39,8 @@ type KeyValueWriter interface {
// KeyValueStater wraps the Stat method of a backing data store.
type KeyValueStater interface {
- // Stat returns a particular internal stat of the database.
- Stat(property string) (string, error)
+ // Stat returns the statistic data of the database.
+ Stat() (string, error)
}
// Compacter wraps the Compact method of a backing data store.
@@ -88,8 +88,8 @@ type AncientReaderOp interface {
// Ancients returns the ancient item numbers in the ancient store.
Ancients() (uint64, error)
- // Tail returns the number of first stored item in the freezer.
- // This number can also be interpreted as the total deleted item numbers.
+ // Tail returns the number of first stored item in the ancient store.
+ // This number can also be interpreted as the total deleted items.
Tail() (uint64, error)
// AncientSize returns the ancient size of the specified category.
@@ -107,7 +107,7 @@ type AncientReader interface {
AncientReaderOp
// ReadAncients runs the given read operation while ensuring that no writes take place
- // on the underlying freezer.
+ // on the underlying ancient store.
ReadAncients(fn func(AncientReaderOp) error) (err error)
}
@@ -147,11 +147,15 @@ type AncientWriteOp interface {
AppendRaw(kind string, number uint64, item []byte) error
}
-// AncientStater wraps the Stat method of a backing data store.
+// AncientStater wraps the Stat method of a backing ancient store.
type AncientStater interface {
- // AncientDatadir returns the path of root ancient directory. Empty string
- // will be returned if ancient store is not enabled at all. The returned
- // path can be used to construct the path of other freezers.
+ // AncientDatadir returns the path of the ancient store directory.
+ //
+ // If the ancient store is not activated, an error is returned.
+ // If an ephemeral ancient store is used, an empty path is returned.
+ //
+ // The path returned by AncientDatadir can be used as the root path
+ // of the ancient store to construct paths for other sub ancient stores.
AncientDatadir() (string, error)
}
@@ -177,15 +181,23 @@ type Stater interface {
}
// AncientStore contains all the methods required to allow handling different
-// ancient data stores backing immutable chain data store.
+// ancient data stores backing immutable data store.
type AncientStore interface {
AncientReader
AncientWriter
io.Closer
}
+// ResettableAncientStore extends the AncientStore interface by adding a Reset method.
+type ResettableAncientStore interface {
+ AncientStore
+
+ // Reset is designed to reset the entire ancient store to its default state.
+ Reset() error
+}
+
// Database contains all the methods required by the high level database to not
-// only access the key-value data store but also the chain freezer.
+// only access the key-value data store but also the ancient chain store.
//
//go:generate mockgen -destination=../eth/filters/IDatabase.go -package=filters . Database
type Database interface {
diff --git a/ethdb/dbtest/testsuite.go b/ethdb/dbtest/testsuite.go
index 7310a61359..ea14302ad2 100644
--- a/ethdb/dbtest/testsuite.go
+++ b/ethdb/dbtest/testsuite.go
@@ -19,12 +19,11 @@ package dbtest
import (
"bytes"
"crypto/rand"
- "reflect"
+ "slices"
"sort"
"testing"
"github.com/ethereum/go-ethereum/ethdb"
- "golang.org/x/exp/slices"
)
// TestDatabaseSuite runs a suite of tests against a KeyValueStore database
@@ -156,8 +155,7 @@ func TestDatabaseSuite(t *testing.T, New func() ethdb.KeyValueStore) {
if err := it.Error(); err != nil {
t.Fatal(err)
}
-
- if !reflect.DeepEqual(got, want) {
+ if !slices.Equal(got, want) {
t.Errorf("Iterator: got: %s; want: %s", got, want)
}
}
@@ -169,8 +167,7 @@ func TestDatabaseSuite(t *testing.T, New func() ethdb.KeyValueStore) {
if err := it.Error(); err != nil {
t.Fatal(err)
}
-
- if !reflect.DeepEqual(got, want) {
+ if !slices.Equal(got, want) {
t.Errorf("IteratorWith(1,nil): got: %s; want: %s", got, want)
}
}
@@ -182,8 +179,7 @@ func TestDatabaseSuite(t *testing.T, New func() ethdb.KeyValueStore) {
if err := it.Error(); err != nil {
t.Fatal(err)
}
-
- if !reflect.DeepEqual(got, want) {
+ if !slices.Equal(got, want) {
t.Errorf("IteratorWith(5,nil): got: %s; want: %s", got, want)
}
}
@@ -195,8 +191,7 @@ func TestDatabaseSuite(t *testing.T, New func() ethdb.KeyValueStore) {
if err := it.Error(); err != nil {
t.Fatal(err)
}
-
- if !reflect.DeepEqual(got, want) {
+ if !slices.Equal(got, want) {
t.Errorf("IteratorWith(nil,2): got: %s; want: %s", got, want)
}
}
@@ -208,8 +203,7 @@ func TestDatabaseSuite(t *testing.T, New func() ethdb.KeyValueStore) {
if err := it.Error(); err != nil {
t.Fatal(err)
}
-
- if !reflect.DeepEqual(got, want) {
+ if !slices.Equal(got, want) {
t.Errorf("IteratorWith(nil,5): got: %s; want: %s", got, want)
}
}
@@ -278,7 +272,7 @@ func TestDatabaseSuite(t *testing.T, New func() ethdb.KeyValueStore) {
{
it := db.NewIterator(nil, nil)
- if got, want := iterateKeys(it), []string{"1", "2", "3", "4"}; !reflect.DeepEqual(got, want) {
+ if got, want := iterateKeys(it), []string{"1", "2", "3", "4"}; !slices.Equal(got, want) {
t.Errorf("got: %s; want: %s", got, want)
}
}
@@ -302,7 +296,7 @@ func TestDatabaseSuite(t *testing.T, New func() ethdb.KeyValueStore) {
{
it := db.NewIterator(nil, nil)
- if got, want := iterateKeys(it), []string{"2", "3", "4", "5", "6"}; !reflect.DeepEqual(got, want) {
+ if got, want := iterateKeys(it), []string{"2", "3", "4", "5", "6"}; !slices.Equal(got, want) {
t.Errorf("got: %s; want: %s", got, want)
}
}
@@ -331,7 +325,7 @@ func TestDatabaseSuite(t *testing.T, New func() ethdb.KeyValueStore) {
}
it := db.NewIterator(nil, nil)
- if got := iterateKeys(it); !reflect.DeepEqual(got, want) {
+ if got := iterateKeys(it); !slices.Equal(got, want) {
t.Errorf("got: %s; want: %s", got, want)
}
})
@@ -409,7 +403,7 @@ func TestDatabaseSuite(t *testing.T, New func() ethdb.KeyValueStore) {
}
})
- t.Run("OperatonsAfterClose", func(t *testing.T) {
+ t.Run("OperationsAfterClose", func(t *testing.T) {
db := New()
db.Put([]byte("key"), []byte("value"))
db.Close()
@@ -557,10 +551,10 @@ func iterateKeys(it ethdb.Iterator) []string {
return keys
}
-// randomHash generates a random blob of data and returns it as a hash.
-func randBytes(length int) []byte {
- buf := make([]byte, length)
- if n, err := rand.Read(buf); n != length || err != nil {
+// randBytes generates a random blob of data.
+func randBytes(len int) []byte {
+ buf := make([]byte, len)
+ if n, err := rand.Read(buf); n != len || err != nil {
panic(err)
}
@@ -577,7 +571,7 @@ func makeDataset(size, ksize, vsize int, order bool) ([][]byte, [][]byte) {
}
if order {
- slices.SortFunc(keys, func(a, b []byte) int { return bytes.Compare(a, b) })
+ slices.SortFunc(keys, bytes.Compare)
}
return keys, vals
diff --git a/ethdb/leveldb/leveldb.go b/ethdb/leveldb/leveldb.go
index 189f317da5..75e1bd2e25 100644
--- a/ethdb/leveldb/leveldb.go
+++ b/ethdb/leveldb/leveldb.go
@@ -22,7 +22,6 @@ package leveldb
import (
"fmt"
- "strings"
"sync"
"time"
@@ -267,14 +266,53 @@ func (db *Database) NewSnapshot() (ethdb.Snapshot, error) {
return &snapshot{db: snap}, nil
}
-// Stat returns a particular internal stat of the database.
-func (db *Database) Stat(property string) (string, error) {
- if property == "" {
- property = "leveldb.stats"
- } else if !strings.HasPrefix(property, "leveldb.") {
- property = "leveldb." + property
+// Stat returns the statistic data of the database.
+func (db *Database) Stat() (string, error) {
+ var stats leveldb.DBStats
+ if err := db.db.Stats(&stats); err != nil {
+ return "", err
}
- return db.db.GetProperty(property)
+ var (
+ message string
+ totalRead int64
+ totalWrite int64
+ totalSize int64
+ totalTables int
+ totalDuration time.Duration
+ )
+ if len(stats.LevelSizes) > 0 {
+ message += " Level | Tables | Size(MB) | Time(sec) | Read(MB) | Write(MB)\n" +
+ "-------+------------+---------------+---------------+---------------+---------------\n"
+ for level, size := range stats.LevelSizes {
+ read := stats.LevelRead[level]
+ write := stats.LevelWrite[level]
+ duration := stats.LevelDurations[level]
+ tables := stats.LevelTablesCounts[level]
+
+ if tables == 0 && duration == 0 {
+ continue
+ }
+ totalTables += tables
+ totalSize += size
+ totalRead += read
+ totalWrite += write
+ totalDuration += duration
+ message += fmt.Sprintf(" %3d | %10d | %13.5f | %13.5f | %13.5f | %13.5f\n",
+ level, tables, float64(size)/1048576.0, duration.Seconds(),
+ float64(read)/1048576.0, float64(write)/1048576.0)
+ }
+ message += "-------+------------+---------------+---------------+---------------+---------------\n"
+ message += fmt.Sprintf(" Total | %10d | %13.5f | %13.5f | %13.5f | %13.5f\n",
+ totalTables, float64(totalSize)/1048576.0, totalDuration.Seconds(),
+ float64(totalRead)/1048576.0, float64(totalWrite)/1048576.0)
+ message += "-------+------------+---------------+---------------+---------------+---------------\n\n"
+ }
+ message += fmt.Sprintf("Read(MB):%.5f Write(MB):%.5f\n", float64(stats.IORead)/1048576.0, float64(stats.IOWrite)/1048576.0)
+ message += fmt.Sprintf("BlockCache(MB):%.5f FileCache:%d\n", float64(stats.BlockCacheSize)/1048576.0, stats.OpenedTablesCount)
+ message += fmt.Sprintf("MemoryCompaction:%d Level0Compaction:%d NonLevel0Compaction:%d SeekCompaction:%d\n", stats.MemComp, stats.Level0Comp, stats.NonLevel0Comp, stats.SeekComp)
+ message += fmt.Sprintf("WriteDelayCount:%d WriteDelayDuration:%s Paused:%t\n", stats.WriteDelayCount, common.PrettyDuration(stats.WriteDelayDuration), stats.WritePaused)
+ message += fmt.Sprintf("Snapshots:%d Iterators:%d\n", stats.AliveSnapshots, stats.AliveIterators)
+ return message, nil
}
// Compact flattens the underlying data store for the given key range. In essence,
@@ -434,7 +472,7 @@ func (b *batch) Put(key, value []byte) error {
return nil
}
-// Delete inserts the a key removal into the batch for later committing.
+// Delete inserts the key removal into the batch for later committing.
func (b *batch) Delete(key []byte) error {
b.b.Delete(key)
b.size += len(key)
diff --git a/ethdb/memorydb/memorydb.go b/ethdb/memorydb/memorydb.go
index 05cab478e1..1eb3166d02 100644
--- a/ethdb/memorydb/memorydb.go
+++ b/ethdb/memorydb/memorydb.go
@@ -194,9 +194,9 @@ func (db *Database) NewSnapshot() (ethdb.Snapshot, error) {
return newSnapshot(db), nil
}
-// Stat returns a particular internal stat of the database.
-func (db *Database) Stat(property string) (string, error) {
- return "", errors.New("unknown property")
+// Stat returns the statistic data of the database.
+func (db *Database) Stat() (string, error) {
+ return "", nil
}
// Compact is not supported on a memory database, but there's no need either as
@@ -240,7 +240,7 @@ func (b *batch) Put(key, value []byte) error {
return nil
}
-// Delete inserts the a key removal into the batch for later committing.
+// Delete inserts the key removal into the batch for later committing.
func (b *batch) Delete(key []byte) error {
b.writes = append(b.writes, keyvalue{string(key), nil, true})
b.size += len(key)
diff --git a/ethdb/pebble/pebble.go b/ethdb/pebble/pebble.go
index 3001cb1c6a..eadc85ff80 100644
--- a/ethdb/pebble/pebble.go
+++ b/ethdb/pebble/pebble.go
@@ -46,6 +46,10 @@ const (
// metricsGatheringInterval specifies the interval to retrieve pebble database
// compaction, io and pause stats to report to the user.
metricsGatheringInterval = 3 * time.Second
+
+ // degradationWarnInterval specifies how often warning should be printed if the
+ // leveldb database cannot keep up with requested writes.
+ degradationWarnInterval = time.Minute
)
// Database is a persistent key-value store based on the pebble storage engine.
@@ -77,14 +81,16 @@ type Database struct {
log log.Logger // Contextual logger tracking the database path
- activeComp int // Current number of active compactions
- compStartTime time.Time // The start time of the earliest currently-active compaction
- compTime atomic.Int64 // Total time spent in compaction in ns
- level0Comp atomic.Uint32 // Total number of level-zero compactions
- nonLevel0Comp atomic.Uint32 // Total number of non level-zero compactions
- writeDelayStartTime time.Time // The start time of the latest write stall
- writeDelayCount atomic.Int64 // Total number of write stall counts
- writeDelayTime atomic.Int64 // Total time spent in write stalls
+ activeComp int // Current number of active compactions
+ compStartTime time.Time // The start time of the earliest currently-active compaction
+ compTime atomic.Int64 // Total time spent in compaction in ns
+ level0Comp atomic.Uint32 // Total number of level-zero compactions
+ nonLevel0Comp atomic.Uint32 // Total number of non level-zero compactions
+
+ writeStalled atomic.Bool // Flag whether the write is stalled
+ writeDelayStartTime time.Time // The start time of the latest write stall
+ writeDelayCount atomic.Int64 // Total number of write stall counts
+ writeDelayTime atomic.Int64 // Total time spent in write stalls
writeOptions *pebble.WriteOptions
}
@@ -117,10 +123,13 @@ func (d *Database) onCompactionEnd(info pebble.CompactionInfo) {
func (d *Database) onWriteStallBegin(b pebble.WriteStallBeginInfo) {
d.writeDelayStartTime = time.Now()
+ d.writeDelayCount.Add(1)
+ d.writeStalled.Store(true)
}
func (d *Database) onWriteStallEnd() {
d.writeDelayTime.Add(int64(time.Since(d.writeDelayStartTime)))
+ d.writeStalled.Store(false)
}
// panicLogger is just a noop logger to disable Pebble's internal logger.
@@ -206,7 +215,7 @@ func New(file string, cache int, handles int, namespace string, readonly bool, e
// The default compaction concurrency(1 thread),
// Here use all available CPUs for faster compaction.
- MaxConcurrentCompactions: func() int { return runtime.NumCPU() },
+ MaxConcurrentCompactions: runtime.NumCPU,
// Per-level options. Options for at least one level must be specified. The
// options for the last level are used for all subsequent levels.
@@ -240,19 +249,19 @@ func New(file string, cache int, handles int, namespace string, readonly bool, e
db.db = innerDB
- db.compTimeMeter = metrics.NewRegisteredMeter(namespace+"compact/time", nil)
- db.compReadMeter = metrics.NewRegisteredMeter(namespace+"compact/input", nil)
- db.compWriteMeter = metrics.NewRegisteredMeter(namespace+"compact/output", nil)
- db.diskSizeGauge = metrics.NewRegisteredGauge(namespace+"disk/size", nil)
- db.diskReadMeter = metrics.NewRegisteredMeter(namespace+"disk/read", nil)
- db.diskWriteMeter = metrics.NewRegisteredMeter(namespace+"disk/write", nil)
- db.writeDelayMeter = metrics.NewRegisteredMeter(namespace+"compact/writedelay/duration", nil)
- db.writeDelayNMeter = metrics.NewRegisteredMeter(namespace+"compact/writedelay/counter", nil)
- db.memCompGauge = metrics.NewRegisteredGauge(namespace+"compact/memory", nil)
- db.level0CompGauge = metrics.NewRegisteredGauge(namespace+"compact/level0", nil)
- db.nonlevel0CompGauge = metrics.NewRegisteredGauge(namespace+"compact/nonlevel0", nil)
- db.seekCompGauge = metrics.NewRegisteredGauge(namespace+"compact/seek", nil)
- db.manualMemAllocGauge = metrics.NewRegisteredGauge(namespace+"memory/manualalloc", nil)
+ db.compTimeMeter = metrics.GetOrRegisterMeter(namespace+"compact/time", nil)
+ db.compReadMeter = metrics.GetOrRegisterMeter(namespace+"compact/input", nil)
+ db.compWriteMeter = metrics.GetOrRegisterMeter(namespace+"compact/output", nil)
+ db.diskSizeGauge = metrics.GetOrRegisterGauge(namespace+"disk/size", nil)
+ db.diskReadMeter = metrics.GetOrRegisterMeter(namespace+"disk/read", nil)
+ db.diskWriteMeter = metrics.GetOrRegisterMeter(namespace+"disk/write", nil)
+ db.writeDelayMeter = metrics.GetOrRegisterMeter(namespace+"compact/writedelay/duration", nil)
+ db.writeDelayNMeter = metrics.GetOrRegisterMeter(namespace+"compact/writedelay/counter", nil)
+ db.memCompGauge = metrics.GetOrRegisterGauge(namespace+"compact/memory", nil)
+ db.level0CompGauge = metrics.GetOrRegisterGauge(namespace+"compact/level0", nil)
+ db.nonlevel0CompGauge = metrics.GetOrRegisterGauge(namespace+"compact/nonlevel0", nil)
+ db.seekCompGauge = metrics.GetOrRegisterGauge(namespace+"compact/seek", nil)
+ db.manualMemAllocGauge = metrics.GetOrRegisterGauge(namespace+"memory/manualalloc", nil)
// Start up the metrics gathering and return
go db.meter(metricsGatheringInterval, namespace)
@@ -430,10 +439,8 @@ func upperBound(prefix []byte) (limit []byte) {
}
// Stat returns the internal metrics of Pebble in a text format. It's a developer
-// method to read everything there is to read independent of Pebble version.
-//
-// The property is unused in Pebble as there's only one thing to retrieve.
-func (d *Database) Stat(property string) (string, error) {
+// method to read everything there is to read, independent of Pebble version.
+func (d *Database) Stat() (string, error) {
return d.db.Metrics().String(), nil
}
@@ -476,13 +483,15 @@ func (d *Database) meter(refresh time.Duration, namespace string) {
// Create storage and warning log tracer for write delay.
var (
- compTimes [2]int64
- writeDelayTimes [2]int64
- writeDelayCounts [2]int64
- compWrites [2]int64
- compReads [2]int64
+ compTimes [2]int64
+ compWrites [2]int64
+ compReads [2]int64
nWrites [2]int64
+
+ writeDelayTimes [2]int64
+ writeDelayCounts [2]int64
+ lastWriteStallReport time.Time
)
// Iterate ad infinitum and collect the stats
@@ -524,7 +533,13 @@ func (d *Database) meter(refresh time.Duration, namespace string) {
if d.writeDelayMeter != nil {
d.writeDelayMeter.Mark(writeDelayTimes[i%2] - writeDelayTimes[(i-1)%2])
}
-
+ // Print a warning log if writing has been stalled for a while. The log will
+ // be printed per minute to avoid overwhelming users.
+ if d.writeStalled.Load() && writeDelayCounts[i%2] == writeDelayCounts[(i-1)%2] &&
+ time.Now().After(lastWriteStallReport.Add(degradationWarnInterval)) {
+ d.log.Warn("Database compacting, degraded performance")
+ lastWriteStallReport = time.Now()
+ }
if d.compTimeMeter != nil {
d.compTimeMeter.Mark(compTimes[i%2] - compTimes[(i-1)%2])
}
@@ -559,7 +574,7 @@ func (d *Database) meter(refresh time.Duration, namespace string) {
for i, level := range stats.Levels {
// Append metrics for additional layers
if i >= len(d.levelsGauge) {
- d.levelsGauge = append(d.levelsGauge, metrics.NewRegisteredGauge(namespace+fmt.Sprintf("tables/level%v", i), nil))
+ d.levelsGauge = append(d.levelsGauge, metrics.GetOrRegisterGauge(namespace+fmt.Sprintf("tables/level%v", i), nil))
}
d.levelsGauge[i].Update(level.NumFiles)
}
@@ -626,7 +641,10 @@ func (b *batch) Replay(w ethdb.KeyValueWriter) error {
reader := b.b.Reader()
for {
- kind, k, v, ok := reader.Next()
+ kind, k, v, ok, err := reader.Next()
+ if err != nil {
+ return err
+ }
if !ok {
break
}
diff --git a/ethdb/remotedb/remotedb.go b/ethdb/remotedb/remotedb.go
index f33d2bb9c0..29935eb7d1 100644
--- a/ethdb/remotedb/remotedb.go
+++ b/ethdb/remotedb/remotedb.go
@@ -143,8 +143,8 @@ func (db *Database) NewIterator(prefix []byte, start []byte) ethdb.Iterator {
panic("not supported")
}
-func (db *Database) Stat(property string) (string, error) {
- panic("not supported")
+func (db *Database) Stat() (string, error) {
+ return "", nil
}
func (db *Database) AncientDatadir() (string, error) {
diff --git a/ethstats/ethstats.go b/ethstats/ethstats.go
index f281725965..cd6c34352e 100644
--- a/ethstats/ethstats.go
+++ b/ethstats/ethstats.go
@@ -39,7 +39,6 @@ import (
ethproto "github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rpc"
@@ -100,13 +99,6 @@ var EthstatsData = &EthstatsDataType{
kv: make(map[string]string),
}
-// miningNodeBackend encompasses the functionality necessary for a mining node
-// reporting to ethstats
-type miningNodeBackend interface {
- fullNodeBackend
- Miner() *miner.Miner
-}
-
// Service implements an Ethereum netstats reporting daemon that pushes local
// chain statistics up to a monitoring server.
type Service struct {
@@ -627,10 +619,13 @@ func (s *Service) reportLatency(conn *connWrapper) error {
return err
}
// Wait for the pong request to arrive back
+ timer := time.NewTimer(5 * time.Second)
+ defer timer.Stop()
+
select {
case <-s.pongCh:
// Pong delivered, report the latency
- case <-time.After(5 * time.Second):
+ case <-timer.C:
// Ping timeout, abort
return errors.New("ping timed out")
}
@@ -734,8 +729,6 @@ func (s *Service) assembleBlockStats(block *types.Block) *blockStats {
}
}
- // It's weird, but it's possible that the block is nil here.
- // even though the check for error is done above.
if block == nil {
return nil
}
@@ -924,30 +917,21 @@ func (s *Service) reportChain2Head(conn *connWrapper, chain2HeadData *core.Chain
type nodeStats struct {
Active bool `json:"active"`
Syncing bool `json:"syncing"`
- Mining bool `json:"mining"`
- Hashrate int `json:"hashrate"`
Peers int `json:"peers"`
GasPrice int `json:"gasPrice"`
Uptime int `json:"uptime"`
}
-// reportStats retrieves various stats about the node at the networking and
-// mining layer and reports it to the stats server.
+// reportStats retrieves various stats about the node at the networking layer
+// and reports it to the stats server.
func (s *Service) reportStats(conn *connWrapper) error {
- // Gather the syncing and mining infos from the local miner instance
+ // Gather the syncing infos from the local miner instance
var (
- mining bool
- hashrate int
syncing bool
gasprice int
)
// check if backend is a full node
if fullBackend, ok := s.backend.(fullNodeBackend); ok {
- if miningBackend, ok := s.backend.(miningNodeBackend); ok {
- mining = miningBackend.Miner().Mining()
- hashrate = int(miningBackend.Miner().Hashrate())
- }
-
sync := fullBackend.SyncProgress()
syncing = fullBackend.CurrentHeader().Number.Uint64() >= sync.HighestBlock
@@ -968,8 +952,6 @@ func (s *Service) reportStats(conn *connWrapper) error {
"id": s.node,
"stats": &nodeStats{
Active: true,
- Mining: mining,
- Hashrate: hashrate,
Peers: s.server.PeerCount(),
GasPrice: gasprice,
Syncing: syncing,
diff --git a/ethstats/ethstats_test.go b/ethstats/ethstats_test.go
index 2237470fca..aed4356f4a 100644
--- a/ethstats/ethstats_test.go
+++ b/ethstats/ethstats_test.go
@@ -17,8 +17,17 @@
package ethstats
import (
+ "context"
+ "math/big"
"strconv"
"testing"
+
+ "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/rpc"
)
func TestParseEthstatsURL(t *testing.T) {
@@ -83,3 +92,63 @@ func TestParseEthstatsURL(t *testing.T) {
}
}
}
+
+// MockBackend is a mock implementation of the backend interface
+type MockFullNodeBackend struct{}
+
+func (m *MockFullNodeBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
+ return nil
+}
+
+func (m *MockFullNodeBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
+ return nil
+}
+
+func (m *MockFullNodeBackend) CurrentHeader() *types.Header {
+ return &types.Header{}
+}
+
+func (m *MockFullNodeBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
+ return nil, nil
+}
+
+func (m *MockFullNodeBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
+ return big.NewInt(0)
+}
+
+func (m *MockFullNodeBackend) Stats() (pending int, queued int) {
+ return 0, 0
+}
+
+func (m *MockFullNodeBackend) SyncProgress() ethereum.SyncProgress {
+ return ethereum.SyncProgress{}
+}
+
+func (m *MockFullNodeBackend) SubscribeChain2HeadEvent(ch chan<- core.Chain2HeadEvent) event.Subscription {
+ return nil
+}
+
+func (m *MockFullNodeBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
+ return nil, nil
+}
+
+func (m *MockFullNodeBackend) CurrentBlock() *types.Header {
+ return &types.Header{Number: big.NewInt(1)}
+}
+
+func (m *MockFullNodeBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
+ return big.NewInt(0), nil
+}
+
+func TestAssembleBlockStats_NilBlock(t *testing.T) {
+ mockBackend := &MockFullNodeBackend{}
+ service := &Service{
+ backend: mockBackend,
+ }
+
+ result := service.assembleBlockStats(nil)
+
+ if result != nil {
+ t.Errorf("Expected nil, got %v", result)
+ }
+}
diff --git a/event/multisub.go b/event/multisub.go
index 5c8d2df48c..1f0af2a292 100644
--- a/event/multisub.go
+++ b/event/multisub.go
@@ -17,7 +17,7 @@
package event
// JoinSubscriptions joins multiple subscriptions to be able to track them as
-// one entity and collectively cancel them of consume any errors from them.
+// one entity and collectively cancel them or consume any errors from them.
func JoinSubscriptions(subs ...Subscription) Subscription {
return NewSubscription(func(unsubbed <-chan struct{}) error {
// Unsubscribe all subscriptions before returning
diff --git a/go.mod b/go.mod
index 156afbfc05..a976c95e21 100644
--- a/go.mod
+++ b/go.mod
@@ -5,50 +5,51 @@ go 1.22
toolchain go1.22.1
require (
- github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.1
- github.com/BurntSushi/toml v1.3.2
+ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2
+ github.com/BurntSushi/toml v1.4.0
github.com/JekaMas/go-grpc-net-conn v0.0.0-20220708155319-6aff21f2d13d
github.com/JekaMas/workerpool v1.1.8
- github.com/Microsoft/go-winio v0.6.1
- github.com/VictoriaMetrics/fastcache v1.12.1
- github.com/aws/aws-sdk-go-v2 v1.25.2
- github.com/aws/aws-sdk-go-v2/config v1.18.45
- github.com/aws/aws-sdk-go-v2/credentials v1.13.43
- github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2
- github.com/btcsuite/btcd/btcec/v2 v2.3.2
+ github.com/Microsoft/go-winio v0.6.2
+ github.com/VictoriaMetrics/fastcache v1.12.2
+ github.com/aws/aws-sdk-go-v2 v1.27.2
+ github.com/aws/aws-sdk-go-v2/config v1.27.18
+ github.com/aws/aws-sdk-go-v2/credentials v1.17.18
+ github.com/aws/aws-sdk-go-v2/service/route53 v1.40.10
+ github.com/btcsuite/btcd/btcec/v2 v2.3.3
github.com/cespare/cp v1.1.1
- github.com/cloudflare/cloudflare-go v0.79.0
- github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593
+ github.com/cloudflare/cloudflare-go v0.97.0
+ github.com/cockroachdb/pebble v1.1.1
github.com/consensys/gnark-crypto v0.12.1
- github.com/cosmos/cosmos-sdk v0.47.3
- github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233
- github.com/crate-crypto/go-kzg-4844 v0.7.0
- github.com/davecgh/go-spew v1.1.1
+ github.com/cosmos/cosmos-sdk v0.50.6
+ github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c
+ github.com/crate-crypto/go-kzg-4844 v1.0.0
+ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
github.com/deckarep/golang-set/v2 v2.6.0
- github.com/dop251/goja v0.0.0-20240220182346-e401ed450204
+ github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0
+ github.com/dop251/goja v0.0.0-20240516125602-ccbae20bcec2
github.com/emirpasic/gods v1.18.1
- github.com/ethereum/c-kzg-4844 v0.4.3
- github.com/fatih/color v1.16.0
+ github.com/ethereum/c-kzg-4844 v1.0.0
+ github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0
+ github.com/fatih/color v1.17.0
+ github.com/ferranbt/fastssz v0.1.2
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e
- github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5
- github.com/fsnotify/fsnotify v1.6.0
+ github.com/fsnotify/fsnotify v1.7.0
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08
- github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46
github.com/gofrs/flock v0.8.1
github.com/golang-jwt/jwt/v4 v4.5.0
github.com/golang/mock v1.6.0
- github.com/golang/protobuf v1.5.3
+ github.com/golang/protobuf v1.5.4
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb
github.com/google/gofuzz v1.2.0
github.com/google/uuid v1.6.0
- github.com/gorilla/websocket v1.5.0
- github.com/graph-gophers/graphql-go v1.3.0
- github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
- github.com/hashicorp/go-bexpr v0.1.10
- github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d
- github.com/hashicorp/hcl/v2 v2.10.1
- github.com/heimdalr/dag v1.2.1
- github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7
+ github.com/gorilla/websocket v1.5.2
+ github.com/graph-gophers/graphql-go v1.5.0
+ github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
+ github.com/hashicorp/go-bexpr v0.1.14
+ github.com/hashicorp/golang-lru v1.0.2
+ github.com/hashicorp/hcl/v2 v2.20.1
+ github.com/heimdalr/dag v1.4.0
+ github.com/holiman/billy v0.0.0-20240322075458-72a4e81ec6da
github.com/holiman/bloomfilter/v2 v2.0.3
github.com/holiman/uint256 v1.2.4
github.com/huin/goupnp v1.3.0
@@ -59,10 +60,11 @@ require (
github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267
github.com/json-iterator/go v1.1.12
github.com/julienschmidt/httprouter v1.3.0
- github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c
+ github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52
+ github.com/kilic/bls12-381 v0.1.0
github.com/kylelemons/godebug v1.1.0
github.com/maticnetwork/crand v1.0.2
- github.com/maticnetwork/heimdall v1.0.4
+ github.com/maticnetwork/heimdall v1.0.7
github.com/maticnetwork/polyproto v0.0.3
github.com/mattn/go-colorable v0.1.13
github.com/mattn/go-isatty v0.0.20
@@ -73,74 +75,76 @@ require (
github.com/pelletier/go-toml v1.9.5
github.com/peterh/liner v1.2.2
github.com/protolambda/bls12-381-util v0.1.0
- github.com/rs/cors v1.10.1
+ github.com/protolambda/zrnt v0.32.2
+ github.com/protolambda/ztyp v0.2.2
+ github.com/rs/cors v1.11.0
github.com/ryanuber/columnize v2.1.2+incompatible
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/status-im/keycard-go v0.3.2
github.com/stretchr/testify v1.9.0
- github.com/supranational/blst v0.3.11
+ github.com/supranational/blst v0.3.12
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
github.com/tendermint/tendermint v0.34.24
github.com/tyler-smith/go-bip39 v1.1.0
- github.com/urfave/cli/v2 v2.25.7
+ github.com/urfave/cli/v2 v2.27.2
github.com/xsleonard/go-merkle v1.1.0
- go.opentelemetry.io/otel v1.19.0
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0
- go.opentelemetry.io/otel/sdk v1.19.0
- go.uber.org/automaxprocs v1.5.2
- go.uber.org/goleak v1.2.1
- golang.org/x/crypto v0.21.0
- golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
- golang.org/x/sync v0.5.0
- golang.org/x/sys v0.18.0
- golang.org/x/text v0.14.0
- golang.org/x/time v0.3.0
- golang.org/x/tools v0.15.0
- google.golang.org/grpc v1.58.3
- gopkg.in/natefinch/lumberjack.v2 v2.0.0
+ go.opentelemetry.io/otel v1.27.0
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0
+ go.opentelemetry.io/otel/sdk v1.27.0
+ go.uber.org/automaxprocs v1.5.3
+ go.uber.org/goleak v1.3.0
+ golang.org/x/crypto v0.24.0
+ golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8
+ golang.org/x/sync v0.7.0
+ golang.org/x/sys v0.21.0
+ golang.org/x/text v0.16.0
+ golang.org/x/time v0.5.0
+ golang.org/x/tools v0.22.0
+ google.golang.org/grpc v1.64.1
+ gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/yaml.v3 v3.0.1
)
require (
- cloud.google.com/go/compute v1.21.0 // indirect
- cloud.google.com/go/iam v1.1.1 // indirect
- github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
+ cloud.google.com/go/iam v1.1.6 // indirect
+ github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pborman/uuid v1.2.1 // indirect
- github.com/pelletier/go-toml/v2 v2.0.9 // indirect
- github.com/subosito/gotenv v1.4.1 // indirect
+ github.com/pelletier/go-toml/v2 v2.1.0 // indirect
+ github.com/subosito/gotenv v1.6.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)
require (
- cloud.google.com/go v0.110.4 // indirect
- cloud.google.com/go/pubsub v1.32.0 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.2 // indirect
+ cloud.google.com/go v0.112.1 // indirect
+ cloud.google.com/go/pubsub v1.36.1 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 // indirect
github.com/DataDog/zstd v1.5.2 // indirect
github.com/agext/levenshtein v1.2.1 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/armon/go-radix v1.0.0 // indirect
github.com/aws/aws-sdk-go v1.40.45 // indirect
- github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.2 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.4 // indirect
- github.com/aws/aws-sdk-go-v2/service/sso v1.20.1 // indirect
- github.com/aws/aws-sdk-go-v2/service/sts v1.28.3 // indirect
- github.com/aws/smithy-go v1.20.1 // indirect
+ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5 // indirect
+ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11 // indirect
+ github.com/aws/aws-sdk-go-v2/service/sso v1.20.11 // indirect
+ github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 // indirect
+ github.com/aws/smithy-go v1.20.2 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.10.0 // indirect
- github.com/cespare/xxhash/v2 v2.2.0 // indirect
- github.com/cockroachdb/errors v1.9.1 // indirect
+ github.com/cespare/xxhash/v2 v2.3.0 // indirect
+ github.com/cockroachdb/errors v1.11.3 // indirect
+ github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
- github.com/cockroachdb/redact v1.1.3 // indirect
+ github.com/cockroachdb/redact v1.1.5 // indirect
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/consensys/bavard v0.1.13 // indirect
- github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
+ github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/dlclark/regexp2 v1.7.0 // indirect
github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 // indirect
- github.com/getsentry/sentry-go v0.18.0 // indirect
+ github.com/getsentry/sentry-go v0.27.0 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
github.com/gogo/protobuf v1.3.2 // indirect
@@ -148,30 +152,30 @@ require (
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
- github.com/kilic/bls12-381 v0.1.0 // indirect
- github.com/klauspost/compress v1.16.7 // indirect
+ github.com/klauspost/compress v1.17.0 // indirect
+ github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
- github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
+ github.com/minio/sha256-simd v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/pointerstructure v1.2.1 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
- github.com/pmezard/go-difflib v1.0.0 // indirect
- github.com/prometheus/client_golang v1.14.0 // indirect
- github.com/prometheus/client_model v0.4.0 // indirect
- github.com/prometheus/common v0.39.0 // indirect
- github.com/prometheus/procfs v0.9.0 // indirect
- github.com/rogpeppe/go-internal v1.10.0 // indirect
+ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
+ github.com/prometheus/client_golang v1.19.0 // indirect
+ github.com/prometheus/client_model v0.5.0 // indirect
+ github.com/prometheus/common v0.48.0 // indirect
+ github.com/prometheus/procfs v0.12.0 // indirect
+ github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
- github.com/tklauser/go-sysconf v0.3.10 // indirect
- github.com/tklauser/numcpus v0.4.0 // indirect
- github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
- golang.org/x/mod v0.14.0 // indirect
- golang.org/x/net v0.23.0 // indirect
- google.golang.org/protobuf v1.31.0
+ github.com/tklauser/go-sysconf v0.3.11 // indirect
+ github.com/tklauser/numcpus v0.6.0 // indirect
+ github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
+ golang.org/x/mod v0.18.0 // indirect
+ golang.org/x/net v0.26.0 // indirect
+ google.golang.org/protobuf v1.34.1
gopkg.in/yaml.v2 v2.4.0 // indirect
gotest.tools v2.2.0+incompatible
pgregory.net/rapid v1.1.0
@@ -179,69 +183,76 @@ require (
)
require (
- cloud.google.com/go/compute/metadata v0.2.3 // indirect
+ cloud.google.com/go/compute/metadata v0.3.0 // indirect
github.com/Masterminds/semver/v3 v3.1.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.1 // indirect
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
- github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.2 // indirect
- github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.2 // indirect
+ github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9 // indirect
+ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
- github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect
- github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1 // indirect
+ github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect
+ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 // indirect
github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d // indirect
github.com/bgentry/speakeasy v0.1.0 // indirect
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect
github.com/cbergoon/merkletree v0.2.0 // indirect
- github.com/cenkalti/backoff/v4 v4.2.1 // indirect
+ github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cosmos/go-bip39 v1.0.0 // indirect
github.com/cosmos/ledger-cosmos-go v0.13.0 // indirect
+ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/etcd-io/bbolt v1.3.3 // indirect
+ github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/gammazero/deque v0.2.1 // indirect
github.com/go-kit/kit v0.12.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
- github.com/go-logr/logr v1.2.4 // indirect
+ github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
- github.com/go-redis/redis v6.15.7+incompatible // indirect
- github.com/goccy/go-json v0.10.2 // indirect
+ github.com/go-redis/redis/v8 v8.11.5 // indirect
+ github.com/go-redsync/redsync/v4 v4.0.4 // indirect
+ github.com/goccy/go-json v0.10.3 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/gomodule/redigo v2.0.0+incompatible // indirect
- github.com/google/go-cmp v0.5.9 // indirect
- github.com/google/s2a-go v0.1.4 // indirect
- github.com/googleapis/gax-go/v2 v2.11.0 // indirect
- github.com/gorilla/mux v1.8.0 // indirect
- github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect
- github.com/hashicorp/errwrap v1.0.0 // indirect
+ github.com/google/go-cmp v0.6.0 // indirect
+ github.com/google/s2a-go v0.1.7 // indirect
+ github.com/googleapis/gax-go/v2 v2.12.2 // indirect
+ github.com/gorilla/mux v1.8.1 // indirect
+ github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
+ github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-multierror v1.1.0 // indirect
- github.com/hashicorp/go-retryablehttp v0.7.5 // indirect
+ github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/huandu/xstrings v1.3.2 // indirect
- github.com/inconshreveable/mousetrap v1.0.0 // indirect
+ github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jmhodges/levigo v1.0.0 // indirect
github.com/kelseyhightower/envconfig v1.4.0 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
- github.com/magiconair/properties v1.8.6 // indirect
+ github.com/magiconair/properties v1.8.7 // indirect
github.com/mitchellh/copystructure v1.0.0 // indirect
- github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
+ github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/reflectwalk v1.0.0 // indirect
- github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
+ github.com/montanaflynn/stats v0.7.0 // indirect
github.com/naoina/go-stringutil v0.1.0 // indirect
github.com/oapi-codegen/runtime v1.0.0 // indirect
github.com/posener/complete v1.2.3 // indirect
github.com/rakyll/statik v0.1.7 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
+ github.com/robfig/cron/v3 v3.0.1 // indirect
+ github.com/sagikazarmark/locafero v0.4.0 // indirect
+ github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/shopspring/decimal v1.2.0 // indirect
- github.com/spf13/afero v1.9.2 // indirect
- github.com/spf13/cast v1.5.0 // indirect
- github.com/spf13/cobra v1.5.0 // indirect
- github.com/spf13/jwalterweatherman v1.1.0 // indirect
+ github.com/sourcegraph/conc v0.3.0 // indirect
+ github.com/spf13/afero v1.11.0 // indirect
+ github.com/spf13/cast v1.6.0 // indirect
+ github.com/spf13/cobra v1.8.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
- github.com/spf13/viper v1.13.0 // indirect
- github.com/streadway/amqp v1.0.0 // indirect
+ github.com/spf13/viper v1.18.2 // indirect
+ github.com/streadway/amqp v1.1.0 // indirect
github.com/stumble/gorocksdb v0.0.3 // indirect
github.com/tendermint/btcd v0.1.1 // indirect
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect
@@ -252,30 +263,32 @@ require (
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
- github.com/yusufpapurcu/wmi v1.2.2 // indirect
+ github.com/yusufpapurcu/wmi v1.2.3 // indirect
github.com/zondax/ledger-go v0.14.1 // indirect
- go.opentelemetry.io/otel/metric v1.19.0 // indirect
- golang.org/x/oauth2 v0.10.0 // indirect
- google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
+ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
+ go.opentelemetry.io/otel/metric v1.27.0 // indirect
+ go.uber.org/atomic v1.9.0 // indirect
+ go.uber.org/multierr v1.9.0 // indirect
+ golang.org/x/oauth2 v0.20.0 // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 // indirect
)
require (
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae // indirect
- github.com/RichardKnop/machinery v1.7.4 // indirect
- github.com/RichardKnop/redsync v1.2.0 // indirect
+ github.com/RichardKnop/machinery v1.10.6 // indirect
github.com/prometheus/tsdb v0.10.0
github.com/zclconf/go-cty v1.13.0 // indirect
github.com/zondax/hid v0.9.1 // indirect
go.mongodb.org/mongo-driver v1.14.0 // indirect
go.opencensus.io v0.24.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect
- go.opentelemetry.io/otel/trace v1.19.0
- go.opentelemetry.io/proto/otlp v1.0.0 // indirect
- google.golang.org/api v0.126.0 // indirect
- google.golang.org/appengine v1.6.7 // indirect
- google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 // indirect
+ go.opentelemetry.io/otel/trace v1.27.0
+ go.opentelemetry.io/proto/otlp v1.2.0 // indirect
+ google.golang.org/api v0.169.0 // indirect
+ google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect
)
replace github.com/cosmos/cosmos-sdk => github.com/maticnetwork/cosmos-sdk v0.38.4
@@ -284,7 +297,7 @@ replace github.com/tendermint/tendermint => github.com/maticnetwork/tendermint v
replace github.com/tendermint/tm-db => github.com/tendermint/tm-db v0.2.0
-replace github.com/ethereum/go-ethereum => github.com/maticnetwork/bor v1.2.7
+replace github.com/ethereum/go-ethereum => github.com/maticnetwork/bor v1.3.2
replace github.com/Masterminds/goutils => github.com/Masterminds/goutils v1.1.1
diff --git a/go.sum b/go.sum
index 771e0b3ecb..ce93e54d7f 100644
--- a/go.sum
+++ b/go.sum
@@ -1,3 +1,4 @@
+cloud.google.com/go v0.0.0-20170206221025-ce650573d812/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
@@ -17,6 +18,7 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
+cloud.google.com/go v0.76.0/go.mod h1:r9EvIAvLrunusnetGdQ50M/gKui1x3zdGW/VELGkdpw=
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
@@ -37,8 +39,9 @@ cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFO
cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I=
cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY=
cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw=
-cloud.google.com/go v0.110.4 h1:1JYyxKMN9hd5dR2MYTPWkGUgcoxVVhg0LKNKEo0qvmk=
cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI=
+cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM=
+cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4=
cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4=
cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw=
cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E=
@@ -200,13 +203,13 @@ cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/
cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE=
cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI=
cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
-cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk=
cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU=
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
-cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
+cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
+cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY=
cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck=
cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w=
@@ -375,8 +378,9 @@ cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB
cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0=
cloud.google.com/go/iam v1.0.1/go.mod h1:yR3tmSL8BcZB4bxByRv2jkSIahVmCtfKZwLYGBalRE8=
cloud.google.com/go/iam v1.1.0/go.mod h1:nxdHjaKfCr7fNYx/HJMM8LgiMugmveWlkatear5gVyk=
-cloud.google.com/go/iam v1.1.1 h1:lW7fzj15aVIXYHREOqjRBV9PsH0Z6u8Y46a1YGvQP4Y=
cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU=
+cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc=
+cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI=
cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc=
cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A=
cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk=
@@ -400,8 +404,9 @@ cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8
cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24=
cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI=
cloud.google.com/go/kms v1.11.0/go.mod h1:hwdiYC0xjnWsKQQCQQmIQnS9asjYVSK6jtXm+zFqXLM=
-cloud.google.com/go/kms v1.12.1 h1:xZmZuwy2cwzsocmKDOPu4BL7umg8QXagQx6fKVmf45U=
cloud.google.com/go/kms v1.12.1/go.mod h1:c9J991h5DTl+kg7gi3MYomh12YEENGrf48ee/N/2CDM=
+cloud.google.com/go/kms v1.15.7 h1:7caV9K3yIxvlQPAcaFffhlT7d1qpxjB1wHBtjWa13SM=
+cloud.google.com/go/kms v1.15.7/go.mod h1:ub54lbsa6tDkUwnu4W7Yt1aAIFLnspgh0kPGToDukeI=
cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic=
cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI=
cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE=
@@ -515,12 +520,14 @@ cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2k
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
+cloud.google.com/go/pubsub v1.10.0/go.mod h1:eNpTrkOy7dCpkNyaSNetMa6udbgecJMd0ZsTJS/cuNo=
cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI=
cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0=
cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8=
cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4=
-cloud.google.com/go/pubsub v1.32.0 h1:JOEkgEYBuUTHSyHS4TcqOFuWr+vD6qO/imsFqShUCp4=
cloud.google.com/go/pubsub v1.32.0/go.mod h1:f+w71I33OMyxf9VpMVcZbnG5KSUkCOUHYpFd5U1GdRc=
+cloud.google.com/go/pubsub v1.36.1 h1:dfEPuGCHGbWUhaMCTHUFjfroILEkx55iUmKBZTP5f+Y=
+cloud.google.com/go/pubsub v1.36.1/go.mod h1:iYjCa9EzWOoBiTdd4ps7QoMtMln5NwaZQpK1hbRfBDE=
cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg=
cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k=
cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM=
@@ -727,38 +734,65 @@ cloud.google.com/go/workflows v1.11.1/go.mod h1:Z+t10G1wF7h8LgdY/EmRcQY8ptBD/nvo
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc=
-github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
-github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1/go.mod h1:fBF9PQNqB8scdgpZ3ufzaLntG0AG7C1WjPMsiFOmfHM=
-github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.2 h1:c4k2FIYIh4xtwqrQwV0Ct1v5+ehlNXj5NI/MWVsiTkQ=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.0.0/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0/go.mod h1:3Ug6Qzto9anB6mGlEdgYMDF5zHQ+wwhEaYR4s17PHMw=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0/go.mod h1:uReU2sSxZExRPBAg3qKzmAucSi51+SP1OhohieR821Q=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1/go.mod h1:RKUqNu35KJYcVG/fqTRqmuXJZYNhYkBrnC/hX7yGbTA=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.2/go.mod h1:5FDJtLEO/GxwNgUxbwrY3LP0pEoThTQJtk2oysdXHxM=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0/go.mod h1:+6sju8gk8FRmSajX3Oz4G5Gm7P+mbqE9FVaXXFYTkCM=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0/go.mod h1:NBanQUfSWiWn3QEpWDTCU0IjBECKOYvl2R8xdRtMtiM=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 h1:sO0/P7g68FrryJzljemN+6GTssUXdANk6aJ7T1ZxnsQ=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1/go.mod h1:h8hyGFDsU5HMivxiS2iYFZsgDbU9OnnJ163x5UGVKYo=
-github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3/go.mod h1:KLF4gFr6DcKFZwSuH8w8yEK6DpFl3LP5rhdvAb7Yz5I=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 h1:LqbJ/WzJUwBf8UiaSzgX7aMclParm9/5Vgp+TY51uBQ=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2/go.mod h1:yInRyqWXAuaPrgI7p70+lDDgh3mlBohis29jGMISnmc=
+github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.0.0/go.mod h1:ceIuwmxDWptoW3eCqSXlnPsZFKh4X+R38dWPv7GS9Vs=
+github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2/go.mod h1:FbdwsQ2EzwvXxOPcMFYO8ogEc9uMMIj3YkmCdXdAFmk=
+github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0/go.mod h1:LRr2FzBTQlONPPa5HREE5+RjSCTXl7BwOvYOaWTqCaI=
+github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanagementgroups v1.0.0/go.mod h1:mLfWfj8v3jfWKsL9G4eoBoXVcsqcIUTapmdKy7uGOp0=
+github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.0.0/go.mod h1:s1tW/At+xHqjNFvWU4G0c0Qv33KOhvbGNj0RCTQDV8s=
+github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1/go.mod h1:c/wcGeGx5FUPbM/JltUYHZcKmigwyVLJlDq+4HdtXaw=
+github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0/go.mod h1:c+Lifp3EDEamAkPVzMooRNOK6CZjNSdEnf1A7jsI9u4=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0 h1:AifHbc4mg0x9zW52WOpKbsHaDKuRhlI7TVl47thgQ70=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0/go.mod h1:T5RfihdXtBDxt1Ch2wobif3TvzTdumDy29kahv6AV9A=
-github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0/go.mod h1:tPaiy8S5bQ+S5sOiDlINkp7+Ef339+Nz5L5XO+cnOHo=
-github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.1 h1:fXPMAmuh0gDuRDey0atC8cXBuKIlqCzCkL8sm1n9Ov0=
+github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0/go.mod h1:+6KLcKIVgxoBDMqMO/Nvy7bZ9a0nbU3I1DtFQK3YvB4=
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.1/go.mod h1:SUZc9YRRHfx2+FAQKNDGrssXehqLpxmwRv2mC/5ntj4=
+github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2 h1:YUUxeiOWgdAQE3pXt2H7QXzZs0q8UBjgRbl56qo8GYM=
+github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2/go.mod h1:dmXQgZuiSubAecswZE+Sm8jkvEa7kQgTPVRvwL/nd0E=
+github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/testdata/perf v0.0.0-20240208231215-981108a6de20/go.mod h1:KMKhmwqL1TqoNRkQG2KGmDaVwT5Dte9d3PoADB38/UY=
+github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4=
+github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU=
+github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o=
+github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA=
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
-github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
+github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
-github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EFZQ978U7x8IRnstaskI3IysnWY5Ao3QgZUKOXlsAdw=
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
-github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w=
-github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo=
github.com/CloudyKit/jet/v6 v6.1.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4=
+github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8=
github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
+github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20190129172621-c8b1d7a94ddf/go.mod h1:aJ4qN3TfrelA6NZ6AXsXRfmEVaYin3EDbSPJrKS8OXo=
github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
github.com/JekaMas/go-grpc-net-conn v0.0.0-20220708155319-6aff21f2d13d h1:RO27lgfZF8s9lZ3pWyzc0gCE0RZC+6/PXbRjAa0CNp8=
@@ -767,37 +801,36 @@ github.com/JekaMas/workerpool v1.1.8 h1:IbDbTITrDgt1xAzdzTS9aLk4Q/4dCsjUOopiyFkD
github.com/JekaMas/workerpool v1.1.8/go.mod h1:IoDWPpwMcA27qbuugZKeBslDrgX09lVmksuh9sjzbhc=
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
-github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7/go.mod h1:6E6s8o2AE4KhCrqr6GRJjdC/gNfTdxkIXvuGZZda2VM=
+github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
-github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
-github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
github.com/Masterminds/sprig/v3 v3.2.1 h1:n6EPaDyLSvCEa3frruQvAiHuNp2dhBlMSmkEr+HuzGc=
github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
-github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
+github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
+github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae h1:DcFpTQBYQ9Ct2d6sC7ol0/ynxc2pO1cpGUM+f4t5adg=
github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae/go.mod h1:rJJ84PyA/Wlmw1hO+xTzV2wsSUon6J5ktg0g8BF2PuU=
-github.com/RichardKnop/machinery v1.7.4 h1:QMHik7BaeN3TsfXcg48xw6tsM9IqzC8rBgoK5i6/IPA=
github.com/RichardKnop/machinery v1.7.4/go.mod h1:W87mnh7t91WdrwGbdnAjvDzqD/bqBV+0+GF276gv/bU=
-github.com/RichardKnop/redsync v1.2.0 h1:gK35hR3zZkQigHKm8wOGb9MpJ9BsrW6MzxezwjTcHP0=
+github.com/RichardKnop/machinery v1.10.6 h1:wviOkVLVM9DaNFAOtXEuZsr9d+Okm4VSw7AILVLIhyc=
+github.com/RichardKnop/machinery v1.10.6/go.mod h1:qT0dXDPzsGqwHoYWO12Gb25MxA/9HfxaqdIaZp9ofWM=
github.com/RichardKnop/redsync v1.2.0/go.mod h1:9b8nBGAX3bE2uCfJGSnsDvF23mKyHTZzmvmj5FH3Tp0=
-github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
-github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw=
-github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40=
-github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o=
+github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI=
+github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI=
github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE=
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
github.com/Workiva/go-datastructures v1.0.53/go.mod h1:1yZL+zfsztete+ePzZz/Zb1/t5BnDuE2Ya2MMGhzP6A=
+github.com/aclements/go-gg v0.0.0-20170118225347-6dbb4e4fefb0/go.mod h1:55qNq4vcpkIuHowELi5C8e+1yUHtoLoOUR9QU5j7Tes=
+github.com/aclements/go-moremath v0.0.0-20210112150236-f10218a38794/go.mod h1:7e+I0LQFUI9AXWxOfsQROs9xPhoJtbsyWcjJqDd4KPY=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8=
@@ -806,6 +839,7 @@ github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY
github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY=
github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
+github.com/ajstarks/svgo v0.0.0-20210923152817-c3b6e2f0c527/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
@@ -815,12 +849,11 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5
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/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
+github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0=
github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI=
github.com/apache/arrow/go/v12 v12.0.0/go.mod h1:d+tV/eHZZ7Dz7RPrFKtPK02tpr+c9/PEd/zm8mDS9Vg=
-github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
-github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU=
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
@@ -828,6 +861,8 @@ github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:o
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
+github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
+github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
@@ -836,70 +871,55 @@ github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
-github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
-github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
-github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.29.15/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg=
-github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
+github.com/aws/aws-sdk-go v1.37.16/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.40.45 h1:QN1nsY27ssD/JmW4s83qmSb+uL6DG4GmCDzjmJB4xUI=
github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
-github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
-github.com/aws/aws-sdk-go-v2 v1.21.0/go.mod h1:/RfNgGmRxI+iFOB1OeJUyxiU+9s88k3pfHvDagGEp0M=
-github.com/aws/aws-sdk-go-v2 v1.21.2/go.mod h1:ErQhvNuEMhJjweavOYhxVkn2RUx7kQXVATHrjKtxIpM=
-github.com/aws/aws-sdk-go-v2 v1.25.2 h1:/uiG1avJRgLGiQM9X3qJM8+Qa6KRGK5rRPuXE0HUM+w=
github.com/aws/aws-sdk-go-v2 v1.25.2/go.mod h1:Evoc5AsmtveRt1komDwIsjHFyrP5tDuF1D1U+6z6pNo=
-github.com/aws/aws-sdk-go-v2/config v1.18.43/go.mod h1:NiFev8qlgg8MPzw3fO/EwzMZeZwlJEKGwfpjRPA9Nvw=
-github.com/aws/aws-sdk-go-v2/config v1.18.45 h1:Aka9bI7n8ysuwPeFdm77nfbyHCAKQ3z9ghB3S/38zes=
-github.com/aws/aws-sdk-go-v2/config v1.18.45/go.mod h1:ZwDUgFnQgsazQTnWfeLWk5GjeqTQTL8lMkoE1UXzxdE=
-github.com/aws/aws-sdk-go-v2/credentials v1.13.41/go.mod h1:cc3Fn7DkKbJalPtQnudHGZZ8ml9+hwtbc1CJONsYYqk=
-github.com/aws/aws-sdk-go-v2/credentials v1.13.43 h1:LU8vo40zBlo3R7bAvBVy/ku4nxGEyZe9N8MqAeFTzF8=
-github.com/aws/aws-sdk-go-v2/credentials v1.13.43/go.mod h1:zWJBz1Yf1ZtX5NGax9ZdNjhhI4rgjfgsyk6vTY1yfVg=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.11/go.mod h1:TEPP4tENqBGO99KwVpV9MlOX4NSrSLP8u3KRy2CDwA8=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13/go.mod h1:f/Ib/qYjhV2/qdsf79H3QP/eRE4AkVyEf6sk7XfZ1tg=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.2 h1:AK0J8iYBFeUk2Ax7O8YpLtFsfhdOByh2QIkHmigpRYk=
+github.com/aws/aws-sdk-go-v2 v1.27.2 h1:pLsTXqX93rimAOZG2FIYraDQstZaaGVVN4tNw65v0h8=
+github.com/aws/aws-sdk-go-v2 v1.27.2/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
+github.com/aws/aws-sdk-go-v2/config v1.27.6/go.mod h1:W9RZFF2pL+OhnUSZsQS/eDMWD8v+R+yWgjj3nSlrXVU=
+github.com/aws/aws-sdk-go-v2/config v1.27.18 h1:wFvAnwOKKe7QAyIxziwSKjmer9JBMH1vzIL6W+fYuKk=
+github.com/aws/aws-sdk-go-v2/config v1.27.18/go.mod h1:0xz6cgdX55+kmppvPm2IaKzIXOheGJhAufacPJaXZ7c=
+github.com/aws/aws-sdk-go-v2/credentials v1.17.6/go.mod h1:chJZuJ7TkW4kiMwmldOJOEueBoSkUb4ynZS1d9dhygo=
+github.com/aws/aws-sdk-go-v2/credentials v1.17.18 h1:D/ALDWqK4JdY3OFgA2thcPO1c9aYTT5STS/CvnkqY1c=
+github.com/aws/aws-sdk-go-v2/credentials v1.17.18/go.mod h1:JuitCWq+F5QGUrmMPsk945rop6bB57jdscu+Glozdnc=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.2/go.mod h1:iRlGzMix0SExQEviAyptRWRGdYNo3+ufW/lCzvKVTUc=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.41/go.mod h1:CrObHAuPneJBlfEJ5T3szXOUkLEThaGfvnhTf33buas=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43/go.mod h1:auo+PiyLl0n1l8A0e8RIeR8tOzYPfZZH/JNlrJ8igTQ=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.2 h1:bNo4LagzUKbjdxE0tIcR9pMzLR2U/Tgie1Hq1HQ3iH8=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5 h1:dDgptDO9dxeFkXy+tEgVkzSClHZje/6JkPW5aZyEvrQ=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5/go.mod h1:gjvE2KBUgUQhcv89jqxrIxH9GaKs1JbZzWejj/DaHGA=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.2/go.mod h1:wRQv0nN6v9wDXuWThpovGQjqF1HFdcgWjporw14lS8k=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.35/go.mod h1:SJC1nEVVva1g3pHAIdCp7QsRIkMmLAgoDquQ9Rr8kYw=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37/go.mod h1:Qe+2KtKml+FEsQF/DHmDV+xjtche/hwoF75EG4UlHW8=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.2 h1:EtOU5jsPdIQNP+6Q2C5e3d65NKT1PeCiQk+9OdzO12Q=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9 h1:cy8ahBJuhtM8GTTSyOkfy6WVPV1IE+SS5/wfXUYuulw=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9/go.mod h1:CZBXGLaJnEZI6EVNcPd7a6B5IC5cA/GkRWtu9fp3S6Y=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.2/go.mod h1:tyF5sKccmDz0Bv4NrstEr+/9YkSPJHrcO7UsUKf7pWM=
-github.com/aws/aws-sdk-go-v2/internal/ini v1.3.43/go.mod h1:rzfdUlfA+jdgLDmPKjd3Chq9V7LVLYo1Nz++Wb91aRo=
-github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45/go.mod h1:lD5M20o09/LCuQ2mE62Mb/iSdSlCNuj6H5ci7tW7OsE=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9 h1:A4SYk07ef04+vxZToz9LWvAXl9LW0NClpPpMsi31cz0=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9/go.mod h1:5jJcHuwDagxN+ErjQ3PU3ocf6Ylc/p9x+BLO/+X4iXw=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o=
-github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.35/go.mod h1:QGF2Rs33W5MaN9gYdEQOBBFPLwTZkEhRwI33f7KIG0o=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37/go.mod h1:vBmDnwWXWxNPFRMmG2m/3MKOe+xEcMDo1tanpaWCcck=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.4 h1:jRiWxyuVO8PlkN72wDMVn/haVH4SDCBkUt0Lf/dxd7s=
+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs=
+github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.4/go.mod h1:Ru7vg1iQ7cR4i7SZ/JTLYN9kaXtbL69UdgG0OQWQxW0=
-github.com/aws/aws-sdk-go-v2/service/route53 v1.29.5/go.mod h1:6zl0jh5MUKuJ07eHn3MNeLOVutxwl8m9vQltZjoLakM=
-github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2 h1:/RPQNjh1sDIezpXaFIkZb7MlXnSyAqjVdAwcJuGYTqg=
-github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2/go.mod h1:TQZBt/WaQy+zTHoW++rnl8JBrmZ0VO6EUbVua1+foCA=
-github.com/aws/aws-sdk-go-v2/service/sso v1.15.0/go.mod h1:fIAwKQKBFu90pBxx07BFOMJLpRUGu8VOzLJakeY+0K4=
-github.com/aws/aws-sdk-go-v2/service/sso v1.15.2/go.mod h1:gsL4keucRCgW+xA85ALBpRFfdSLH4kHOVSnLMSuBECo=
-github.com/aws/aws-sdk-go-v2/service/sso v1.20.1 h1:utEGkfdQ4L6YW/ietH7111ZYglLJvS+sLriHJ1NBJEQ=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11 h1:o4T+fKxA3gTMcluBNZZXE9DNaMkJuUL1O3mffCUjoJo=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11/go.mod h1:84oZdJ+VjuJKs9v1UTC9NaodRZRseOXCTgku+vQJWR8=
+github.com/aws/aws-sdk-go-v2/service/route53 v1.40.1/go.mod h1:7Wa9sIDxey/5b2FK5r1Z6ryVfojt4Nl+VzzpK8q1L+M=
+github.com/aws/aws-sdk-go-v2/service/route53 v1.40.10 h1:J9uHribwEgHmesH5r0enxsZYyiGBWd2AaExSW2SydqE=
+github.com/aws/aws-sdk-go-v2/service/route53 v1.40.10/go.mod h1:tdzmlLwRjsHJjd4XXoSSnubCkVdRa39y4jCp4RACMkY=
github.com/aws/aws-sdk-go-v2/service/sso v1.20.1/go.mod h1:RsYqzYr2F2oPDdpy+PdhephuZxTfjHQe7SOBcZGoAU8=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.1/go.mod h1:yygr8ACQRY2PrEcy3xsUI357stq2AxnFM6DIsR9lij4=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.3/go.mod h1:a7bHA82fyUXOm+ZSWKU6PIoBxrjSprdLoM8xPYvzYVg=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1 h1:9/GylMS45hGGFCcMrUZDVayQE1jYSIN6da9jo7RAYIw=
+github.com/aws/aws-sdk-go-v2/service/sso v1.20.11 h1:gEYM2GSpr4YNWc6hCd5nod4+d4kd9vWIAWrmGuLdlMw=
+github.com/aws/aws-sdk-go-v2/service/sso v1.20.11/go.mod h1:gVvwPdPNYehHSP9Rs7q27U1EU+3Or2ZpXvzAYJNh63w=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1/go.mod h1:YjAPFn4kGFqKC54VsHs5fn5B6d+PCY2tziEa3U/GB5Y=
-github.com/aws/aws-sdk-go-v2/service/sts v1.23.0/go.mod h1:VC7JDqsqiwXukYEDjoHh9U0fOJtNWh04FPQz4ct4GGU=
-github.com/aws/aws-sdk-go-v2/service/sts v1.23.2/go.mod h1:Eows6e1uQEsc4ZaHANmsPRzAKcVDrcmjjWiih2+HUUQ=
-github.com/aws/aws-sdk-go-v2/service/sts v1.28.3 h1:TkiFkSVX990ryWIMBCT4kPqZEgThQe1xPU/AQXavtvU=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 h1:iXjh3uaH3vsVcnyZX7MqCoCfcyxIrVE9iOQruRaWPrQ=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5/go.mod h1:5ZXesEuy/QcO0WUnt+4sDkxhdXRHTu2yG0uCSH8B6os=
github.com/aws/aws-sdk-go-v2/service/sts v1.28.3/go.mod h1:xYNauIUqSuvzlPVb3VB5no/n48YGhmlInD3Uh0Co8Zc=
+github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 h1:M/1u4HBpwLuMtjlxuI2y6HoVLzF5e2mfxHCg7ZVMYmk=
+github.com/aws/aws-sdk-go-v2/service/sts v1.28.12/go.mod h1:kcfd+eTdEi/40FIbLq4Hif3XMXnl5b/+t/KTfLt9xIk=
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
-github.com/aws/smithy-go v1.14.2/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
-github.com/aws/smithy-go v1.15.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
-github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw=
github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
+github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q=
+github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
-github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d h1:1aAija9gr0Hyv4KfQcRcwlmFIrhkDmIj2dz5bkg/s/8=
github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d/go.mod h1:icNx/6QdFblhsEjZehARqbNumymUT/ydwlLojFdv7Sk=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
@@ -920,37 +940,36 @@ github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0=
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
-github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0=
+github.com/bsm/ginkgo/v2 v2.9.5/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
+github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
-github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA=
-github.com/btcsuite/btcd/btcec/v2 v2.1.2/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE=
github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU=
-github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U=
github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
-github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
+github.com/btcsuite/btcd/btcec/v2 v2.3.3 h1:6+iXlDKE8RMtKsvK0gshlXIuPbyWM/h84Ensb7o3sC0=
+github.com/btcsuite/btcd/btcec/v2 v2.3.3/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
-github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ=
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
-github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I=
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
-github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
-github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
+github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
+github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
+github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
+github.com/bytedance/sonic v1.10.0-rc3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/casbin/casbin/v2 v2.37.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
github.com/cbergoon/merkletree v0.2.0 h1:Bttqr3OuoiZEo4ed1L7fTasHka9II+BF9fhBfbNEEoQ=
github.com/cbergoon/merkletree v0.2.0/go.mod h1:5c15eckUgiucMGDOCanvalj/yJnD+KAZj1qyJtRW5aM=
-github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
-github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
+github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
@@ -959,9 +978,14 @@ github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/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/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U=
+github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
+github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
+github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
@@ -971,11 +995,10 @@ github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMn
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
-github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
-github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304=
-github.com/cloudflare/cloudflare-go v0.79.0 h1:ErwCYDjFCYppDJlDJ/5WhsSmzegAUe2+K9qgFyQDg3M=
-github.com/cloudflare/cloudflare-go v0.79.0/go.mod h1:gkHQf9xEubaQPEuerBuoinR9P8bf8a05Lq0X6WKy1Oc=
+github.com/cloudflare/cloudflare-go v0.89.0/go.mod h1:eyuehb1i6BNRc+ZwaTZAiRHeE+4jbKvHAns19oGeakg=
+github.com/cloudflare/cloudflare-go v0.97.0 h1:feZRGiRF1EbljnNIYdt8014FnOLtC3CCvgkLXu915ks=
+github.com/cloudflare/cloudflare-go v0.97.0/go.mod h1:JXRwuTfHpe5xFg8xytc2w0XC6LcrFsBVMS4WlVaiGg8=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
@@ -991,33 +1014,28 @@ github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20230428030218-4003588d1b74/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
-github.com/cockroachdb/datadriven v1.0.0/go.mod h1:5Ib8Meh+jk1RlHIXej6Pzevx/NLlNvQB9pmSBZErGA4=
github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4=
github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU=
-github.com/cockroachdb/errors v1.6.1/go.mod h1:tm6FTP5G81vwJ5lC0SizQo374JNCOPrHyXGitRJoDqM=
-github.com/cockroachdb/errors v1.8.1/go.mod h1:qGwQn6JmZ+oMjuLwjWzUNqblqk0xl4CVV3SQbGwK7Ac=
-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-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
-github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs=
+github.com/cockroachdb/errors v1.11.1/go.mod h1:8MUxA3Gi6b25tYlFEBGLf+D8aISL+M4MIpiWMSNRfxw=
+github.com/cockroachdb/errors v1.11.3 h1:5bA+k2Y6r+oz/6Z/RFlNeVCesGARKuC6YymtcDrbC/I=
+github.com/cockroachdb/errors v1.11.3/go.mod h1:m4UIW4CDjx+R5cybPsNrRbreomiFqt8o1h1wUVazSd8=
+github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce h1:giXvy4KSc/6g/esnpM7Geqxka4WSqI1SZc7sMJFd3y4=
+github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce/go.mod h1:9/y3cnZ5GKakj/H4y9r9GTjCvAFta7KLgSHPJJYc52M=
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/go.mod h1:Nb5lgvnQ2+oGlE/EyZy4+2/CxRh9KfvCXnag1vtpxVM=
-github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A=
-github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo=
-github.com/cockroachdb/redact v1.0.8/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
-github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ=
-github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
-github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ=
+github.com/cockroachdb/pebble v1.1.0/go.mod h1:sEHm5NOXxyiAoKWhoFxT8xMgd/f3RA6qUqQ1BXKrh2E=
+github.com/cockroachdb/pebble v1.1.1 h1:XnKU22oiCLy2Xn8vp1re67cXg4SAasg/WDt1NtcRFaw=
+github.com/cockroachdb/pebble v1.1.1/go.mod h1:4exszw1r40423ZsmkG/09AFEG83I0uDgfujJdbL6kYU=
+github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
+github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo=
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ=
-github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ=
github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI=
github.com/consensys/gnark-crypto v0.10.0/go.mod h1:Iq/P3HHl0ElSjsg2E1gsMwhAyxnxoKK5nVyZKd+/KhU=
+github.com/consensys/gnark-crypto v0.11.2/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY=
github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M=
github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
@@ -1025,37 +1043,33 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc
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/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
-github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
-github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
-github.com/cosmos/go-bip39 v0.0.0-20180618194314-52158e4697b8/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=
-github.com/cosmos/ledger-cosmos-go v0.10.3/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY=
github.com/cosmos/ledger-cosmos-go v0.13.0 h1:ex0CvCxToSR7j5WjrghPu2Bu9sSXKikjnVvUryNnx4s=
github.com/cosmos/ledger-cosmos-go v0.13.0/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI=
-github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
-github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/crate-crypto/go-ipa v0.0.0-20230601170251-1830d0757c80/go.mod h1:gzbVz57IDJgQ9rLQwfSk696JGWof8ftznEL9GoAv3NI=
-github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ=
-github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs=
-github.com/crate-crypto/go-kzg-4844 v0.3.0/go.mod h1:SBP7ikXEgDnUPONgm33HtuDZEDtWa3L4QtN1ocJSEQ4=
-github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA=
+github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
+github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/crate-crypto/go-ipa v0.0.0-20230905211650-63ccabc1a949/go.mod h1:7fZtshzGQ3dxVpDpF51K9mX8oziq8Xd5AoM/UT9fF5o=
+github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c h1:uQYC5Z1mdLRPrZhHjHxufI8+2UG/i25QG92j0Er9p6I=
+github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs=
github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc=
-github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
+github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDFnUp1TsawI=
+github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
+github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM=
github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
@@ -1063,14 +1077,11 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK
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/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
-github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M=
-github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw=
-github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk=
github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/djherbis/atime v1.1.0/go.mod h1:28OF6Y8s3NQWwacXc5eZTsEsiMzp7LF8MbXE+XJPdBE=
@@ -1080,15 +1091,15 @@ github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnm
github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko=
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
-github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
+github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0 h1:C7t6eeMaEQVy6e8CarIhscYQlNmw5e3G36y7l7Y21Ao=
+github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0/go.mod h1:56wL82FO0bfMU5RvfXoIwSOP2ggqqxT+tAfNEIyxuHw=
github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
-github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4=
-github.com/dop251/goja v0.0.0-20240220182346-e401ed450204 h1:O7I1iuzEA7SG+dK8ocOBSlYAA9jBUmCYl/Qa7ey7JAM=
github.com/dop251/goja v0.0.0-20240220182346-e401ed450204/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4=
+github.com/dop251/goja v0.0.0-20240516125602-ccbae20bcec2 h1:OFTHt+yJDo/uaIKMGjEKzc3DGhrpQZoqvMUIloZv6ZY=
+github.com/dop251/goja v0.0.0-20240516125602-ccbae20bcec2/go.mod h1:o31y53rb/qiIAONF7w3FHJZRqqP3fzHUr1HqanthByw=
github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y=
github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM=
-github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
@@ -1098,7 +1109,6 @@ github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaB
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
-github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
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.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@@ -1121,9 +1131,11 @@ github.com/envoyproxy/protoc-gen-validate v1.0.1/go.mod h1:0vj8bNkYbSTNS2PIyH87K
github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
github.com/etcd-io/bbolt v1.3.3 h1:gSJmxrs37LgTqR/oyJBWok6k6SvXEUerFTbltIhXkBM=
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
-github.com/ethereum/c-kzg-4844 v0.3.1/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0=
-github.com/ethereum/c-kzg-4844 v0.4.3 h1:Mpg+qsE1XyDAc03LyDfJsr8oxrt7mN7HX6wJIlB2880=
github.com/ethereum/c-kzg-4844 v0.4.3/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0=
+github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA=
+github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0=
+github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0 h1:KrE8I4reeVvf7C1tm8elRjj4BdscTYzz/WAbYyf/JI4=
+github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0/go.mod h1:D9AJLVXSyZQXJQVk8oh1EwjISE+sJTn2duYIZC0dy3w=
github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64=
github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0=
github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64=
@@ -1132,59 +1144,55 @@ github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqL
github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0=
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk=
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0=
-github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
-github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
+github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
+github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
+github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
+github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
+github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
+github.com/ferranbt/fastssz v0.1.2 h1:Dky6dXlngF6Qjc+EfDipAkE83N5I5DE68bY6O0VLNPk=
+github.com/ferranbt/fastssz v0.1.2/go.mod h1:X5UPrE2u1UJjxHA8X54u04SBwdAQjG2sFtWs39YxyWs=
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e h1:bBLctRc7kr01YGvaDfgLbTwjFNW5jdp5y5rj8XXBHfY=
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY=
-github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=
-github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
-github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA=
+github.com/fjl/memsize v0.0.2/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
-github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
-github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
+github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
+github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
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.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
-github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
+github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
+github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
+github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
github.com/gammazero/deque v0.2.0/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZDV34tuU=
github.com/gammazero/deque v0.2.1 h1:qSdsbG6pgp6nL7A0+K/B7s12mcCY/5l5SIUpMOl+dC0=
github.com/gammazero/deque v0.2.1/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZDV34tuU=
github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 h1:IZqZOB2fydHte3kUgxrzK5E1fW7RQGeDwE8F/ZZnUYc=
github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8=
-github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays=
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
-github.com/gballet/go-verkle v0.0.0-20230607174250-df487255f46b/go.mod h1:CDncRYVRSDqwakm282WEkjfaAj1hxU/v5RXxk5nXOiI=
-github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE=
-github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc=
-github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
-github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
-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/gballet/go-verkle v0.1.0/go.mod h1:7JamHhSTnnHDhcI3G8r4sWaD9XlleriqVlC3FeAQJKM=
github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ=
+github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
+github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgooyS7OzLDOpUGgm9fA3bQENb/cFSyyBmMoJDs=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
-github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
-github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
-github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
-github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
-github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
+github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g=
@@ -1197,7 +1205,6 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4=
github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
@@ -1212,75 +1219,88 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG
github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
+github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
+github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
-github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
-github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
-github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
+github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
+github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
-github.com/go-redis/redis v6.15.7+incompatible h1:3skhDh95XQMpnqeqNftPkQD9jL9e5e36z/1SUm6dy1U=
+github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
+github.com/go-playground/validator/v10 v10.14.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-redis/redis v6.15.7+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
+github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
+github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
+github.com/go-redis/redis/v7 v7.4.0 h1:7obg6wUoj05T0EpY0o8B59S9w5yeMWql7sw2kwNW1x4=
+github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg=
+github.com/go-redis/redis/v8 v8.1.1/go.mod h1:ysgGY09J/QeDYbu3HikWEIPCwaeOkuNoTgKayTEaEOw=
+github.com/go-redis/redis/v8 v8.6.0/go.mod h1:DQ9q4Rk2HtwkrwVrdgmphoOQDMfpvcd/nHEwRsicg8s=
+github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
+github.com/go-redsync/redsync/v4 v4.0.4 h1:ru0qG+VCefaZSx3a5ADmlKZXkNdgeeYWIuymDu/tzV8=
+github.com/go-redsync/redsync/v4 v4.0.4/go.mod h1:QBOJAs1k8O6Eyrre4a++pxQgHe5eQ+HF56KuTVv+8Bs=
github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU=
github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
-github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
+github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
+github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
-github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M=
-github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8=
+github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
+github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
-github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
+github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
-github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
-github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0=
+github.com/gobwas/ws v1.3.0/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
-github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
+github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
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.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
-github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
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.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
-github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
+github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
+github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
+github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
+github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
-github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ=
-github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -1316,18 +1336,25 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
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/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
-github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
+github.com/gomarkdown/markdown v0.0.0-20230716120725-531d2d74bc12/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
+github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
+github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc=
+github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg=
+github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhSyOzRwuXkOgAvijx4o+4YMUJJo9OvPYMkks=
+github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2EAE789SSiSJNqxPaC0aE9J8NTOI0Jo/A=
+github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
@@ -1345,9 +1372,9 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
@@ -1380,21 +1407,28 @@ github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8q
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/s2a-go v0.1.0/go.mod h1:OJpEgntRZo8ugHpF9hkoLJbS5dSI20XZeXJ9JVywLlM=
github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
-github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc=
github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
+github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
+github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
+github.com/google/safehtml v0.0.2/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
-github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k=
github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
+github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
+github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
+github.com/googleapis/gax-go v0.0.0-20161107002406-da06d194a00e/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
@@ -1408,8 +1442,9 @@ github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57Q
github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
github.com/googleapis/gax-go/v2 v2.10.0/go.mod h1:4UOEnMCrxsSqQ940WnTiD6qJ63le2ev3xfyagutxiPw=
-github.com/googleapis/gax-go/v2 v2.11.0 h1:9V9PWXEsWnPpQhu/PeQIkS4eGzMlTLGgt80cUUI8Ki4=
github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI=
+github.com/googleapis/gax-go/v2 v2.12.2 h1:mhN09QQW1jEWeMF74zGR81R30z4VJzjZsfkUhuHF+DA=
+github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc=
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@@ -1417,41 +1452,39 @@ github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfre
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
-github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
-github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
+github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
+github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
-github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
-github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
-github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
-github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
-github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0=
-github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
+github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
+github.com/gorilla/websocket v1.5.2 h1:qoW6V1GT3aZxybsbC6oLnailWnB+qTMVwMreOso9XUw=
+github.com/gorilla/websocket v1.5.2/go.mod h1:0n9H61RBAcf5/38py2MCYbxzPIY9rOkpvvMT24Rqs30=
+github.com/graph-gophers/graphql-go v1.5.0 h1:fDqblo50TEpD0LY7RXk/LFVYEVqo3+tXMNMPSVXA1yc=
+github.com/graph-gophers/graphql-go v1.5.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
-github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
-github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
-github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
+github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
+github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
-github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
+github.com/guptarohit/asciigraph v0.5.5/go.mod h1:dYl5wwK4gNsnFf9Zp+l06rFiDZ5YtXM6x7SRWZ3KGag=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
-github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
-github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
-github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
-github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE=
-github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0=
+github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
+github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/go-bexpr v0.1.14 h1:uKDeyuOhWhT1r5CiMTjdVY4Aoxdxs6EtwgTGnlosyp4=
+github.com/hashicorp/go-bexpr v0.1.14/go.mod h1:gN7hRKB3s7yT+YvTdnhZVLTENejvhlkZ8UE4YVBS+Q8=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
@@ -1459,8 +1492,9 @@ github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/S
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
-github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM=
github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
+github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
+github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
@@ -1468,25 +1502,27 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
-github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M=
github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
+github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
+github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
-github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
-github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs=
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
+github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
+github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
-github.com/hashicorp/hcl/v2 v2.10.1 h1:h4Xx4fsrRE26ohAk/1iGF/JBqRQbyUqu5Lvj60U54ys=
-github.com/hashicorp/hcl/v2 v2.10.1/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg=
+github.com/hashicorp/hcl/v2 v2.20.0/go.mod h1:WmcD/Ym72MDOOx5F62Ly+leloeu6H7m0pG7VBiU6pQk=
+github.com/hashicorp/hcl/v2 v2.20.1 h1:M6hgdyz7HYt1UN9e61j+qKJBqR3orTWbI1HKBJEdxtc=
+github.com/hashicorp/hcl/v2 v2.20.1/go.mod h1:TZDqQ4kNKCbh1iJp99FdPiUaVDDUPivbqxZulxDYqL4=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
@@ -1498,10 +1534,11 @@ github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/J
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
-github.com/heimdalr/dag v1.2.1 h1:XJOMaoWqJK1UKdp+4zaO2uwav9GFbHMGCirdViKMRIQ=
-github.com/heimdalr/dag v1.2.1/go.mod h1:Of/wUB7Yoj4dwiOcGOOYIq6MHlPF/8/QMBKFJpwg+yc=
-github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw=
-github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc=
+github.com/heimdalr/dag v1.4.0 h1:zG3JA4RDVLc55k3AXAgfwa+EgBNZ0TkfOO3C29Ucpmg=
+github.com/heimdalr/dag v1.4.0/go.mod h1:OCh6ghKmU0hPjtwMqWBoNxPmtRioKd1xSu7Zs4sbIqM=
+github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc=
+github.com/holiman/billy v0.0.0-20240322075458-72a4e81ec6da h1:8qEhdMGSUx67L2s5aGQinJhOwLfIRKLRBHPQq8m6WxE=
+github.com/holiman/billy v0.0.0-20240322075458-72a4e81ec6da/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc=
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.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw=
@@ -1513,14 +1550,10 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
-github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo=
-github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y=
github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
-github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
-github.com/hydrogen18/memlistener v0.0.0-20141126152155-54553eb933fb/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE=
-github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE=
+github.com/hydrogen18/memlistener v1.0.0/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE=
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
@@ -1528,34 +1561,27 @@ github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
-github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8=
+github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
+github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/influxdata/influxdb-client-go/v2 v2.13.0 h1:ioBbLmR5NMbAjP4UVA5r9b5xGjpABD7j65pI8kFphDM=
github.com/influxdata/influxdb-client-go/v2 v2.13.0/go.mod h1:k+spCbt9hcvqvUiz0sr5D8LolXHqAAOfPw9v/RIRHl4=
-github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c h1:qSHzRbhzK8RdXOsAdfDgO49TtqC1oZ+acxPrkfTxcCs=
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 h1:vilfsDSy7TDxedi9gyBkMvAirat/oRcL0lFdJBf6tdM=
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
-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/httpexpect/v2 v2.3.1/go.mod h1:ICTf89VBKSD3KB0fsyyHviKF8G8hyepP0dOXJPWz3T0=
-github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI=
-github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk=
+github.com/iris-contrib/httpexpect/v2 v2.15.1/go.mod h1:cUwf1Mm5CWs5ahZNHtDq82WuGOitAWBg/eMGevX9ilg=
github.com/iris-contrib/jade v1.1.4/go.mod h1:EDqR+ur9piDl6DUgs6qRrlfzmlx/D5UybogqrXvJTBE=
-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/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
-github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU=
github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 h1:TMtDYDHKYY15rFihtRfck/bfFqNfvcabqvXAFQfAUpY=
github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267/go.mod h1:h1nSAbGFqGVzn6Jyl1R/iCcBUHN4g+gW1u9CoBTrb9E=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
-github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
@@ -1568,8 +1594,6 @@ github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFF
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
-github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -1578,35 +1602,28 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
-github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
-github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
-github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
-github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
-github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c h1:AqsttAyEyIEsNz5WLRwuRwjiT5CMDUfLk6cFJDVPebs=
+github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52 h1:msKODTL1m0wigztaqILOtla9HeW1ciscYG4xjLtvk5I=
+github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52/go.mod h1:qk1sX/IBgppQNcGCRoj90u6EGC056EBoIc1oEjCWla8=
github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
github.com/kataras/blocks v0.0.6/go.mod h1:UK+Iwk0Oxpc0GdoJja7sEildotAUKK1LYeYcVF0COWc=
github.com/kataras/blocks v0.0.7/go.mod h1:UJIU97CluDo0f+zEjbnbkeMRlvYORtmc1304EeyXf4I=
-github.com/kataras/golog v0.0.9/go.mod h1:12HJgwBIZFNGL0EJnMRhmvGA0PQGx8VFwrZtM4CqbAk=
-github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8=
github.com/kataras/golog v0.1.7/go.mod h1:jOSQ+C5fUqsNSwurB/oAHq1IFSb0KI3l6GMa7xB6dZA=
-github.com/kataras/iris/v12 v12.0.1/go.mod h1:udK4vLQKkdDqMGJJVd/msuMtN6hpYJhg/lSzuxjhO+U=
-github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE=
+github.com/kataras/golog v0.1.9/go.mod h1:jlpk/bOaYCyqDqH18pgDHdaJab72yBE6i0O3s30hpWY=
github.com/kataras/iris/v12 v12.2.0-beta5/go.mod h1:q26aoWJ0Knx/00iPKg5iizDK7oQQSPjbD8np0XDh6dc=
+github.com/kataras/iris/v12 v12.2.5/go.mod h1:bf3oblPF8tQmRgyPCzPZr0mLazvEDFgImdaGZYuN4hw=
github.com/kataras/jwt v0.1.8/go.mod h1:Q5j2IkcIHnfwy+oNY3TVWuEBJNw0ADgCcXK9CaZwV4o=
-github.com/kataras/neffos v0.0.10/go.mod h1:ZYmJC07hQPW67eKuzlfY7SO3bC0mw83A3j6im82hfqw=
-github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE=
+github.com/kataras/jwt v0.1.9/go.mod h1:Kw6GZv2JQN8K4D3NGaSc/qZzTYfaRdyaC2zWi+RBRIQ=
github.com/kataras/neffos v0.0.20/go.mod h1:srdvC/Uo8mgrApWW0AYtiiLgMbyNPf69qPsd2FhE6MQ=
-github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d/go.mod h1:NV88laa9UiiDuX9AhMbDPkGYSPugBOV6yTZB1l2K9Z0=
-github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro=
+github.com/kataras/neffos v0.0.22/go.mod h1:IIJZcUDvwBxJGlDj942dqQgyznVKYDti91f8Ez+RRxE=
github.com/kataras/pio v0.0.10/go.mod h1:gS3ui9xSD+lAUpbYnjOGiQyY7sUMJO+EHpiRzhtZ5no=
github.com/kataras/pio v0.0.11/go.mod h1:38hH6SWH6m4DKSYmRhlrCJ5WItwWgCVrTNU62XZyUvI=
-github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8=
+github.com/kataras/pio v0.0.12/go.mod h1:ODK/8XBhhQ5WqrAhKy+9lTPS7sBf6O3KcLhc9klfRcY=
github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4=
github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
@@ -1615,15 +1632,12 @@ github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa
github.com/kilic/bls12-381 v0.1.0 h1:encrdjqKMEvabVQ7qYOKu1OvhqpK4s47wDYtNiPtlp4=
github.com/kilic/bls12-381 v0.1.0/go.mod h1:vDTTHJONJ6G+P2R74EhnyotQDTliQDnFEwhdmfzw1ig=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
-github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
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/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE=
-github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.10.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
@@ -1633,10 +1647,16 @@ github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHU
github.com/klauspost/compress v1.15.10/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4=
-github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
+github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
-github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
+github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
+github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
+github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
+github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
+github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
@@ -1655,54 +1675,45 @@ github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758/go.mod h1:B69LE
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
-github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
-github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg=
-github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y=
github.com/labstack/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
-github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
+github.com/labstack/echo/v4 v4.11.1/go.mod h1:YuYRTSM3CHs2ybfrL8Px48bO6BAnYIN4l8wSTMP6BDQ=
github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
+github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
-github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM=
+github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
-github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
-github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o=
github.com/lyft/protoc-gen-star/v2 v2.0.3/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk=
-github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
-github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
+github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
+github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mailgun/raymond/v2 v2.0.46/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18=
-github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
-github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
-github.com/maticnetwork/bor v1.2.7/go.mod h1:84m4hX8Ru+n3p/WedvrPpmrjdweSMwGJlB1SjCZiP/M=
+github.com/maticnetwork/bor v1.3.2/go.mod h1:AM85jUjwEw0Yk69TTFZ+sQMB506tDMG/4XAwQ4RcRqI=
github.com/maticnetwork/cosmos-sdk v0.38.4 h1:PAfkMXzHDHJoAf4bXQL4UWgwbu/U3yYuXoXxPhXdpBw=
github.com/maticnetwork/cosmos-sdk v0.38.4/go.mod h1:NbuVdUoqlRF6RrFJp27hpbqSoRB8cJJfUxCzUJWtaLA=
github.com/maticnetwork/crand v1.0.2 h1:Af0tAivC8zrxXDpGWNWVT/0s1fOz8w0eRbahZgURS8I=
github.com/maticnetwork/crand v1.0.2/go.mod h1:/NRNL3bj2eYdqpWmoIP5puxndTpi0XRxpj5ZKxfHjyg=
-github.com/maticnetwork/heimdall v0.3.1-0.20230227104835-81bd1055b0bc/go.mod h1:P2DoKhovYP9G9Kj2EH/zHaiRJF1jNU7ZJOyelG4UCa8=
-github.com/maticnetwork/heimdall v1.0.4 h1:xSsLn6JE/KqF3Fs9Wlx1s4dclJf2cduIodx2tL6K/cg=
github.com/maticnetwork/heimdall v1.0.4/go.mod h1:Xh7KFvtbs/SVNjOI8IgYmk6JdzYx89eU/XUwH0AgHLs=
+github.com/maticnetwork/heimdall v1.0.7 h1:QStn+hbZKxfE+PqecaorA/uATDPuQoi+U9Z7IIonb60=
+github.com/maticnetwork/heimdall v1.0.7/go.mod h1:+ANI5+VV28ahwfdl7oMzrcNwaTEs1Fn6z39BqBGcvaA=
+github.com/maticnetwork/polyproto v0.0.3-0.20230216113155-340ea926ca53 h1:PjYV+lghs106JKkrYgOnrsfDLoTc11BxZd4rUa4Rus4=
github.com/maticnetwork/polyproto v0.0.3-0.20230216113155-340ea926ca53/go.mod h1:e1mU2EXSwEpn5jM7GfNwu3AupsV6WAGoPFFfswXOF0o=
-github.com/maticnetwork/polyproto v0.0.3 h1:a69rIp97fcl3ABY4LlVX9B2t1qhLa0Jhny3HNOzReBU=
-github.com/maticnetwork/polyproto v0.0.3/go.mod h1:e1mU2EXSwEpn5jM7GfNwu3AupsV6WAGoPFFfswXOF0o=
github.com/maticnetwork/tendermint v0.33.0 h1:f+vORM02BoUOlCvnu3Zjw5rv6l6JSNVchWjH03rUuR8=
github.com/maticnetwork/tendermint v0.33.0/go.mod h1:D2fcnxGk6bje+LoPwImuKSSYLiK7/G06IynGNDSEcJk=
-github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
-github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
-github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
@@ -1710,37 +1721,31 @@ github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-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.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
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-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
-github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
-github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
-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/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed/go.mod h1:dSsfyI2zABAdhcbvkXqgxOxrCsbYeHCPgrZkku60dSg=
-github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQGvsUt6O3Pj+LDCQ=
-github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
github.com/mediocregopher/radix/v3 v3.8.0/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
-github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
+github.com/mediocregopher/radix/v3 v3.8.1/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
github.com/microcosm-cc/bluemonday v1.0.20/go.mod h1:yfBmMi8mxvaZut3Yytv+jTXRY8mxyjJ0/kQBTElld50=
github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM=
+github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
@@ -1749,9 +1754,10 @@ github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcs
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE=
github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
+github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
+github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
-github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4=
github.com/mitchellh/cli v1.1.5 h1:OxRIeJXpAMztws/XHlN2vu6imG5Dpq+j61AzAX5fLng=
github.com/mitchellh/cli v1.1.5/go.mod h1:v8+iFts2sPIKUV1ltktPXMCC8fumSKFItNcD2cLtRR4=
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
@@ -1760,8 +1766,9 @@ github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
-github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
+github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
+github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
@@ -1771,7 +1778,6 @@ github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
-github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw=
github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
@@ -1787,34 +1793,32 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
-github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
-github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
+github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
+github.com/montanaflynn/stats v0.7.0 h1:r3y12KyNxj/Sb/iOE46ws+3mS1+MZca1wlHQFPsY/JU=
+github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks=
github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
github.com/naoina/toml v0.1.1 h1:PT/lllxVVN0gzzSqSlHEmP8MJB4MY2U7STGxiouV4X8=
github.com/naoina/toml v0.1.1/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
-github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
-github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
github.com/nats-io/jwt v1.2.2/go.mod h1:/xX356yQA6LuXI9xWW7mZNpxgF2mBmGecH+Fj34sP5Q=
github.com/nats-io/jwt/v2 v2.0.3/go.mod h1:VRP+deawSXyhNjXmxPCHskrR6Mq50BqpEI5SEcNiGlY=
github.com/nats-io/jwt/v2 v2.2.1-0.20220330180145-442af02fd36a/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k=
github.com/nats-io/jwt/v2 v2.3.0/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k=
-github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
+github.com/nats-io/jwt/v2 v2.4.1/go.mod h1:24BeQtRwxRV8ruvC4CojXlx/WQ/VjuwlYiH+vu/+ibI=
github.com/nats-io/nats-server/v2 v2.5.0/go.mod h1:Kj86UtrXAL6LwYRA6H4RqzkHhK0Vcv2ZnKD5WbQ1t3g=
github.com/nats-io/nats-server/v2 v2.8.4/go.mod h1:8zZa+Al3WsESfmgSs98Fi06dRWLH5Bnq90m5bKD/eT4=
-github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM=
-github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
+github.com/nats-io/nats-server/v2 v2.9.11/go.mod h1:b0oVuxSlkvS3ZjMkncFeACGyZohbO4XhSqW1Lt7iRRY=
github.com/nats-io/nats.go v1.12.1/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
github.com/nats-io/nats.go v1.15.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
github.com/nats-io/nats.go v1.16.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
-github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4=
-github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
-github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
+github.com/nats-io/nats.go v1.19.0/go.mod h1:tLqubohF7t4z3du1QDPYJIQQyhb4wl6DhjxEajSI7UA=
+github.com/nats-io/nats.go v1.28.0/go.mod h1:XpbWUlOElGwTYbMR7imivs7jJj9GtK7ypv321Wp6pjc=
github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=
github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
+github.com/nats-io/nkeys v0.4.4/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
@@ -1824,49 +1828,68 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/oapi-codegen/runtime v1.0.0 h1:P4rqFX5fMFWqRzY9M/3YF9+aPSPPB06IzP2P7oOxrWo=
github.com/oapi-codegen/runtime v1.0.0/go.mod h1:LmCUMQuPB4M/nLXilQXhHw+BLZdDb18B34OO356yJ/A=
-github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
-github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
-github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
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.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.10.1/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.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
+github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
+github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg=
github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
-github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
+github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
+github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU=
+github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
+github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0=
+github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo=
+github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw=
+github.com/onsi/ginkgo/v2 v2.7.0/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo=
+github.com/onsi/ginkgo/v2 v2.8.1/go.mod h1:N1/NbDngAFcSLdyZ+/aYTYGSlq9qMCS/cNKGJjy+csc=
+github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxmrTcxyk=
+github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo=
+github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts=
+github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
+github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0=
+github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
+github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
+github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48=
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
-github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
+github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
+github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
+github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc=
+github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM=
+github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
+github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
+github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
+github.com/onsi/gomega v1.27.1/go.mod h1:aHX5xOykVYzWOV4WqQy0sy8BQptgukenXpCXfadcIAw=
+github.com/onsi/gomega v1.27.3/go.mod h1:5vG284IBtfDAmDyrK+eGyZmUgUlmi+Wngqo557cZ6Gw=
+github.com/onsi/gomega v1.27.4/go.mod h1:riYq/GJKh8hhoM01HN6Vmuy93AarCXCBGpvFDK3q3fQ=
+github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
+github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4=
+github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ=
+github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
+github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
-github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
-github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
-github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
-github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
-github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
-github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
-github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE=
-github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
-github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw=
github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
@@ -1875,9 +1898,10 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
-github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0=
+github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
-github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
+github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
+github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM=
github.com/peterh/liner v1.2.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
github.com/peterh/liner v1.2.2 h1:aJ4AOodmL+JxOZZEL2u9iJf8omNRpqHc/EbrK+3mAXw=
@@ -1887,12 +1911,14 @@ github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2
github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
-github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
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/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
+github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
+github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -1901,8 +1927,10 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
@@ -1910,43 +1938,39 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:Om
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
-github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
-github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
-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_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
+github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
-github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
-github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
+github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
+github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
-github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
-github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
-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/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
+github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
@@ -1954,24 +1978,32 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
-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/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
+github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic=
github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4=
-github.com/protolambda/bls12-381-util v0.0.0-20220416220906-d8552aa452c7/go.mod h1:IToEjHuttnUzwZI5KBSM/LOOW3qLbbrHOEfp3SbECGY=
github.com/protolambda/bls12-381-util v0.1.0 h1:05DU2wJN7DTU7z28+Q+zejXkIsA/MF8JZQGhtBZZiWk=
github.com/protolambda/bls12-381-util v0.1.0/go.mod h1:cdkysJTRpeFeuUVx/TXGDQNMTiRAalk1vQw3TYTHcE4=
+github.com/protolambda/zrnt v0.32.2 h1:KZ48T+3UhsPXNdtE/5QEvGc9DGjUaRI17nJaoznoIaM=
+github.com/protolambda/zrnt v0.32.2/go.mod h1:A0fezkp9Tt3GBLATSPIbuY4ywYESyAuc/FFmPKg8Lqs=
+github.com/protolambda/ztyp v0.2.2 h1:rVcL3vBu9W/aV646zF6caLS/dyn9BN8NYiuJzicLNyY=
+github.com/protolambda/ztyp v0.2.2/go.mod h1:9bYgKGqg3wJqT9ac1gI2hnVb0STQq7p/1lapqrqY1dU=
+github.com/prysmaticlabs/gohashtree v0.0.1-alpha.0.20220714111606-acbb2962fb48 h1:cSo6/vk8YpvkLbk9v3FO97cakNmUoxwi2KMP8hd5WIw=
+github.com/prysmaticlabs/gohashtree v0.0.1-alpha.0.20220714111606-acbb2962fb48/go.mod h1:4pWaT30XoEx1j8KNJf3TV+E3mQkaufn7mf+jRNb/Fuk=
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
+github.com/redis/go-redis/v9 v9.1.0/go.mod h1:urWj3He21Dj5k4TK1y59xH8Uj6ATueP8AH1cY3lZl4c=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
-github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM=
+github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
+github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@@ -1979,12 +2011,13 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
-github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
-github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
+github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
+github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
-github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo=
github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
+github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po=
+github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
@@ -1992,22 +2025,25 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
-github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/columnize v2.1.2+incompatible h1:C89EOx/XBWwIXl8wm8OPJBd7kPF25UfsK2X7Ph/zCAk=
github.com/ryanuber/columnize v2.1.2+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8=
-github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
+github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
+github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
+github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
+github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
+github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
-github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
-github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
-github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil/v3 v3.22.8/go.mod h1:s648gW4IywYzUfE/KjXxUsqrqx/T2xO5VqOXxONeRfI=
+github.com/shirou/gopsutil/v3 v3.23.7/go.mod h1:c4gnmoRC0hQuaLqvxnx1//VXQ0Ms/X9UnJF8pddY5z4=
+github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
+github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
@@ -2027,28 +2063,30 @@ github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3
github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPHbB5mVY2iO9KV3pTt/QbIkGaO8gQ2WrDbP4=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
+github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
+github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
-github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw=
github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
+github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
+github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
-github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
+github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
+github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
-github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
+github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
+github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
-github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
-github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@@ -2056,19 +2094,17 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
-github.com/spf13/viper v1.13.0 h1:BWSJ/M+f+3nmdz9bxB+bWX28kkALN2ok11D0rSo8EJU=
github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw=
+github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
+github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
-github.com/status-im/keycard-go v0.0.0-20211109104530-b0e0482ba91d/go.mod h1:97vT0Rym0wCnK4B++hNA3nCetr0Mh1KXaVxzSt1arjg=
-github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg=
github.com/status-im/keycard-go v0.3.2 h1:YusIF/bHx6YZis8UTOJrpZFnTs4IkRBdmJXqdiXkpFE=
github.com/status-im/keycard-go v0.3.2/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
-github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/amqp v0.0.0-20200108173154-1c71cc93ed71/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
-github.com/streadway/amqp v1.0.0 h1:kuuDrUJFZL1QYL9hUNuCxNObNzB0bV/ZG5jV3RWAQgo=
github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
-github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
+github.com/streadway/amqp v1.1.0 h1:py12iX8XSyI7aN/3dUT8DFIDJazNJsVJdxNVEpnQTZM=
+github.com/streadway/amqp v1.1.0/go.mod h1:WYSrTEYHOXHd0nwFeUXAe2G2hRnQT+deZJJf88uS9Bg=
github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -2076,6 +2112,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
+github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@@ -2098,24 +2135,29 @@ github.com/stumble/gorocksdb v0.0.3/go.mod h1:v6IHdFBXk5DJ1K4FZ0xi+eY737quiiBxYt
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM=
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
-github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
-github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4=
+github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
+github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
+github.com/supranational/blst v0.3.12 h1:Vfas2U2CFHhniv2QkUm2OVa1+pGTdqtpqm9NnhUUbZ8=
+github.com/supranational/blst v0.3.12/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA=
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/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8=
github.com/tdewolff/minify/v2 v2.12.1/go.mod h1:p5pwbvNs1ghbFED/ZW1towGsnnWwzvM8iz8l0eURi9g=
github.com/tdewolff/minify/v2 v2.12.4/go.mod h1:h+SRvSIX3kwgwTFOpSckvSxgax3uy8kZTSF1Ojrr3bk=
+github.com/tdewolff/minify/v2 v2.12.8/go.mod h1:YRgk7CC21LZnbuke2fmYnCTq+zhCgpb0yJACOTUNJ1E=
github.com/tdewolff/parse/v2 v2.6.3/go.mod h1:woz0cgbLwFdtbjJu8PIKxhW05KplTFQkOdX78o+Jgrs=
github.com/tdewolff/parse/v2 v2.6.4/go.mod h1:woz0cgbLwFdtbjJu8PIKxhW05KplTFQkOdX78o+Jgrs=
+github.com/tdewolff/parse/v2 v2.6.7/go.mod h1:XHDhaU6IBgsryfdnpzUXBlT6leW/l25yrFBTEb4eIyM=
github.com/tdewolff/test v1.0.7/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
+github.com/tdewolff/test v1.0.9/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s=
github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U=
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 h1:hqAk8riJvK4RMWx1aInLzndwxKalgi5rTqgfXxOxbEI=
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk=
github.com/tendermint/go-amino v0.14.1/go.mod h1:i/UKE5Uocn+argJJBb12qTZsCDBcAYMbR92AaJVmKso=
-github.com/tendermint/go-amino v0.15.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME=
github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E=
github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME=
github.com/tendermint/iavl v0.12.4 h1:hd1woxUGISKkfUWBA4mmmTwOua6PQZTJM/F0FDrmMV8=
@@ -2123,43 +2165,37 @@ github.com/tendermint/iavl v0.12.4/go.mod h1:8LHakzt8/0G3/I8FUU0ReNx98S/EP6eyPJk
github.com/tendermint/tm-db v0.2.0 h1:rJxgdqn6fIiVJZy4zLpY1qVlyD0TU6vhkT4kEf71TQQ=
github.com/tendermint/tm-db v0.2.0/go.mod h1:0cPKWu2Mou3IlxecH+MEUSYc1Ch537alLe6CpFrKzgw=
github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg=
-github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
-github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
-github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
-github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
+github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
+github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
-github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
+github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
+github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
+github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
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 v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
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/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
-github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
-github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
-github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
+github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli/v2 v2.24.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
-github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
-github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
+github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
+github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI=
+github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM=
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/fasthttp v1.40.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
-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/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
-github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
-github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
@@ -2175,8 +2211,9 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
-github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
+github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw=
+github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk=
github.com/xsleonard/go-merkle v1.1.0 h1:fHe1fuhJjGH22ZzVTAH0jqHLhTGhOq3wQjJN+8P0jQg=
github.com/xsleonard/go-merkle v1.1.0/go.mod h1:cW4z+UZ/4f2n9IJgIiyDCdYguchoDyDAPmpuOWGxdGg=
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
@@ -2193,25 +2230,27 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
+github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
+github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
-github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
github.com/zclconf/go-cty v1.13.0 h1:It5dfKTTZHe9aeppbNOda3mN7Ag7sg6QkBNm6TkyFa0=
github.com/zclconf/go-cty v1.13.0/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0=
+github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI=
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
-github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo=
github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
github.com/zondax/ledger-go v0.14.1 h1:Pip65OOl4iJ84WTpA4BKChvOufMhhbxED3BaihoZN4c=
github.com/zondax/ledger-go v0.14.1/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320=
+go.einride.tech/aip v0.66.0 h1:XfV+NQX6L7EOYK11yoHHFtndeaWh3KbD9/cN/6iWEt8=
+go.einride.tech/aip v0.66.0/go.mod h1:qAhMsfT7plxBX+Oy7Huol6YUvZ0ZzdUz26yZsQwfl1M=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
-go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
-go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
+go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
+go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A=
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
@@ -2220,88 +2259,99 @@ go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsX
go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU=
go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0=
go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY=
+go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M=
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
-go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
-go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
+go.opencensus.io v0.22.6/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
-go.opentelemetry.io/otel v1.2.0/go.mod h1:aT17Fk0Z1Nor9e0uisf98LrntPGMnk4frBO9+dkf69I=
-go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
+go.opentelemetry.io/otel v0.11.0/go.mod h1:G8UCk+KooF2HLkgo8RHX9epABH/aRGYET7gQOqBVdB0=
+go.opentelemetry.io/otel v0.17.0/go.mod h1:Oqtdxmf7UtEvL037ohlgnaYa1h7GtMh0NcSd9eqkC9s=
+go.opentelemetry.io/otel v1.6.3/go.mod h1:7BgNga5fNlF/iZjG06hM3yofffp0ofKCDwSXx1GC4dI=
go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.2.0/go.mod h1:14T5gr+Y6s2AgHPqBMgnGwp04csUjQmYXFWPeiBoq5s=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
+go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg=
+go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.2.0/go.mod h1:9mLBBnPRf3sf+ASVH2p9xREXVBvwib02FxcKnavtExg=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S281UTjM+AbF31XSOYn1qXn3BgIdWl8HNEpx08Jk=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I=
-go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ=
+go.opentelemetry.io/otel/metric v0.17.0/go.mod h1:hUz9lH1rNXyEwWAhIWCMFWKhYtpASgSnObJFnU26dJ0=
go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
-go.opentelemetry.io/otel/sdk v1.2.0/go.mod h1:jNN8QtpvbsKhgaC6V5lHiejMoKD+V8uadoSafgHPx1U=
-go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o=
+go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik=
+go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak=
+go.opentelemetry.io/otel/oteltest v0.17.0/go.mod h1:JT/LGFxPwpN+nlsTiinSYjdIx3hZIGqHCpChcIZmdoE=
go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A=
-go.opentelemetry.io/otel/trace v1.2.0/go.mod h1:N5FLswTubnxKxOJHM7XZC074qpeEdLy3CgAVsdMucK0=
-go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg=
+go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI=
+go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A=
+go.opentelemetry.io/otel/trace v0.17.0/go.mod h1:bIujpqg6ZL6xUTubIUgziI1jSaUPthmabA/ygf/6Cfg=
+go.opentelemetry.io/otel/trace v1.6.3/go.mod h1:GNJQusJlUgZl9/TQBPKU/Y/ty+0iVB5fjhKeJGZPGFs=
go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=
+go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw=
+go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
-go.opentelemetry.io/proto/otlp v0.10.0/go.mod h1:zG20xCK0szZ1xdokeSOwEcmlXu+x9kkdRe6N1DhKcfU=
go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
-go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
-go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94=
+go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
-go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
-go.uber.org/automaxprocs v1.5.2 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME=
-go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
+go.uber.org/automaxprocs v1.5.1/go.mod h1:BF4eumQw0P9GtnuxxovUd06vwm1o18oMzFtK66vU6XU=
+go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=
+go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
+go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
-go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
-go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
-go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
+go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
+go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
-go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
+go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
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-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
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-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
@@ -2314,19 +2364,28 @@ golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
+golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
+golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
+golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
+golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
+golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
-golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
+golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
+golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
+golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
+golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -2342,12 +2401,13 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20200228211341-fcea875c7e85/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
-golang.org/x/exp v0.0.0-20200513190911-00229845015e/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
+golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/exp v0.0.0-20230810033253-352e893a4cad/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
-golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
-golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
+golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
+golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 h1:LoYXNGAShUG3m/ehNk4iFctuhGX/+R1ZpfJ4/ia80JM=
+golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@@ -2387,6 +2447,7 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
+golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
@@ -2394,10 +2455,12 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
-golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
+golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -2407,7 +2470,6 @@ golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/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-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/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=
@@ -2420,8 +2482,6 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/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-20190923162816-aa69164e4478/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-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -2443,10 +2503,10 @@ golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
@@ -2454,12 +2514,9 @@ golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
@@ -2489,9 +2546,16 @@ golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
+golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
+golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
-golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
-golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
+golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
+golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
+golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
+golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
+golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
+golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
+golang.org/x/oauth2 v0.0.0-20170207211851-4464e7848382/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -2500,6 +2564,8 @@ golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20210113205817-d3ed898aa8a3/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20210201163806-010130855d6c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
@@ -2525,8 +2591,10 @@ golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
-golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
+golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo=
+golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
+golang.org/x/perf v0.0.0-20230113213139-801c7ef9e5c5/go.mod h1:UBKtEnL8aqnd+0JHqZ+2qoMDwtuy6cYhhKNoHLBiTQc=
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=
@@ -2546,17 +2614,16 @@ golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
-golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
-golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
+golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/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-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -2565,14 +2632,11 @@ golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -2580,10 +2644,10 @@ golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -2605,7 +2669,6 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -2624,9 +2687,7 @@ golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/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=
@@ -2636,6 +2697,7 @@ golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/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-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/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-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -2646,7 +2708,7 @@ golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBc
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-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -2658,19 +2720,21 @@ golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220818161305-2296e01440c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -2685,11 +2749,18 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
+golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
+golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ=
+golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -2703,8 +2774,13 @@ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
+golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
+golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
+golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
+golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
+golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -2723,36 +2799,33 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
+golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
+golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/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-20190206041539-40960b6deb8e/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-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/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-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
@@ -2765,8 +2838,7 @@ golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -2776,7 +2848,6 @@ golang.org/x/tools v0.0.0-20191126055441-b0650ceb63d9/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
@@ -2803,6 +2874,7 @@ golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
@@ -2815,16 +2887,22 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
+golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
+golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
+golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
-golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8=
-golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=
+golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
+golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
+golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
+golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
+golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
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=
@@ -2840,8 +2918,9 @@ gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY=
+gonum.org/v1/plot v0.10.0/go.mod h1:JWIHJ7U20drSQb/aDpTetJzfC1KlAPldJLpkSy88dvQ=
gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo=
-google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
+google.golang.org/api v0.0.0-20170206182103-3d017632ea10/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
@@ -2860,6 +2939,8 @@ google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSr
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
+google.golang.org/api v0.38.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
+google.golang.org/api v0.39.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
@@ -2906,16 +2987,15 @@ google.golang.org/api v0.118.0/go.mod h1:76TtD3vkgmZ66zZzp72bUUklpmQmKlhh6sYtIjY
google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms=
google.golang.org/api v0.124.0/go.mod h1:xu2HQurE5gi/3t1aFCvhPD781p0a3p11sdunTJ2BlP4=
google.golang.org/api v0.125.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw=
-google.golang.org/api v0.126.0 h1:q4GJq+cAdMAC7XP7njvQ4tvohGLiSlytuL4BQxbIZ+o=
google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw=
+google.golang.org/api v0.169.0 h1:QwWPy71FgMWqJN/l6jVlFHUa29a7dcUy02I8o799nPY=
+google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
-google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
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=
@@ -2925,7 +3005,6 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
@@ -2959,6 +3038,8 @@ google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210202153253-cf70463f6119/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210207032614-bba0dbe2a9ea/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
@@ -3052,6 +3133,7 @@ google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ
google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA=
google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw=
google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw=
+google.golang.org/genproto v0.0.0-20230227214838-9b19f0bdc514/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA=
google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA=
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s=
google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s=
@@ -3065,16 +3147,18 @@ google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFl
google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64=
google.golang.org/genproto v0.0.0-20230629202037-9506855d4529/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64=
google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:O9kGHb51iE/nOGvQaDUuadVYqovW56s5emA88lQnj6Y=
-google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g=
google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0=
+google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y=
+google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s=
google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a/go.mod h1:ts19tUU+Z0ZShN1y3aPyq2+O3d5FUNNgT6FtOzmrNn8=
google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ=
-google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw=
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ=
+google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 h1:P8OJ/WCl/Xo4E4zoe4/bifHpSmmKwARqyqE4nW6J2GQ=
+google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:RGnPtTG7r4i8sPlNyDeikXF99hMM+hN6QMm4ooG9g2g=
google.golang.org/genproto/googleapis/bytestream v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:ylj+BE99M198VPbBh6A8d9n3w8fChvyLK3wwBOjXBFA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234015-3fc162c6f38a/go.mod h1:xURIpW9ES5+/GZhnV6beoEtxQrnkRGIfP5VQG2tCBLc=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
@@ -3082,19 +3166,17 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e/go.
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230629202037-9506855d4529/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:8mL13HKkDa+IuJ8yruA3ci0q+0vsUz4m//+ottjwS5o=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 h1:AgADTJarZTBqgjiUzRgfaBchgYB3/WFTC80GPwsMcRI=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
+google.golang.org/grpc v0.0.0-20170208002647-2a6bf6142e96/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
-google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
-google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
@@ -3117,7 +3199,6 @@ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
-google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
@@ -3136,8 +3217,9 @@ google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
-google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ=
google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
+google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA=
+google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0/go.mod h1:DNq5QpG7LJqD2AamLZ7zvKE0DEpVl2BSEVjFycAAjRY=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
@@ -3157,8 +3239,10 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
+google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
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=
@@ -3167,24 +3251,18 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
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/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
-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/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
-gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
-gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
-gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
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/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -3196,15 +3274,12 @@ gopkg.in/yaml.v2 v2.2.8/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.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
-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=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
-gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
-honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -3265,7 +3340,8 @@ modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8=
moul.io/http2curl v1.0.0/go.mod h1:f6cULg+e4Md/oW1cYmwW4IWQOVl2lGbmCNGOHvzX2kE=
-pgregory.net/rapid v0.4.8/go.mod h1:Z5PbWqjvWR1I3UGjvboUuan4fe4ZYEYNLNQLExzCoUs=
+moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE=
+nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw=
pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
@@ -3274,6 +3350,4 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU=
rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA=
-sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
-sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
diff --git a/graphql/graphql.go b/graphql/graphql.go
index 60ca71850e..79a277717f 100644
--- a/graphql/graphql.go
+++ b/graphql/graphql.go
@@ -100,7 +100,7 @@ func (a *Account) Balance(ctx context.Context) (hexutil.Big, error) {
if err != nil {
return hexutil.Big{}, err
}
- balance := state.GetBalance(a.address)
+ balance := state.GetBalance(a.address).ToBig()
if balance == nil {
return hexutil.Big{}, fmt.Errorf("failed to load balance %x", a.address)
}
@@ -230,8 +230,8 @@ func (t *Transaction) resolve(ctx context.Context) (*types.Transaction, *Block)
return t.tx, t.block
}
// Try to return an already finalized transaction
- tx, blockHash, _, index, err := t.r.backend.GetTransaction(ctx, t.hash)
- if err == nil && tx != nil {
+ found, tx, blockHash, _, index, _ := t.r.backend.GetTransaction(ctx, t.hash)
+ if found {
t.tx = tx
blockNrOrHash := rpc.BlockNumberOrHashWithHash(blockHash, false)
t.block = &Block{
@@ -1509,9 +1509,15 @@ func (s *SyncState) HealingTrienodes() hexutil.Uint64 {
func (s *SyncState) HealingBytecode() hexutil.Uint64 {
return hexutil.Uint64(s.progress.HealingBytecode)
}
+func (s *SyncState) TxIndexFinishedBlocks() hexutil.Uint64 {
+ return hexutil.Uint64(s.progress.TxIndexFinishedBlocks)
+}
+func (s *SyncState) TxIndexRemainingBlocks() hexutil.Uint64 {
+ return hexutil.Uint64(s.progress.TxIndexRemainingBlocks)
+}
// Syncing returns false in case the node is currently not syncing with the network. It can be up-to-date or has not
-// yet received the latest block headers from its pears. In case it is synchronizing:
+// yet received the latest block headers from its peers. In case it is synchronizing:
// - startingBlock: block number this node started to synchronize from
// - currentBlock: block number this node is currently importing
// - highestBlock: block number of the highest block header this node has received from peers
@@ -1527,11 +1533,13 @@ func (s *SyncState) HealingBytecode() hexutil.Uint64 {
// - healedBytecodeBytes: number of bytecodes persisted to disk
// - healingTrienodes: number of state trie nodes pending
// - healingBytecode: number of bytecodes pending
+// - txIndexFinishedBlocks: number of blocks whose transactions are indexed
+// - txIndexRemainingBlocks: number of blocks whose transactions are not indexed yet
func (r *Resolver) Syncing() (*SyncState, error) {
progress := r.backend.SyncProgress()
// Return not syncing if the synchronisation already completed
- if progress.CurrentBlock >= progress.HighestBlock {
+ if progress.Done() {
return nil, nil
}
// Otherwise gather the block sync stats
diff --git a/graphql/graphql_test.go b/graphql/graphql_test.go
index 73ef17c9c2..69ebcafe81 100644
--- a/graphql/graphql_test.go
+++ b/graphql/graphql_test.go
@@ -32,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/consensus/beacon"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
@@ -189,7 +190,7 @@ func TestGraphQLBlockSerializationEIP2718(t *testing.T) {
Config: params.AllEthashProtocolChanges,
GasLimit: 11500000,
Difficulty: big.NewInt(1048576),
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
address: {Balance: funds},
// The address 0xdad sloads 0x00 and 0x01
dad: {
@@ -287,7 +288,7 @@ func TestGraphQLConcurrentResolvers(t *testing.T) {
Config: params.AllEthashProtocolChanges,
GasLimit: 11500000,
Difficulty: big.NewInt(1048576),
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
addr: {Balance: big.NewInt(params.Ether)},
dad: {
// LOG0(0, 0), LOG0(0, 0), RETURN(0, 0)
@@ -387,7 +388,7 @@ func TestWithdrawals(t *testing.T) {
Config: params.AllEthashProtocolChanges,
GasLimit: 11500000,
Difficulty: common.Big1,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
addr: {Balance: big.NewInt(params.Ether)},
},
}
@@ -462,6 +463,7 @@ func newGQLService(t *testing.T, stack *node.Node, shanghai bool, gspec *core.Ge
TrieDirtyCache: 5,
TrieTimeout: 60 * time.Minute,
SnapshotCache: 5,
+ StateScheme: rawdb.HashScheme,
}
var engine consensus.Engine = ethash.NewFaker()
if shanghai {
diff --git a/interfaces.go b/interfaces.go
index 2ebe1cf562..0ece6fad7a 100644
--- a/interfaces.go
+++ b/interfaces.go
@@ -120,6 +120,18 @@ type SyncProgress struct {
HealingTrienodes uint64 // Number of state trie nodes pending
HealingBytecode uint64 // Number of bytecodes pending
+
+ // "transaction indexing" fields
+ TxIndexFinishedBlocks uint64 // Number of blocks whose transactions are already indexed
+ TxIndexRemainingBlocks uint64 // Number of blocks whose transactions are not indexed yet
+}
+
+// Done returns the indicator if the initial sync is finished or not.
+func (prog SyncProgress) Done() bool {
+ if prog.CurrentBlock < prog.HighestBlock {
+ return false
+ }
+ return prog.TxIndexRemainingBlocks == 0
}
// ChainSyncReader wraps access to the node's current sync status. If there's no
@@ -140,6 +152,10 @@ type CallMsg struct {
Data []byte // input data, usually an ABI-encoded contract method invocation
AccessList types.AccessList // EIP-2930 access list.
+
+ // For BlobTxType
+ BlobGasFeeCap *big.Int
+ BlobHashes []common.Hash
}
// A ContractCaller provides contract calls, essentially transactions that are executed by
@@ -199,6 +215,16 @@ type GasPricer interface {
SuggestGasPrice(ctx context.Context) (*big.Int, error)
}
+// GasPricer1559 provides access to the EIP-1559 gas price oracle.
+type GasPricer1559 interface {
+ SuggestGasTipCap(ctx context.Context) (*big.Int, error)
+}
+
+// FeeHistoryReader provides access to the fee history oracle.
+type FeeHistoryReader interface {
+ FeeHistory(ctx context.Context, blockCount uint64, lastBlock *big.Int, rewardPercentiles []float64) (*FeeHistory, error)
+}
+
// FeeHistory provides recent fee market data that consumers can use to determine
// a reasonable maxPriorityFeePerGas value.
type FeeHistory struct {
@@ -264,3 +290,13 @@ type ChainValidator interface {
RemoveMilestoneID(milestoneId string)
GetMilestoneIDsList() []string
}
+
+// BlockNumberReader provides access to the current block number.
+type BlockNumberReader interface {
+ BlockNumber(ctx context.Context) (uint64, error)
+}
+
+// ChainIDReader provides access to the chain ID.
+type ChainIDReader interface {
+ ChainID(ctx context.Context) (*big.Int, error)
+}
diff --git a/internal/build/archive.go b/internal/build/archive.go
index 4597237b9a..51b87dbe38 100644
--- a/internal/build/archive.go
+++ b/internal/build/archive.go
@@ -300,18 +300,22 @@ func extractFile(arpath string, armode os.FileMode, data io.Reader, dest string)
return fmt.Errorf("path %q escapes archive destination", target)
}
- // Ensure the destination directory exists.
+ // Remove the preivously-extracted file if it exists
+ if err := os.RemoveAll(target); err != nil {
+ return err
+ }
+
+ // Recreate the destination directory
if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil {
return err
}
// Copy file data.
- file, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, armode)
+ file, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY, armode)
if err != nil {
return err
}
-
- if _, err := io.Copy(file, data); err != nil {
+ if _, err = io.Copy(file, data); err != nil {
file.Close()
os.Remove(target)
diff --git a/internal/build/download.go b/internal/build/download.go
index d4605a9019..0ef907f738 100644
--- a/internal/build/download.go
+++ b/internal/build/download.go
@@ -40,8 +40,7 @@ func MustLoadChecksums(file string) *ChecksumDB {
if err != nil {
log.Fatal("can't load checksum file: " + err.Error())
}
-
- return &ChecksumDB{strings.Split(string(content), "\n")}
+ return &ChecksumDB{strings.Split(strings.ReplaceAll(string(content), "\r\n", "\n"), "\n")}
}
// Verify checks whether the given file is valid according to the checksum database.
@@ -89,12 +88,13 @@ func (db *ChecksumDB) DownloadFile(url, dstPath string) error {
resp, err := http.Get(url)
if err != nil {
return fmt.Errorf("download error: %v", err)
- } else if resp.StatusCode != http.StatusOK {
- return fmt.Errorf("download error: status %d", resp.StatusCode)
}
defer resp.Body.Close()
+ if resp.StatusCode != http.StatusOK {
+ return fmt.Errorf("download error: status %d", resp.StatusCode)
+ }
if err := os.MkdirAll(filepath.Dir(dstPath), 0755); err != nil {
return err
}
diff --git a/internal/build/gotool.go b/internal/build/gotool.go
index 5f76d829ec..5d4b467da5 100644
--- a/internal/build/gotool.go
+++ b/internal/build/gotool.go
@@ -155,7 +155,6 @@ func Version(csdb *ChecksumDB, version string) (string, error) {
continue
}
if parts[0] == version {
- log.Printf("Found version %q", parts[1])
return parts[1], nil
}
}
diff --git a/internal/build/util.go b/internal/build/util.go
index 937e648b6e..45891f0646 100644
--- a/internal/build/util.go
+++ b/internal/build/util.go
@@ -27,7 +27,6 @@ import (
"log"
"os"
"os/exec"
- "path"
"path/filepath"
"strconv"
"strings"
@@ -74,6 +73,27 @@ func MustRunCommand(cmd string, args ...string) {
MustRun(exec.Command(cmd, args...))
}
+// MustRunCommandWithOutput runs the given command, and ensures that some output will be
+// printed while it runs. This is useful for CI builds where the process will be stopped
+// when there is no output.
+func MustRunCommandWithOutput(cmd string, args ...string) {
+ interval := time.NewTicker(time.Minute)
+ done := make(chan struct{})
+ defer interval.Stop()
+ defer close(done)
+ go func() {
+ for {
+ select {
+ case <-interval.C:
+ fmt.Printf("Waiting for command %q\n", cmd)
+ case <-done:
+ return
+ }
+ }
+ }()
+ MustRun(exec.Command(cmd, args...))
+}
+
var warnedAboutGit bool
// RunGit runs a git subcommand and returns its output.
@@ -103,7 +123,7 @@ func RunGit(args ...string) string {
// readGitFile returns content of file in .git directory.
func readGitFile(file string) string {
- content, err := os.ReadFile(path.Join(".git", file))
+ content, err := os.ReadFile(filepath.Join(".git", file))
if err != nil {
return ""
}
@@ -176,7 +196,7 @@ func UploadSFTP(identityFile, host, dir string, files []string) error {
in := io.MultiWriter(stdin, os.Stdout)
for _, f := range files {
- fmt.Fprintln(in, "put", f, path.Join(dir, filepath.Base(f)))
+ fmt.Fprintln(in, "put", f, filepath.Join(dir, filepath.Base(f)))
}
fmt.Fprintln(in, "exit")
diff --git a/internal/cli/bootnode.go b/internal/cli/bootnode.go
index 2dd99cc8c0..c0f8d2476d 100644
--- a/internal/cli/bootnode.go
+++ b/internal/cli/bootnode.go
@@ -48,10 +48,10 @@ func (b *BootnodeCommand) Help() string {
}
// MarkDown implements cli.MarkDown interface
-func (c *BootnodeCommand) MarkDown() string {
+func (b *BootnodeCommand) MarkDown() string {
items := []string{
"# Bootnode",
- c.Flags().MarkDown(),
+ b.Flags().MarkDown(),
}
return strings.Join(items, "\n\n")
diff --git a/internal/cli/chain_sethead.go b/internal/cli/chain_sethead.go
index 718ada4648..353470cf20 100644
--- a/internal/cli/chain_sethead.go
+++ b/internal/cli/chain_sethead.go
@@ -18,13 +18,13 @@ type ChainSetHeadCommand struct {
}
// MarkDown implements cli.MarkDown interface
-func (a *ChainSetHeadCommand) MarkDown() string {
+func (c *ChainSetHeadCommand) MarkDown() string {
items := []string{
"# Chain sethead",
"The ```chain sethead ``` command sets the current chain to a certain block.",
"## Arguments",
"- ```number```: The block number to roll back.",
- a.Flags().MarkDown(),
+ c.Flags().MarkDown(),
}
return strings.Join(items, "\n\n")
diff --git a/internal/cli/command.go b/internal/cli/command.go
index 66ad650d9f..8c3bf02f0f 100644
--- a/internal/cli/command.go
+++ b/internal/cli/command.go
@@ -233,7 +233,7 @@ func (m *Meta2) NewFlagSet(n string) *flagset.Flagset {
}
func (m *Meta2) Conn() (*grpc.ClientConn, error) {
- conn, err := grpc.Dial(m.addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
+ conn, err := grpc.NewClient(m.addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
return nil, fmt.Errorf("failed to connect to server: %v", err)
}
diff --git a/internal/cli/debug.go b/internal/cli/debug.go
index baa29c8721..12ad94a50c 100644
--- a/internal/cli/debug.go
+++ b/internal/cli/debug.go
@@ -28,7 +28,7 @@ type DebugCommand struct {
}
// MarkDown implements cli.MarkDown interface
-func (d *DebugCommand) MarkDown() string {
+func (c *DebugCommand) MarkDown() string {
examples := []string{
"## Examples",
"By default it creates a tar.gz file with the output:",
diff --git a/internal/cli/debug_block.go b/internal/cli/debug_block.go
index 5a282cc550..011349083c 100644
--- a/internal/cli/debug_block.go
+++ b/internal/cli/debug_block.go
@@ -17,11 +17,11 @@ type DebugBlockCommand struct {
output string
}
-func (p *DebugBlockCommand) MarkDown() string {
+func (c *DebugBlockCommand) MarkDown() string {
items := []string{
"# Debug trace",
"The ```bor debug block ``` command will create an archive containing traces of a bor block.",
- p.Flags().MarkDown(),
+ c.Flags().MarkDown(),
}
return strings.Join(items, "\n\n")
diff --git a/internal/cli/debug_pprof.go b/internal/cli/debug_pprof.go
index ddb4520e9c..3910dc7e9c 100644
--- a/internal/cli/debug_pprof.go
+++ b/internal/cli/debug_pprof.go
@@ -21,11 +21,11 @@ type DebugPprofCommand struct {
skiptrace bool
}
-func (p *DebugPprofCommand) MarkDown() string {
+func (d *DebugPprofCommand) MarkDown() string {
items := []string{
"# Debug Pprof",
"The ```debug pprof ``` command will create an archive containing bor pprof traces.",
- p.Flags().MarkDown(),
+ d.Flags().MarkDown(),
}
return strings.Join(items, "\n\n")
diff --git a/internal/cli/dumpconfig.go b/internal/cli/dumpconfig.go
index 13ef57c087..0597bfdec4 100644
--- a/internal/cli/dumpconfig.go
+++ b/internal/cli/dumpconfig.go
@@ -15,7 +15,7 @@ type DumpconfigCommand struct {
}
// MarkDown implements cli.MarkDown interface
-func (p *DumpconfigCommand) MarkDown() string {
+func (c *DumpconfigCommand) MarkDown() string {
items := []string{
"# Dumpconfig",
"The ```bor dumpconfig ``` command will export the user provided flags into a configuration file",
diff --git a/internal/cli/peers.go b/internal/cli/peers.go
index fbbca24fad..5d87178f12 100644
--- a/internal/cli/peers.go
+++ b/internal/cli/peers.go
@@ -12,7 +12,7 @@ type PeersCommand struct {
}
// MarkDown implements cli.MarkDown interface
-func (a *PeersCommand) MarkDown() string {
+func (c *PeersCommand) MarkDown() string {
items := []string{
"# Peers",
"The ```peers``` command groups actions to interact with peers:",
diff --git a/internal/cli/peers_add.go b/internal/cli/peers_add.go
index 3df1a6b6cb..10bbc1fcb8 100644
--- a/internal/cli/peers_add.go
+++ b/internal/cli/peers_add.go
@@ -48,36 +48,36 @@ func (p *PeersAddCommand) Flags() *flagset.Flagset {
}
// Synopsis implements the cli.Command interface
-func (c *PeersAddCommand) Synopsis() string {
+func (p *PeersAddCommand) Synopsis() string {
return "Join the client to a remote peer"
}
// Run implements the cli.Command interface
-func (c *PeersAddCommand) Run(args []string) int {
- flags := c.Flags()
+func (p *PeersAddCommand) Run(args []string) int {
+ flags := p.Flags()
if err := flags.Parse(args); err != nil {
- c.UI.Error(err.Error())
+ p.UI.Error(err.Error())
return 1
}
args = flags.Args()
if len(args) != 1 {
- c.UI.Error("No enode address provided")
+ p.UI.Error("No enode address provided")
return 1
}
- borClt, err := c.BorConn()
+ borClt, err := p.BorConn()
if err != nil {
- c.UI.Error(err.Error())
+ p.UI.Error(err.Error())
return 1
}
req := &proto.PeersAddRequest{
Enode: args[0],
- Trusted: c.trusted,
+ Trusted: p.trusted,
}
if _, err := borClt.PeersAdd(context.Background(), req); err != nil {
- c.UI.Error(err.Error())
+ p.UI.Error(err.Error())
return 1
}
diff --git a/internal/cli/peers_list.go b/internal/cli/peers_list.go
index 4a572447c1..a0e8fadc34 100644
--- a/internal/cli/peers_list.go
+++ b/internal/cli/peers_list.go
@@ -41,21 +41,21 @@ func (p *PeersListCommand) Flags() *flagset.Flagset {
}
// Synopsis implements the cli.Command interface
-func (c *PeersListCommand) Synopsis() string {
+func (p *PeersListCommand) Synopsis() string {
return ""
}
// Run implements the cli.Command interface
-func (c *PeersListCommand) Run(args []string) int {
- flags := c.Flags()
+func (p *PeersListCommand) Run(args []string) int {
+ flags := p.Flags()
if err := flags.Parse(args); err != nil {
- c.UI.Error(err.Error())
+ p.UI.Error(err.Error())
return 1
}
- borClt, err := c.BorConn()
+ borClt, err := p.BorConn()
if err != nil {
- c.UI.Error(err.Error())
+ p.UI.Error(err.Error())
return 1
}
@@ -63,11 +63,11 @@ func (c *PeersListCommand) Run(args []string) int {
resp, err := borClt.PeersList(context.Background(), req)
if err != nil {
- c.UI.Error(err.Error())
+ p.UI.Error(err.Error())
return 1
}
- c.UI.Output(formatPeers(resp.Peers))
+ p.UI.Output(formatPeers(resp.Peers))
return 0
}
diff --git a/internal/cli/peers_remove.go b/internal/cli/peers_remove.go
index f53284c40c..e3d30dfa53 100644
--- a/internal/cli/peers_remove.go
+++ b/internal/cli/peers_remove.go
@@ -48,36 +48,36 @@ func (p *PeersRemoveCommand) Flags() *flagset.Flagset {
}
// Synopsis implements the cli.Command interface
-func (c *PeersRemoveCommand) Synopsis() string {
+func (p *PeersRemoveCommand) Synopsis() string {
return "Disconnects a peer from the client"
}
// Run implements the cli.Command interface
-func (c *PeersRemoveCommand) Run(args []string) int {
- flags := c.Flags()
+func (p *PeersRemoveCommand) Run(args []string) int {
+ flags := p.Flags()
if err := flags.Parse(args); err != nil {
- c.UI.Error(err.Error())
+ p.UI.Error(err.Error())
return 1
}
args = flags.Args()
if len(args) != 1 {
- c.UI.Error("No enode address provided")
+ p.UI.Error("No enode address provided")
return 1
}
- borClt, err := c.BorConn()
+ borClt, err := p.BorConn()
if err != nil {
- c.UI.Error(err.Error())
+ p.UI.Error(err.Error())
return 1
}
req := &proto.PeersRemoveRequest{
Enode: args[0],
- Trusted: c.trusted,
+ Trusted: p.trusted,
}
if _, err := borClt.PeersRemove(context.Background(), req); err != nil {
- c.UI.Error(err.Error())
+ p.UI.Error(err.Error())
return 1
}
diff --git a/internal/cli/peers_status.go b/internal/cli/peers_status.go
index f5d700a273..ad02e22dc8 100644
--- a/internal/cli/peers_status.go
+++ b/internal/cli/peers_status.go
@@ -41,27 +41,27 @@ func (p *PeersStatusCommand) Flags() *flagset.Flagset {
}
// Synopsis implements the cli.Command interface
-func (c *PeersStatusCommand) Synopsis() string {
+func (p *PeersStatusCommand) Synopsis() string {
return "Display the status of a peer"
}
// Run implements the cli.Command interface
-func (c *PeersStatusCommand) Run(args []string) int {
- flags := c.Flags()
+func (p *PeersStatusCommand) Run(args []string) int {
+ flags := p.Flags()
if err := flags.Parse(args); err != nil {
- c.UI.Error(err.Error())
+ p.UI.Error(err.Error())
return 1
}
args = flags.Args()
if len(args) != 1 {
- c.UI.Error("No enode address provided")
+ p.UI.Error("No enode address provided")
return 1
}
- borClt, err := c.BorConn()
+ borClt, err := p.BorConn()
if err != nil {
- c.UI.Error(err.Error())
+ p.UI.Error(err.Error())
return 1
}
@@ -71,11 +71,11 @@ func (c *PeersStatusCommand) Run(args []string) int {
resp, err := borClt.PeersStatus(context.Background(), req)
if err != nil {
- c.UI.Error(err.Error())
+ p.UI.Error(err.Error())
return 1
}
- c.UI.Output(formatPeer(resp.Peer))
+ p.UI.Output(formatPeer(resp.Peer))
return 0
}
diff --git a/internal/cli/server/chains/amoy.go b/internal/cli/server/chains/amoy.go
index 98a15de3b4..60ec4464eb 100644
--- a/internal/cli/server/chains/amoy.go
+++ b/internal/cli/server/chains/amoy.go
@@ -29,9 +29,10 @@ var amoyTestnet = &Chain{
ShanghaiBlock: big.NewInt(73100),
CancunBlock: big.NewInt(5423600),
Bor: ¶ms.BorConfig{
- JaipurBlock: big.NewInt(73100),
- DelhiBlock: big.NewInt(73100),
- IndoreBlock: big.NewInt(73100),
+ JaipurBlock: big.NewInt(73100),
+ DelhiBlock: big.NewInt(73100),
+ IndoreBlock: big.NewInt(73100),
+ AhmedabadBlock: big.NewInt(11865856),
StateSyncConfirmationDelay: map[string]uint64{
"0": 128,
},
@@ -53,6 +54,31 @@ var amoyTestnet = &Chain{
"0": "0x000000000000000000000000000000000000dead",
"73100": "0xeCDD77cE6f146cCf5dab707941d318Bd50eeD2C9",
},
+ BlockAlloc: map[string]interface{}{
+ "11865856": map[string]interface{}{
+ // StateReceiver contract
+ "0000000000000000000000000000000000001001": map[string]interface{}{
+ "balance": "0x0",
+ "code": "0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c80635407ca671161008c578063abca220411610066578063abca2204146102fa578063d72a0b6714610302578063ee3a87f21461031f578063f165053614610342576100cf565b80635407ca67146102585780636757e5d914610260578063942af179146102f2576100cf565b806303112a17146100d457806319494a17146100f357806330e69fc31461017e578063318926f7146101985780633434735f146101bc57806351950cd9146101c4575b600080fd5b6100f1600480360360208110156100ea57600080fd5b503561034a565b005b61016a6004803603604081101561010957600080fd5b8135919081019060408101602082013564010000000081111561012b57600080fd5b82018360208201111561013d57600080fd5b8035906020019184600183028401116401000000008311171561015f57600080fd5b50909250905061060d565b604080519115158252519081900360200190f35b61018661093e565b60408051918252519081900360200190f35b6101a0610944565b604080516001600160a01b039092168252519081900360200190f35b6101a0610968565b6100f160048036036102808110156101db57600080fd5b61020082013590610220830135906001600160a01b036102408501351690840184610280810161026082013564010000000081111561021957600080fd5b82018360208201111561022b57600080fd5b8035906020019184600183028401116401000000008311171561024d57600080fd5b509092509050610973565b610186610c78565b61027d6004803603602081101561027657600080fd5b5035610c7e565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102b757818101518382015260200161029f565b50505050905090810190601f1680156102e45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610186610d19565b610186610d1f565b61016a6004803603602081101561031857600080fd5b5035610d25565b6100f16004803603604081101561033557600080fd5b5080359060200135610d3a565b610186610db0565b60008181526003602090815260409182902080548351601f60026000196101006001861615020190931692909204918201849004840281018401909452808452606093928301828280156103df5780601f106103b4576101008083540402835291602001916103df565b820191906000526020600020905b8154815290600101906020018083116103c257829003601f168201915b50505050509050805160001415610426576040805162461bcd60e51b815260206004820152600660248201526508599bdd5b9960d21b604482015290519081900360640190fd5b600082815260036020526040812061043d916112bb565b6000606082806020019051604081101561045657600080fd5b81516020830180516040519294929383019291908464010000000082111561047d57600080fd5b90830190602082018581111561049257600080fd5b82516401000000008111828201881017156104ac57600080fd5b82525081516020918201929091019080838360005b838110156104d95781810151838201526020016104c1565b50505050905090810190601f1680156105065780820380516001836020036101000a031916815260200191505b5060405250505091509150837f8797144948782adcede8e04bfa0bd8fd56941e0df7508bd02a629b477f7b073a60405160405180910390a2604080516313629df560e11b815260048101868152602482019283528351604483015283516001600160a01b038616936326c53bea938993879390929160640190602085019080838360005b838110156105a257818101518382015260200161058a565b50505050905090810190601f1680156105cf5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b1580156105ef57600080fd5b505af1158015610603573d6000803e3d6000fd5b5050505050505050565b6000336002600160a01b031461065f576040805162461bcd60e51b81526020600482015260126024820152714e6f742053797374656d204164646573732160701b604482015290519081900360640190fd5b60606106a86106a385858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610db592505050565b610ddb565b905060006106c9826000815181106106bc57fe5b6020026020010151610f14565b90508060005460010114610724576040805162461bcd60e51b815260206004820152601b60248201527f537461746549647320617265206e6f742073657175656e7469616c0000000000604482015290519081900360640190fd5b6000805460019081018255835161074c918591811061073f57fe5b6020026020010151610f62565b9050606061076d8460028151811061076057fe5b6020026020010151610f82565b905061077882610fff565b15610933576000624c4b409050606084836040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156107cf5781810151838201526020016107b7565b50505050905090810190601f1680156107fc5780820380516001836020036101000a031916815260200191505b5060408051601f198184030181529190526020810180516001600160e01b03166313629df560e11b1781528151919650600095508594509092509050828887f1604080518215158152905191985086917f5a22725590b0a51c923940223f7458512164b1113359a735e86e7f27f44791ee9181900360200190a28661093057838360405160200180836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156108cc5781810151838201526020016108b4565b50505050905090810190601f1680156108f95780820380516001836020036101000a031916815260200191505b5060408051601f1981840301815291815260008b815260036020908152919020825161092e9750909550910192509050611302565b505b50505b505050509392505050565b60045481565b7f000000000000000000000000be971fef2bb60f709e1daf3e55d00914e230cd9481565b6002600160a01b0381565b6201000085106109be576040805162461bcd60e51b81526020600482015260116024820152700d2dcecc2d8d2c840d8cac2cc92dcc8caf607b1b604482015290519081900360640190fd5b60045460058054600101908190551115610a05576040805162461bcd60e51b8152602060048201526003602482015262195b9960ea1b604482015290519081900360640190fd5b60015480610a42576040805162461bcd60e51b8152602060048201526005602482015264085c9bdbdd60da1b604482015290519081900360640190fd5b60008585858560405160200180858152602001846001600160a01b0316815260200180602001828103825284848281815260200192508082843760008184015260408051601f19601f909301831690940184810390920184525250805160209091012096507f28cf91ac064e179f8a42e4b7a20ba080187781da55fd4f3f18870b7a25bacb559550505050828414801592509050610aef575060008281526002602052604090205460ff16155b610b29576040805162461bcd60e51b815260206004808301919091526024820152631d5cd95960e21b604482015290519081900360640190fd5b60008281526002602052604090819020805460ff191660011790558051610200818101909252610b74918b9060109083908390808284376000920191909152508b915085905061100b565b8314610bb0576040805162461bcd60e51b815260206004820152600660248201526510b83937b7b360d11b604482015290519081900360640190fd5b60405187907f8797144948782adcede8e04bfa0bd8fd56941e0df7508bd02a629b477f7b073a90600090a2604080516313629df560e11b81526004810189815260248201928352604482018790526001600160a01b038916926326c53bea928b928a928a92606401848480828437600081840152601f19601f820116905080830192505050945050505050600060405180830381600087803b158015610c5557600080fd5b505af1158015610c69573d6000803e3d6000fd5b50505050505050505050505050565b60005481565b60036020908152600091825260409182902080548351601f600260001961010060018616150201909316929092049182018490048402810184019094528084529091830182828015610d115780601f10610ce657610100808354040283529160200191610d11565b820191906000526020600020905b815481529060010190602001808311610cf457829003601f168201915b505050505081565b60055481565b60015481565b60026020526000908152604090205460ff1681565b336001600160a01b037f000000000000000000000000be971fef2bb60f709e1daf3e55d00914e230cd941614610da5576040805162461bcd60e51b815260206004820152600b60248201526a10b937b7ba29b2ba3a32b960a91b604482015290519081900360640190fd5b600191909155600455565b601081565b610dbd611380565b5060408051808201909152815181526020828101908201525b919050565b6060610de6826110b6565b610def57600080fd5b6000610dfa836110f0565b905060608167ffffffffffffffff81118015610e1557600080fd5b50604051908082528060200260200182016040528015610e4f57816020015b610e3c611380565b815260200190600190039081610e345790505b5090506000610e618560200151611148565b60208601510190506000805b84811015610eb857610e7e836111ab565b9150604051806040016040528083815260200184815250848281518110610ea157fe5b602090810291909101015291810191600101610e6d565b5085516020870151830314610f0a576040805162461bcd60e51b81526020600482015260136024820152722bb937b733903a37ba30b6103632b733ba341760691b604482015290519081900360640190fd5b5090949350505050565b805160009015801590610f2957508151602110155b610f3257600080fd5b600080610f3e84611244565b815191935091506020821015610f5a5760208290036101000a90045b949350505050565b8051600090601514610f7357600080fd5b610f7c82610f14565b92915050565b8051606090610f9057600080fd5b600080610f9c84611244565b9150915060608167ffffffffffffffff81118015610fb957600080fd5b506040519080825280601f01601f191660200182016040528015610fe4576020820181803683370190505b50905060208101610ff684828561126a565b50949350505050565b3b63ffffffff16151590565b600081815b6010811015610ff657600185821c8116141561106c5785816010811061103257fe5b60200201518260405160200180838152602001828152602001925050506040516020818303038152906040528051906020012091506110ae565b8186826010811061107957fe5b602002015160405160200180838152602001828152602001925050506040516020818303038152906040528051906020012091505b600101611010565b80516000906110c757506000610dd6565b6020820151805160001a9060c08210156110e657600092505050610dd6565b5060019392505050565b805160009061110157506000610dd6565b6000806111118460200151611148565b602085015185519181019250015b8082101561113f57611130826111ab565b6001909301929091019061111f565b50909392505050565b8051600090811a6080811015611162576000915050610dd6565b60b881108061117d575060c0811080159061117d575060f881105b1561118c576001915050610dd6565b60c08110156111a05760b519019050610dd6565b60f519019050610dd6565b80516000908190811a60808110156111c6576001915061123d565b60b88110156111db57607e198101915061123d565b60c08110156112085760b78103600185019450806020036101000a8551046001820181019350505061123d565b60f881101561121d5760be198101915061123d565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b60008060006112568460200151611148565b602085015194519481019594039392505050565b80611274576112b6565b5b60208110611294578251825260209283019290910190601f1901611275565b80156112b6578251825160208390036101000a60001901801990921691161782525b505050565b50805460018160011615610100020316600290046000825580601f106112e157506112ff565b601f0160209004906000526020600020908101906112ff919061139a565b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061134357805160ff1916838001178555611370565b82800160010185558215611370579182015b82811115611370578251825591602001919060010190611355565b5061137c92915061139a565b5090565b604051806040016040528060008152602001600081525090565b5b8082111561137c576000815560010161139b56fea164736f6c634300060c000a",
+ },
+ // MRC20 contract
+ "0000000000000000000000000000000000001010": map[string]interface{}{
+ "balance": "0x0",
+ "code": "0x6080604052600436106101b75760003560e01c80638da5cb5b116100ec578063b789543c1161008a578063e614d0d611610064578063e614d0d614610695578063ed9ef524146106aa578063f2fde38b146106dd578063fc0c546a14610710576101b7565b8063b789543c14610626578063cc79f97b1461066b578063e306f77914610680576101b7565b806395d89b41116100c657806395d89b41146105a6578063a9059cbb146105bb578063abceeba2146105e7578063acd06cb3146105fc576101b7565b80638da5cb5b146105535780638f32d59b146105685780639025e64c14610591576101b7565b806347e7ef241161015957806370a082311161013357806370a082311461043c578063715018a61461046f578063771282f61461048457806377d32e9414610499576101b7565b806347e7ef24146103b3578063485cc955146103ec57806360f96a8f14610427576101b7565b806319d27d9c1161019557806319d27d9c146102a25780632e1a7d4d14610356578063313ce5671461037357806342fc47fb1461039e576101b7565b806306fdde03146101bc5780631499c5921461024657806318160ddd1461027b575b600080fd5b3480156101c857600080fd5b506101d1610725565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561020b5781810151838201526020016101f3565b50505050905090810190601f1680156102385780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025257600080fd5b506102796004803603602081101561026957600080fd5b50356001600160a01b031661075c565b005b34801561028757600080fd5b5061029061079c565b60408051918252519081900360200190f35b3480156102ae57600080fd5b5061033a600480360360a08110156102c557600080fd5b8101906020810181356401000000008111156102e057600080fd5b8201836020820111156102f257600080fd5b8035906020019184600183028401116401000000008311171561031457600080fd5b9193509150803590602081013590604081013590606001356001600160a01b03166107ac565b604080516001600160a01b039092168252519081900360200190f35b6102796004803603602081101561036c57600080fd5b50356107ee565b34801561037f57600080fd5b506103886108c6565b6040805160ff9092168252519081900360200190f35b3480156103aa57600080fd5b5061033a6108cb565b3480156103bf57600080fd5b50610279600480360360408110156103d657600080fd5b506001600160a01b0381351690602001356108da565b3480156103f857600080fd5b506102796004803603604081101561040f57600080fd5b506001600160a01b03813581169160200135166109a8565b34801561043357600080fd5b5061033a610a21565b34801561044857600080fd5b506102906004803603602081101561045f57600080fd5b50356001600160a01b0316610a30565b34801561047b57600080fd5b50610279610a3d565b34801561049057600080fd5b50610290610a98565b3480156104a557600080fd5b5061033a600480360360408110156104bc57600080fd5b813591908101906040810160208201356401000000008111156104de57600080fd5b8201836020820111156104f057600080fd5b8035906020019184600183028401116401000000008311171561051257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610a9e945050505050565b34801561055f57600080fd5b5061033a610bc2565b34801561057457600080fd5b5061057d610bd1565b604080519115158252519081900360200190f35b34801561059d57600080fd5b506101d1610be2565b3480156105b257600080fd5b506101d1610c00565b61057d600480360360408110156105d157600080fd5b506001600160a01b038135169060200135610c1d565b3480156105f357600080fd5b50610290610c40565b34801561060857600080fd5b5061057d6004803603602081101561061f57600080fd5b5035610cc9565b34801561063257600080fd5b506102906004803603608081101561064957600080fd5b506001600160a01b038135169060208101359060408101359060600135610cde565b34801561067757600080fd5b50610290610cfd565b34801561068c57600080fd5b50610290610d03565b3480156106a157600080fd5b50610290610d09565b3480156106b657600080fd5b50610279600480360360208110156106cd57600080fd5b50356001600160a01b0316610d53565b3480156106e957600080fd5b506102796004803603602081101561070057600080fd5b50356001600160a01b0316610e05565b34801561071c57600080fd5b5061033a610e22565b60408051808201909152601781527f506f6c79676f6e2045636f73797374656d20546f6b656e000000000000000000602082015290565b6040805162461bcd60e51b815260206004820152601060248201526f44697361626c6564206665617475726560801b604482015290519081900360640190fd5b6b204fce5e3e2502611000000090565b6040805162461bcd60e51b815260206004820152601060248201526f44697361626c6564206665617475726560801b6044820152905160009181900360640190fd5b3360006107fa82610a30565b600654909150610810908463ffffffff610e3116565b600655821580159061082157508234145b610868576040805162461bcd60e51b8152602060048201526013602482015272125b9cdd59999a58da595b9d08185b5bdd5b9d606a1b604482015290519081900360640190fd5b6002546001600160a01b0380841691167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f85846108a487610a30565b60408051938452602084019290925282820152519081900360600190a3505050565b601290565b6003546001600160a01b031681565b6108e2610bd1565b6108eb57600080fd5b60008111801561090357506001600160a01b03821615155b61093e5760405162461bcd60e51b815260040180806020018281038252602381526020018061138d6023913960400191505060405180910390fd5b600061094983610a30565b60065490915061095f908363ffffffff610e4616565b60065561096c8383610e58565b6002546001600160a01b0380851691167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f684846108a488610a30565b60075460ff16156109ea5760405162461bcd60e51b815260040180806020018281038252602381526020018061136a6023913960400191505060405180910390fd5b6007805460ff19166001179055600280546001600160a01b0383166001600160a01b0319909116179055610a1d82610f17565b5050565b6004546001600160a01b031681565b6001600160a01b03163190565b610a45610bd1565b610a4e57600080fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b60065481565b6000806000808451604114610ab95760009350505050610bbc565b50505060208201516040830151604184015160ff16601b811015610adb57601b015b8060ff16601b14158015610af357508060ff16601c14155b15610b045760009350505050610bbc565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa158015610b5b573d6000803e3d6000fd5b5050604051601f1901519450506001600160a01b038416610bb8576040805162461bcd60e51b815260206004820152601260248201527122b93937b91034b71032b1b932b1b7bb32b960711b604482015290519081900360640190fd5b5050505b92915050565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b604051806040016040528060028152602001613a9960f01b81525081565b6040805180820190915260038152621413d360ea1b602082015290565b6000813414610c2e57506000610bbc565b610c39338484610f85565b9392505050565b6040518060800160405280605b8152602001611434605b91396040516020018082805190602001908083835b60208310610c8b5780518252601f199092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b60056020526000908152604090205460ff1681565b6000610cf4610cef868686866111d2565b61128b565b95945050505050565b613a9981565b60015481565b6040518060800160405280605281526020016113b06052913960405160200180828051906020019080838360208310610c8b5780518252601f199092019160209182019101610c6c565b610d5b610bd1565b610d6457600080fd5b6001600160a01b038116610da95760405162461bcd60e51b81526004018080602001828103825260328152602001806114026032913960400191505060405180910390fd5b6003546040516001600160a01b038084169216907f1f9f3556dd336016cdf20adaead7d5c73665dba664b60e8c17e9a4eb91ce1d3990600090a3600380546001600160a01b0319166001600160a01b0392909216919091179055565b610e0d610bd1565b610e1657600080fd5b610e1f81610f17565b50565b6002546001600160a01b031681565b600082821115610e4057600080fd5b50900390565b600082820183811015610c3957600080fd5b60085415610e9a576040805162461bcd60e51b815260206004820152600a6024820152697265656e7472616e637960b01b604482015290519081900360640190fd5b6001600855604051611388906000906060906001600160a01b038616908490869085818181858888f193505050503d8060008114610ef4576040519150601f19603f3d011682016040523d82523d6000602084013e610ef9565b606091505b509150915081610f0b57805160208201fd5b50506000600855505050565b6001600160a01b038116610f2a57600080fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b604080516370a0823160e01b81526001600160a01b03851660048201529051600091829130916370a08231916024808301926020929190829003018186803b158015610fd057600080fd5b505afa158015610fe4573d6000803e3d6000fd5b505050506040513d6020811015610ffa57600080fd5b5051604080516370a0823160e01b81526001600160a01b0387166004820152905191925060009130916370a08231916024808301926020929190829003018186803b15801561104857600080fd5b505afa15801561105c573d6000803e3d6000fd5b505050506040513d602081101561107257600080fd5b50519050611081868686611299565b600254604080516370a0823160e01b81526001600160a01b03898116600483018190529251818a1694909116917fe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c49189918891889130916370a0823191602480820192602092909190829003018186803b1580156110fe57600080fd5b505afa158015611112573d6000803e3d6000fd5b505050506040513d602081101561112857600080fd5b5051604080516370a0823160e01b81526001600160a01b038f166004820152905130916370a08231916024808301926020929190829003018186803b15801561117057600080fd5b505afa158015611184573d6000803e3d6000fd5b505050506040513d602081101561119a57600080fd5b50516040805195865260208601949094528484019290925260608401526080830152519081900360a00190a450600195945050505050565b6000806040518060800160405280605b8152602001611434605b91396040516020018082805190602001908083835b602083106112205780518252601f199092019160209182019101611201565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f1901835280855282519282019290922082526001600160a01b039b909b169a81019a909a5250880196909652505050606084019190915260808301525060a0902090565b6000610bbc82600154611347565b6001600160a01b0382163014156112ed576040805162461bcd60e51b8152602060048201526013602482015272063616e27742073656e6420746f204d5243323606c1b604482015290519081900360640190fd5b6112f78282610e58565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b60405161190160f01b815260028101919091526022810191909152604290209056fe54686520636f6e747261637420697320616c726561647920696e697469616c697a6564496e73756666696369656e7420616d6f756e74206f7220696e76616c69642075736572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e7472616374294368696c6420746f6b656e3a206e6577206368696c64206164647265737320697320746865207a65726f2061646472657373546f6b656e5472616e736665724f726465722861646472657373207370656e6465722c75696e7432353620746f6b656e49644f72416d6f756e742c6279746573333220646174612c75696e743235362065787069726174696f6e29a265627a7a723158205f23be7574e70cfc01d0cfd6803b871f92465e9ae4a10fe95ed31ccb810bda3e64736f6c63430005110032",
+ },
+ // WMATIC contract
+ "360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9": map[string]interface{}{
+ "balance": "0x0",
+ "code": "0x6080604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b9578063095ea7b31461014957806318160ddd146101ae57806323b872dd146101d95780632e1a7d4d1461025e578063313ce5671461028b57806370a08231146102bc57806395d89b4114610313578063a9059cbb146103a3578063d0e30db014610408578063dd62ed3e14610412575b6100b7610489565b005b3480156100c557600080fd5b506100ce610526565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561010e5780820151818401526020810190506100f3565b50505050905090810190601f16801561013b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015557600080fd5b50610194600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105c4565b604051808215151515815260200191505060405180910390f35b3480156101ba57600080fd5b506101c36106b6565b6040518082815260200191505060405180910390f35b3480156101e557600080fd5b50610244600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506106d5565b604051808215151515815260200191505060405180910390f35b34801561026a57600080fd5b5061028960048036038101908080359060200190929190505050610a22565b005b34801561029757600080fd5b506102a0610b55565b604051808260ff1660ff16815260200191505060405180910390f35b3480156102c857600080fd5b506102fd600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b68565b6040518082815260200191505060405180910390f35b34801561031f57600080fd5b50610328610b80565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036857808201518184015260208101905061034d565b50505050905090810190601f1680156103955780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103af57600080fd5b506103ee600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610c1e565b604051808215151515815260200191505060405180910390f35b610410610489565b005b34801561041e57600080fd5b50610473600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c33565b6040518082815260200191505060405180910390f35b34600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055503373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a2565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156105bc5780601f10610591576101008083540402835291602001916105bc565b820191906000526020600020905b81548152906001019060200180831161059f57829003601f168201915b505050505081565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60003073ffffffffffffffffffffffffffffffffffffffff1631905090565b600081600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561072557600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141580156107fd57507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414155b156109185781600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561088d57600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b81600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a7057600080fd5b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610b03573d6000803e3d6000fd5b503373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65826040518082815260200191505060405180910390a250565b600260009054906101000a900460ff1681565b60036020528060005260406000206000915090505481565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c165780601f10610beb57610100808354040283529160200191610c16565b820191906000526020600020905b815481529060010190602001808311610bf957829003601f168201915b505050505081565b6000610c2b3384846106d5565b905092915050565b60046020528160005260406000206020528060005260406000206000915091505054815600a165627a7a72305820ea7b3a90a89969eb00d2a56f58b0f80481944475908acf25438759b53be73e5b0029",
+ },
+ },
+ "12121856": map[string]interface{}{
+ "360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9": map[string]interface{}{
+ "balance": "0x0",
+ "code": "0x6080604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b9578063095ea7b31461014957806318160ddd146101ae57806323b872dd146101d95780632e1a7d4d1461025e578063313ce5671461028b57806370a08231146102bc57806395d89b4114610313578063a9059cbb146103a3578063d0e30db014610408578063dd62ed3e14610412575b6100b7610489565b005b3480156100c557600080fd5b506100ce610526565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561010e5780820151818401526020810190506100f3565b50505050905090810190601f16801561013b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015557600080fd5b50610194600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610563565b604051808215151515815260200191505060405180910390f35b3480156101ba57600080fd5b506101c3610655565b6040518082815260200191505060405180910390f35b3480156101e557600080fd5b50610244600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610674565b604051808215151515815260200191505060405180910390f35b34801561026a57600080fd5b50610289600480360381019080803590602001909291905050506109c1565b005b34801561029757600080fd5b506102a0610af4565b604051808260ff1660ff16815260200191505060405180910390f35b3480156102c857600080fd5b506102fd600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610afd565b6040518082815260200191505060405180910390f35b34801561031f57600080fd5b50610328610b15565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036857808201518184015260208101905061034d565b50505050905090810190601f1680156103955780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103af57600080fd5b506103ee600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610b52565b604051808215151515815260200191505060405180910390f35b610410610489565b005b34801561041e57600080fd5b50610473600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b67565b6040518082815260200191505060405180910390f35b34600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055503373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a2565b60606040805190810160405280601f81526020017f5772617070656420506f6c79676f6e2045636f73797374656d20546f6b656e00815250905090565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60003073ffffffffffffffffffffffffffffffffffffffff1631905090565b600081600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156106c457600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415801561079c57507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414155b156108b75781600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561082c57600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b81600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a0f57600080fd5b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610aa2573d6000803e3d6000fd5b503373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65826040518082815260200191505060405180910390a250565b60006012905090565b60036020528060005260406000206000915090505481565b60606040805190810160405280600481526020017f57504f4c00000000000000000000000000000000000000000000000000000000815250905090565b6000610b5f338484610674565b905092915050565b60046020528160005260406000206020528060005260406000206000915091505054815600a165627a7a723058208d70d8aa2d752533105b5ccda8206dae8b0c1de765f89fb1f0c5727cbac1b40d0029",
+ },
+ },
+ },
},
},
Nonce: 0,
diff --git a/internal/cli/server/chains/developer.go b/internal/cli/server/chains/developer.go
index 40d65005f9..fdc20a84f3 100644
--- a/internal/cli/server/chains/developer.go
+++ b/internal/cli/server/chains/developer.go
@@ -5,6 +5,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
)
@@ -29,7 +30,7 @@ func GetDeveloperChain(period uint64, gasLimitt uint64, faucet common.Address) *
GasLimit: gasLimitt,
BaseFee: big.NewInt(params.InitialBaseFee),
Difficulty: big.NewInt(1),
- Alloc: map[common.Address]core.GenesisAccount{
+ Alloc: map[common.Address]types.Account{
common.BytesToAddress([]byte{1}): {Balance: big.NewInt(1)}, // ECRecover
common.BytesToAddress([]byte{2}): {Balance: big.NewInt(1)}, // SHA256
common.BytesToAddress([]byte{3}): {Balance: big.NewInt(1)}, // RIPEMD
diff --git a/internal/cli/server/chains/mainnet.go b/internal/cli/server/chains/mainnet.go
index 35f57f762c..3b97156e9b 100644
--- a/internal/cli/server/chains/mainnet.go
+++ b/internal/cli/server/chains/mainnet.go
@@ -30,9 +30,10 @@ var mainnetBor = &Chain{
ShanghaiBlock: big.NewInt(50523000),
CancunBlock: big.NewInt(54876000),
Bor: ¶ms.BorConfig{
- JaipurBlock: big.NewInt(23850000),
- DelhiBlock: big.NewInt(38189056),
- IndoreBlock: big.NewInt(44934656),
+ JaipurBlock: big.NewInt(23850000),
+ DelhiBlock: big.NewInt(38189056),
+ IndoreBlock: big.NewInt(44934656),
+ AhmedabadBlock: big.NewInt(62278656),
StateSyncConfirmationDelay: map[string]uint64{
"44934656": 128,
},
@@ -81,6 +82,23 @@ var mainnetBor = &Chain{
"code": "0x608060405234801561001057600080fd5b506004361061005e576000357c01000000000000000000000000000000000000000000000000000000009004806319494a17146100635780633434735f146100fe5780635407ca6714610148575b600080fd5b6100e46004803603604081101561007957600080fd5b8101908080359060200190929190803590602001906401000000008111156100a057600080fd5b8201836020820111156100b257600080fd5b803590602001918460018302840111640100000000831117156100d457600080fd5b9091929391929390505050610166565b604051808215151515815260200191505060405180910390f35b6101066104d3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101506104eb565b6040518082815260200191505060405180910390f35b600073fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461021d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4e6f742053797374656d2041646465737321000000000000000000000000000081525060200191505060405180910390fd5b606061027461026f85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506104f1565b61051f565b905060006102958260008151811061028857fe5b60200260200101516105fc565b90508060016000540114610311576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f537461746549647320617265206e6f742073657175656e7469616c000000000081525060200191505060405180910390fd5b600080815480929190600101919050555060006103418360018151811061033457fe5b602002602001015161066d565b905060606103628460028151811061035557fe5b6020026020010151610690565b905061036d8261071c565b156104c8576000624c4b409050606084836040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156103c75780820151818401526020810190506103ac565b50505050905090810190601f1680156103f45780820380516001836020036101000a031916815260200191505b5093505050506040516020818303038152906040527f26c53bea000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060008082516020840160008887f19650847f5a22725590b0a51c923940223f7458512164b1113359a735e86e7f27f44791ee88604051808215151515815260200191505060405180910390a250505b505050509392505050565b73fffffffffffffffffffffffffffffffffffffffe81565b60005481565b6104f961099c565b600060208301905060405180604001604052808451815260200182815250915050919050565b606061052a82610735565b61053357600080fd5b600061053e83610783565b905060608160405190808252806020026020018201604052801561057c57816020015b6105696109b6565b8152602001906001900390816105615790505b509050600061058e85602001516107f4565b8560200151019050600080600090505b848110156105ef576105af8361087d565b91506040518060400160405280838152602001848152508482815181106105d257fe5b60200260200101819052508183019250808060010191505061059e565b5082945050505050919050565b600080826000015111801561061657506021826000015111155b61061f57600080fd5b600061062e83602001516107f4565b9050600081846000015103905060008083866020015101905080519150602083101561066157826020036101000a820491505b81945050505050919050565b6000601582600001511461068057600080fd5b610689826105fc565b9050919050565b606060008260000151116106a357600080fd5b60006106b283602001516107f4565b905060008184600001510390506060816040519080825280601f01601f1916602001820160405280156106f45781602001600182028038833980820191505090505b5090506000816020019050610710848760200151018285610935565b81945050505050919050565b600080823b905060008163ffffffff1611915050919050565b6000808260000151141561074c576000905061077e565b60008083602001519050805160001a915060c060ff168260ff1610156107775760009250505061077e565b6001925050505b919050565b6000808260000151141561079a57600090506107ef565b600080905060006107ae84602001516107f4565b84602001510190506000846000015185602001510190505b808210156107e8576107d78261087d565b8201915082806001019350506107c6565b8293505050505b919050565b600080825160001a9050608060ff16811015610814576000915050610878565b60b860ff16811080610839575060c060ff168110158015610838575060f860ff1681105b5b15610848576001915050610878565b60c060ff168110156108685760018060b80360ff16820301915050610878565b60018060f80360ff168203019150505b919050565b6000806000835160001a9050608060ff1681101561089e576001915061092b565b60b860ff168110156108bb576001608060ff16820301915061092a565b60c060ff168110156108eb5760b78103600185019450806020036101000a85510460018201810193505050610929565b60f860ff1681101561090857600160c060ff168203019150610928565b60f78103600185019450806020036101000a855104600182018101935050505b5b5b5b8192505050919050565b600081141561094357610997565b5b602060ff1681106109735782518252602060ff1683019250602060ff1682019150602060ff1681039050610944565b6000600182602060ff16036101000a03905080198451168184511681811785525050505b505050565b604051806040016040528060008152602001600081525090565b60405180604001604052806000815260200160008152509056fea265627a7a723158208f1ea6fcf63d6911ac5dbfe340be1029614581802c6a750e7d6354b32ce6647c64736f6c63430005110032",
},
},
+ "62278656": map[string]interface{}{
+ // StateReceiver contract
+ "0000000000000000000000000000000000001001": map[string]interface{}{
+ "balance": "0x0",
+ "code": "0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c80635407ca671161008c578063abca220411610066578063abca2204146102fa578063d72a0b6714610302578063ee3a87f21461031f578063f165053614610342576100cf565b80635407ca67146102585780636757e5d914610260578063942af179146102f2576100cf565b806303112a17146100d457806319494a17146100f357806330e69fc31461017e578063318926f7146101985780633434735f146101bc57806351950cd9146101c4575b600080fd5b6100f1600480360360208110156100ea57600080fd5b503561034a565b005b61016a6004803603604081101561010957600080fd5b8135919081019060408101602082013564010000000081111561012b57600080fd5b82018360208201111561013d57600080fd5b8035906020019184600183028401116401000000008311171561015f57600080fd5b50909250905061060d565b604080519115158252519081900360200190f35b61018661093e565b60408051918252519081900360200190f35b6101a0610944565b604080516001600160a01b039092168252519081900360200190f35b6101a0610968565b6100f160048036036102808110156101db57600080fd5b61020082013590610220830135906001600160a01b036102408501351690840184610280810161026082013564010000000081111561021957600080fd5b82018360208201111561022b57600080fd5b8035906020019184600183028401116401000000008311171561024d57600080fd5b509092509050610973565b610186610c78565b61027d6004803603602081101561027657600080fd5b5035610c7e565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102b757818101518382015260200161029f565b50505050905090810190601f1680156102e45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610186610d19565b610186610d1f565b61016a6004803603602081101561031857600080fd5b5035610d25565b6100f16004803603604081101561033557600080fd5b5080359060200135610d3a565b610186610db0565b60008181526003602090815260409182902080548351601f60026000196101006001861615020190931692909204918201849004840281018401909452808452606093928301828280156103df5780601f106103b4576101008083540402835291602001916103df565b820191906000526020600020905b8154815290600101906020018083116103c257829003601f168201915b50505050509050805160001415610426576040805162461bcd60e51b815260206004820152600660248201526508599bdd5b9960d21b604482015290519081900360640190fd5b600082815260036020526040812061043d916112bb565b6000606082806020019051604081101561045657600080fd5b81516020830180516040519294929383019291908464010000000082111561047d57600080fd5b90830190602082018581111561049257600080fd5b82516401000000008111828201881017156104ac57600080fd5b82525081516020918201929091019080838360005b838110156104d95781810151838201526020016104c1565b50505050905090810190601f1680156105065780820380516001836020036101000a031916815260200191505b5060405250505091509150837f8797144948782adcede8e04bfa0bd8fd56941e0df7508bd02a629b477f7b073a60405160405180910390a2604080516313629df560e11b815260048101868152602482019283528351604483015283516001600160a01b038616936326c53bea938993879390929160640190602085019080838360005b838110156105a257818101518382015260200161058a565b50505050905090810190601f1680156105cf5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b1580156105ef57600080fd5b505af1158015610603573d6000803e3d6000fd5b5050505050505050565b6000336002600160a01b031461065f576040805162461bcd60e51b81526020600482015260126024820152714e6f742053797374656d204164646573732160701b604482015290519081900360640190fd5b60606106a86106a385858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610db592505050565b610ddb565b905060006106c9826000815181106106bc57fe5b6020026020010151610f14565b90508060005460010114610724576040805162461bcd60e51b815260206004820152601b60248201527f537461746549647320617265206e6f742073657175656e7469616c0000000000604482015290519081900360640190fd5b6000805460019081018255835161074c918591811061073f57fe5b6020026020010151610f62565b9050606061076d8460028151811061076057fe5b6020026020010151610f82565b905061077882610fff565b15610933576000624c4b409050606084836040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156107cf5781810151838201526020016107b7565b50505050905090810190601f1680156107fc5780820380516001836020036101000a031916815260200191505b5060408051601f198184030181529190526020810180516001600160e01b03166313629df560e11b1781528151919650600095508594509092509050828887f1604080518215158152905191985086917f5a22725590b0a51c923940223f7458512164b1113359a735e86e7f27f44791ee9181900360200190a28661093057838360405160200180836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156108cc5781810151838201526020016108b4565b50505050905090810190601f1680156108f95780820380516001836020036101000a031916815260200191505b5060408051601f1981840301815291815260008b815260036020908152919020825161092e9750909550910192509050611302565b505b50505b505050509392505050565b60045481565b7f000000000000000000000000eb1cd9e44ab6bfe5a55ee96c468086e51b1b873a81565b6002600160a01b0381565b6201000085106109be576040805162461bcd60e51b81526020600482015260116024820152700d2dcecc2d8d2c840d8cac2cc92dcc8caf607b1b604482015290519081900360640190fd5b60045460058054600101908190551115610a05576040805162461bcd60e51b8152602060048201526003602482015262195b9960ea1b604482015290519081900360640190fd5b60015480610a42576040805162461bcd60e51b8152602060048201526005602482015264085c9bdbdd60da1b604482015290519081900360640190fd5b60008585858560405160200180858152602001846001600160a01b0316815260200180602001828103825284848281815260200192508082843760008184015260408051601f19601f909301831690940184810390920184525250805160209091012096507f28cf91ac064e179f8a42e4b7a20ba080187781da55fd4f3f18870b7a25bacb559550505050828414801592509050610aef575060008281526002602052604090205460ff16155b610b29576040805162461bcd60e51b815260206004808301919091526024820152631d5cd95960e21b604482015290519081900360640190fd5b60008281526002602052604090819020805460ff191660011790558051610200818101909252610b74918b9060109083908390808284376000920191909152508b915085905061100b565b8314610bb0576040805162461bcd60e51b815260206004820152600660248201526510b83937b7b360d11b604482015290519081900360640190fd5b60405187907f8797144948782adcede8e04bfa0bd8fd56941e0df7508bd02a629b477f7b073a90600090a2604080516313629df560e11b81526004810189815260248201928352604482018790526001600160a01b038916926326c53bea928b928a928a92606401848480828437600081840152601f19601f820116905080830192505050945050505050600060405180830381600087803b158015610c5557600080fd5b505af1158015610c69573d6000803e3d6000fd5b50505050505050505050505050565b60005481565b60036020908152600091825260409182902080548351601f600260001961010060018616150201909316929092049182018490048402810184019094528084529091830182828015610d115780601f10610ce657610100808354040283529160200191610d11565b820191906000526020600020905b815481529060010190602001808311610cf457829003601f168201915b505050505081565b60055481565b60015481565b60026020526000908152604090205460ff1681565b336001600160a01b037f000000000000000000000000eb1cd9e44ab6bfe5a55ee96c468086e51b1b873a1614610da5576040805162461bcd60e51b815260206004820152600b60248201526a10b937b7ba29b2ba3a32b960a91b604482015290519081900360640190fd5b600191909155600455565b601081565b610dbd611380565b5060408051808201909152815181526020828101908201525b919050565b6060610de6826110b6565b610def57600080fd5b6000610dfa836110f0565b905060608167ffffffffffffffff81118015610e1557600080fd5b50604051908082528060200260200182016040528015610e4f57816020015b610e3c611380565b815260200190600190039081610e345790505b5090506000610e618560200151611148565b60208601510190506000805b84811015610eb857610e7e836111ab565b9150604051806040016040528083815260200184815250848281518110610ea157fe5b602090810291909101015291810191600101610e6d565b5085516020870151830314610f0a576040805162461bcd60e51b81526020600482015260136024820152722bb937b733903a37ba30b6103632b733ba341760691b604482015290519081900360640190fd5b5090949350505050565b805160009015801590610f2957508151602110155b610f3257600080fd5b600080610f3e84611244565b815191935091506020821015610f5a5760208290036101000a90045b949350505050565b8051600090601514610f7357600080fd5b610f7c82610f14565b92915050565b8051606090610f9057600080fd5b600080610f9c84611244565b9150915060608167ffffffffffffffff81118015610fb957600080fd5b506040519080825280601f01601f191660200182016040528015610fe4576020820181803683370190505b50905060208101610ff684828561126a565b50949350505050565b3b63ffffffff16151590565b600081815b6010811015610ff657600185821c8116141561106c5785816010811061103257fe5b60200201518260405160200180838152602001828152602001925050506040516020818303038152906040528051906020012091506110ae565b8186826010811061107957fe5b602002015160405160200180838152602001828152602001925050506040516020818303038152906040528051906020012091505b600101611010565b80516000906110c757506000610dd6565b6020820151805160001a9060c08210156110e657600092505050610dd6565b5060019392505050565b805160009061110157506000610dd6565b6000806111118460200151611148565b602085015185519181019250015b8082101561113f57611130826111ab565b6001909301929091019061111f565b50909392505050565b8051600090811a6080811015611162576000915050610dd6565b60b881108061117d575060c0811080159061117d575060f881105b1561118c576001915050610dd6565b60c08110156111a05760b519019050610dd6565b60f519019050610dd6565b80516000908190811a60808110156111c6576001915061123d565b60b88110156111db57607e198101915061123d565b60c08110156112085760b78103600185019450806020036101000a8551046001820181019350505061123d565b60f881101561121d5760be198101915061123d565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b60008060006112568460200151611148565b602085015194519481019594039392505050565b80611274576112b6565b5b60208110611294578251825260209283019290910190601f1901611275565b80156112b6578251825160208390036101000a60001901801990921691161782525b505050565b50805460018160011615610100020316600290046000825580601f106112e157506112ff565b601f0160209004906000526020600020908101906112ff919061139a565b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061134357805160ff1916838001178555611370565b82800160010185558215611370579182015b82811115611370578251825591602001919060010190611355565b5061137c92915061139a565b5090565b604051806040016040528060008152602001600081525090565b5b8082111561137c576000815560010161139b56fea164736f6c634300060c000a",
+ },
+ // MRC20 contract
+ "0000000000000000000000000000000000001010": map[string]interface{}{
+ "balance": "0x0",
+ "code": "0x6080604052600436106101b75760003560e01c80638da5cb5b116100ec578063b789543c1161008a578063e614d0d611610064578063e614d0d614610695578063ed9ef524146106aa578063f2fde38b146106dd578063fc0c546a14610710576101b7565b8063b789543c14610626578063cc79f97b1461066b578063e306f77914610680576101b7565b806395d89b41116100c657806395d89b41146105a6578063a9059cbb146105bb578063abceeba2146105e7578063acd06cb3146105fc576101b7565b80638da5cb5b146105535780638f32d59b146105685780639025e64c14610591576101b7565b806347e7ef241161015957806370a082311161013357806370a082311461043c578063715018a61461046f578063771282f61461048457806377d32e9414610499576101b7565b806347e7ef24146103b3578063485cc955146103ec57806360f96a8f14610427576101b7565b806319d27d9c1161019557806319d27d9c146102a25780632e1a7d4d14610356578063313ce5671461037357806342fc47fb1461039e576101b7565b806306fdde03146101bc5780631499c5921461024657806318160ddd1461027b575b600080fd5b3480156101c857600080fd5b506101d1610725565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561020b5781810151838201526020016101f3565b50505050905090810190601f1680156102385780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025257600080fd5b506102796004803603602081101561026957600080fd5b50356001600160a01b031661075c565b005b34801561028757600080fd5b5061029061079c565b60408051918252519081900360200190f35b3480156102ae57600080fd5b5061033a600480360360a08110156102c557600080fd5b8101906020810181356401000000008111156102e057600080fd5b8201836020820111156102f257600080fd5b8035906020019184600183028401116401000000008311171561031457600080fd5b9193509150803590602081013590604081013590606001356001600160a01b03166107ac565b604080516001600160a01b039092168252519081900360200190f35b6102796004803603602081101561036c57600080fd5b50356107ee565b34801561037f57600080fd5b506103886108c6565b6040805160ff9092168252519081900360200190f35b3480156103aa57600080fd5b5061033a6108cb565b3480156103bf57600080fd5b50610279600480360360408110156103d657600080fd5b506001600160a01b0381351690602001356108da565b3480156103f857600080fd5b506102796004803603604081101561040f57600080fd5b506001600160a01b03813581169160200135166109a8565b34801561043357600080fd5b5061033a610a21565b34801561044857600080fd5b506102906004803603602081101561045f57600080fd5b50356001600160a01b0316610a30565b34801561047b57600080fd5b50610279610a3d565b34801561049057600080fd5b50610290610a98565b3480156104a557600080fd5b5061033a600480360360408110156104bc57600080fd5b813591908101906040810160208201356401000000008111156104de57600080fd5b8201836020820111156104f057600080fd5b8035906020019184600183028401116401000000008311171561051257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610a9e945050505050565b34801561055f57600080fd5b5061033a610bc2565b34801561057457600080fd5b5061057d610bd1565b604080519115158252519081900360200190f35b34801561059d57600080fd5b506101d1610be2565b3480156105b257600080fd5b506101d1610c00565b61057d600480360360408110156105d157600080fd5b506001600160a01b038135169060200135610c1d565b3480156105f357600080fd5b50610290610c40565b34801561060857600080fd5b5061057d6004803603602081101561061f57600080fd5b5035610cc9565b34801561063257600080fd5b506102906004803603608081101561064957600080fd5b506001600160a01b038135169060208101359060408101359060600135610cde565b34801561067757600080fd5b50610290610cfd565b34801561068c57600080fd5b50610290610d03565b3480156106a157600080fd5b50610290610d09565b3480156106b657600080fd5b50610279600480360360208110156106cd57600080fd5b50356001600160a01b0316610d53565b3480156106e957600080fd5b506102796004803603602081101561070057600080fd5b50356001600160a01b0316610e05565b34801561071c57600080fd5b5061033a610e22565b60408051808201909152601781527f506f6c79676f6e2045636f73797374656d20546f6b656e000000000000000000602082015290565b6040805162461bcd60e51b815260206004820152601060248201526f44697361626c6564206665617475726560801b604482015290519081900360640190fd5b6b204fce5e3e2502611000000090565b6040805162461bcd60e51b815260206004820152601060248201526f44697361626c6564206665617475726560801b6044820152905160009181900360640190fd5b3360006107fa82610a30565b600654909150610810908463ffffffff610e3116565b600655821580159061082157508234145b610868576040805162461bcd60e51b8152602060048201526013602482015272125b9cdd59999a58da595b9d08185b5bdd5b9d606a1b604482015290519081900360640190fd5b6002546001600160a01b0380841691167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f85846108a487610a30565b60408051938452602084019290925282820152519081900360600190a3505050565b601290565b6003546001600160a01b031681565b6108e2610bd1565b6108eb57600080fd5b60008111801561090357506001600160a01b03821615155b61093e5760405162461bcd60e51b815260040180806020018281038252602381526020018061138d6023913960400191505060405180910390fd5b600061094983610a30565b60065490915061095f908363ffffffff610e4616565b60065561096c8383610e58565b6002546001600160a01b0380851691167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f684846108a488610a30565b60075460ff16156109ea5760405162461bcd60e51b815260040180806020018281038252602381526020018061136a6023913960400191505060405180910390fd5b6007805460ff19166001179055600280546001600160a01b0383166001600160a01b0319909116179055610a1d82610f17565b5050565b6004546001600160a01b031681565b6001600160a01b03163190565b610a45610bd1565b610a4e57600080fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b60065481565b6000806000808451604114610ab95760009350505050610bbc565b50505060208201516040830151604184015160ff16601b811015610adb57601b015b8060ff16601b14158015610af357508060ff16601c14155b15610b045760009350505050610bbc565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa158015610b5b573d6000803e3d6000fd5b5050604051601f1901519450506001600160a01b038416610bb8576040805162461bcd60e51b815260206004820152601260248201527122b93937b91034b71032b1b932b1b7bb32b960711b604482015290519081900360640190fd5b5050505b92915050565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b604051806040016040528060028152602001613a9960f01b81525081565b6040805180820190915260038152621413d360ea1b602082015290565b6000813414610c2e57506000610bbc565b610c39338484610f85565b9392505050565b6040518060800160405280605b8152602001611434605b91396040516020018082805190602001908083835b60208310610c8b5780518252601f199092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b60056020526000908152604090205460ff1681565b6000610cf4610cef868686866111d2565b61128b565b95945050505050565b613a9981565b60015481565b6040518060800160405280605281526020016113b06052913960405160200180828051906020019080838360208310610c8b5780518252601f199092019160209182019101610c6c565b610d5b610bd1565b610d6457600080fd5b6001600160a01b038116610da95760405162461bcd60e51b81526004018080602001828103825260328152602001806114026032913960400191505060405180910390fd5b6003546040516001600160a01b038084169216907f1f9f3556dd336016cdf20adaead7d5c73665dba664b60e8c17e9a4eb91ce1d3990600090a3600380546001600160a01b0319166001600160a01b0392909216919091179055565b610e0d610bd1565b610e1657600080fd5b610e1f81610f17565b50565b6002546001600160a01b031681565b600082821115610e4057600080fd5b50900390565b600082820183811015610c3957600080fd5b60085415610e9a576040805162461bcd60e51b815260206004820152600a6024820152697265656e7472616e637960b01b604482015290519081900360640190fd5b6001600855604051611388906000906060906001600160a01b038616908490869085818181858888f193505050503d8060008114610ef4576040519150601f19603f3d011682016040523d82523d6000602084013e610ef9565b606091505b509150915081610f0b57805160208201fd5b50506000600855505050565b6001600160a01b038116610f2a57600080fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b604080516370a0823160e01b81526001600160a01b03851660048201529051600091829130916370a08231916024808301926020929190829003018186803b158015610fd057600080fd5b505afa158015610fe4573d6000803e3d6000fd5b505050506040513d6020811015610ffa57600080fd5b5051604080516370a0823160e01b81526001600160a01b0387166004820152905191925060009130916370a08231916024808301926020929190829003018186803b15801561104857600080fd5b505afa15801561105c573d6000803e3d6000fd5b505050506040513d602081101561107257600080fd5b50519050611081868686611299565b600254604080516370a0823160e01b81526001600160a01b03898116600483018190529251818a1694909116917fe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c49189918891889130916370a0823191602480820192602092909190829003018186803b1580156110fe57600080fd5b505afa158015611112573d6000803e3d6000fd5b505050506040513d602081101561112857600080fd5b5051604080516370a0823160e01b81526001600160a01b038f166004820152905130916370a08231916024808301926020929190829003018186803b15801561117057600080fd5b505afa158015611184573d6000803e3d6000fd5b505050506040513d602081101561119a57600080fd5b50516040805195865260208601949094528484019290925260608401526080830152519081900360a00190a450600195945050505050565b6000806040518060800160405280605b8152602001611434605b91396040516020018082805190602001908083835b602083106112205780518252601f199092019160209182019101611201565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f1901835280855282519282019290922082526001600160a01b039b909b169a81019a909a5250880196909652505050606084019190915260808301525060a0902090565b6000610bbc82600154611347565b6001600160a01b0382163014156112ed576040805162461bcd60e51b8152602060048201526013602482015272063616e27742073656e6420746f204d5243323606c1b604482015290519081900360640190fd5b6112f78282610e58565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b60405161190160f01b815260028101919091526022810191909152604290209056fe54686520636f6e747261637420697320616c726561647920696e697469616c697a6564496e73756666696369656e7420616d6f756e74206f7220696e76616c69642075736572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e7472616374294368696c6420746f6b656e3a206e6577206368696c64206164647265737320697320746865207a65726f2061646472657373546f6b656e5472616e736665724f726465722861646472657373207370656e6465722c75696e7432353620746f6b656e49644f72416d6f756e742c6279746573333220646174612c75696e743235362065787069726174696f6e29a265627a7a723158205f23be7574e70cfc01d0cfd6803b871f92465e9ae4a10fe95ed31ccb810bda3e64736f6c63430005110032",
+ },
+ // WMATIC contract
+ "0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270": map[string]interface{}{
+ "balance": "0x0",
+ "code": "0x6080604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b9578063095ea7b31461014957806318160ddd146101ae57806323b872dd146101d95780632e1a7d4d1461025e578063313ce5671461028b57806370a08231146102bc57806395d89b4114610313578063a9059cbb146103a3578063d0e30db014610408578063dd62ed3e14610412575b6100b7610489565b005b3480156100c557600080fd5b506100ce610526565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561010e5780820151818401526020810190506100f3565b50505050905090810190601f16801561013b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015557600080fd5b50610194600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610563565b604051808215151515815260200191505060405180910390f35b3480156101ba57600080fd5b506101c3610655565b6040518082815260200191505060405180910390f35b3480156101e557600080fd5b50610244600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610674565b604051808215151515815260200191505060405180910390f35b34801561026a57600080fd5b50610289600480360381019080803590602001909291905050506109c1565b005b34801561029757600080fd5b506102a0610af4565b604051808260ff1660ff16815260200191505060405180910390f35b3480156102c857600080fd5b506102fd600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610afd565b6040518082815260200191505060405180910390f35b34801561031f57600080fd5b50610328610b15565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036857808201518184015260208101905061034d565b50505050905090810190601f1680156103955780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103af57600080fd5b506103ee600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610b52565b604051808215151515815260200191505060405180910390f35b610410610489565b005b34801561041e57600080fd5b50610473600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b67565b6040518082815260200191505060405180910390f35b34600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055503373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a2565b60606040805190810160405280601f81526020017f5772617070656420506f6c79676f6e2045636f73797374656d20546f6b656e00815250905090565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60003073ffffffffffffffffffffffffffffffffffffffff1631905090565b600081600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156106c457600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415801561079c57507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414155b156108b75781600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561082c57600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b81600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a0f57600080fd5b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610aa2573d6000803e3d6000fd5b503373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65826040518082815260200191505060405180910390a250565b60006012905090565b60036020528060005260406000206000915090505481565b60606040805190810160405280600481526020017f57504f4c00000000000000000000000000000000000000000000000000000000815250905090565b6000610b5f338484610674565b905092915050565b60046020528160005260406000206020528060005260406000206000915091505054815600a165627a7a723058208d70d8aa2d752533105b5ccda8206dae8b0c1de765f89fb1f0c5727cbac1b40d0029",
+ },
+ },
},
},
},
diff --git a/internal/cli/server/chains/utils.go b/internal/cli/server/chains/utils.go
index 860ff5b6ee..33d7a9c0ed 100644
--- a/internal/cli/server/chains/utils.go
+++ b/internal/cli/server/chains/utils.go
@@ -5,13 +5,13 @@ import (
"encoding/json"
"fmt"
- "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
)
//go:embed allocs
var allocs embed.FS
-func readPrealloc(filename string) core.GenesisAlloc {
+func readPrealloc(filename string) types.GenesisAlloc {
f, err := allocs.Open(filename)
if err != nil {
panic(fmt.Sprintf("Could not open genesis preallocation for %s: %v", filename, err))
@@ -19,7 +19,7 @@ func readPrealloc(filename string) core.GenesisAlloc {
defer f.Close()
decoder := json.NewDecoder(f)
- ga := make(core.GenesisAlloc)
+ ga := make(types.GenesisAlloc)
err = decoder.Decode(&ga)
if err != nil {
diff --git a/internal/cli/server/command_test.go b/internal/cli/server/command_test.go
index de6a2d5efa..3181dd6402 100644
--- a/internal/cli/server/command_test.go
+++ b/internal/cli/server/command_test.go
@@ -86,7 +86,7 @@ func TestFlagsWithConfig(t *testing.T) {
"32000000": "0x875500011e5eecc0c554f95d07b31cf59df4ca2505f4dbbfffa7d4e4da917c68",
},
)
- require.Equal(t, c.config.Sealer.GasPrice, big.NewInt(30000000000))
+ require.Equal(t, c.config.Sealer.GasPrice, big.NewInt(25000000000))
require.Equal(t, c.config.Sealer.Recommit, recommit)
require.Equal(t, c.config.JsonRPC.RPCEVMTimeout, evmTimeout)
require.Equal(t, c.config.JsonRPC.Http.API, []string{"eth", "bor"})
diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go
index a496f23586..5960fdeab0 100644
--- a/internal/cli/server/config.go
+++ b/internal/cli/server/config.go
@@ -678,7 +678,7 @@ func DefaultConfig() *Config {
MaxHeaderHistory: 1024,
MaxBlockHistory: 1024,
MaxPrice: gasprice.DefaultMaxPrice,
- IgnorePrice: gasprice.DefaultIgnorePrice,
+ IgnorePrice: gasprice.DefaultIgnorePrice, // bor's default
},
JsonRPC: &JsonRPCConfig{
IPCDisable: false,
diff --git a/internal/cli/server/config_legacy_test.go b/internal/cli/server/config_legacy_test.go
index e9957c3353..2d2d7ec397 100644
--- a/internal/cli/server/config_legacy_test.go
+++ b/internal/cli/server/config_legacy_test.go
@@ -26,7 +26,7 @@ func TestConfigLegacy(t *testing.T) {
"31000000": "0x2087b9e2b353209c2c21e370c82daa12278efd0fe5f0febe6c29035352cf050e",
"32000000": "0x875500011e5eecc0c554f95d07b31cf59df4ca2505f4dbbfffa7d4e4da917c68",
}
- testConfig.Sealer.GasPrice = big.NewInt(30000000000)
+ testConfig.Sealer.GasPrice = big.NewInt(25000000000)
testConfig.Sealer.Recommit = 20 * time.Second
testConfig.JsonRPC.RPCEVMTimeout = 5 * time.Second
testConfig.JsonRPC.TxFeeCap = 6.0
diff --git a/internal/cli/server/flags.go b/internal/cli/server/flags.go
index eb84f4fd77..0cf8919b9d 100644
--- a/internal/cli/server/flags.go
+++ b/internal/cli/server/flags.go
@@ -806,6 +806,13 @@ func (c *Command) Flags(config *Config) *flagset.Flagset {
Default: c.cliConfig.P2P.TxArrivalWait,
Group: "P2P",
})
+ f.SliceStringFlag(&flagset.SliceStringFlag{
+ Name: "discovery.dns",
+ Usage: "Comma separated list of enrtree:// URLs which will be queried for nodes to connect to",
+ Value: &c.cliConfig.P2P.Discovery.DNS,
+ Default: c.cliConfig.P2P.Discovery.DNS,
+ Group: "P2P",
+ })
// metrics
f.BoolFlag(&flagset.BoolFlag{
diff --git a/internal/cli/server/server.go b/internal/cli/server/server.go
index 713b99f1db..57a931baa7 100644
--- a/internal/cli/server/server.go
+++ b/internal/cli/server/server.go
@@ -29,16 +29,7 @@ import (
"github.com/ethereum/go-ethereum/metrics/influxdb"
"github.com/ethereum/go-ethereum/metrics/prometheus"
"github.com/ethereum/go-ethereum/node"
- "github.com/mattn/go-colorable"
- "github.com/mattn/go-isatty"
- "go.opentelemetry.io/otel"
- "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
- "go.opentelemetry.io/otel/propagation"
- "go.opentelemetry.io/otel/sdk/resource"
- sdktrace "go.opentelemetry.io/otel/sdk/trace"
- semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
- "google.golang.org/grpc"
- "google.golang.org/grpc/reflection"
+ "github.com/ethereum/go-ethereum/rpc"
// Force-load the tracer engines to trigger registration
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
@@ -314,19 +305,17 @@ func (s *Server) Stop() {
func (s *Server) setupMetrics(config *TelemetryConfig, serviceName string) error {
// Check the global metrics if they're matching with the provided config
- if metrics.Enabled != config.Enabled || metrics.EnabledExpensive != config.Expensive {
+ if metrics.Enabled != config.Enabled {
log.Warn(
"Metric misconfiguration, some of them might not be visible",
"metrics", metrics.Enabled,
"config.metrics", config.Enabled,
- "expensive", metrics.EnabledExpensive,
"config.expensive", config.Expensive,
)
}
// Update the values anyways (for services which don't need immediate attention)
metrics.Enabled = config.Enabled
- metrics.EnabledExpensive = config.Expensive
if !metrics.Enabled {
// metrics are disabled, do not set up any sink
@@ -335,10 +324,6 @@ func (s *Server) setupMetrics(config *TelemetryConfig, serviceName string) error
log.Info("Enabling metrics collection")
- if metrics.EnabledExpensive {
- log.Info("Enabling expensive metrics collection")
- }
-
// influxdb
if v1Enabled, v2Enabled := config.InfluxDB.V1Enabled, config.InfluxDB.V2Enabled; v1Enabled || v2Enabled {
if v1Enabled && v2Enabled {
@@ -370,9 +355,15 @@ func (s *Server) setupMetrics(config *TelemetryConfig, serviceName string) error
prometheusMux.Handle("/debug/metrics/prometheus", prometheus.Handler(metrics.DefaultRegistry))
+ timeouts := rpc.DefaultHTTPTimeouts
+
promServer := &http.Server{
- Addr: config.PrometheusAddr,
- Handler: prometheusMux,
+ Addr: config.PrometheusAddr,
+ Handler: prometheusMux,
+ ReadTimeout: timeouts.ReadTimeout,
+ ReadHeaderTimeout: timeouts.ReadHeaderTimeout,
+ WriteTimeout: timeouts.WriteTimeout,
+ IdleTimeout: timeouts.IdleTimeout,
}
go func() {
diff --git a/internal/cli/server/server_test.go b/internal/cli/server/server_test.go
index 6c52ae8a14..b3b8e89bae 100644
--- a/internal/cli/server/server_test.go
+++ b/internal/cli/server/server_test.go
@@ -34,7 +34,7 @@ func TestServer_DeveloperMode(t *testing.T) {
currBlock := server.backend.BlockChain().CurrentBlock().Number.Int64()
expected := blockNumber + i + 1
- if res := assert.Equal(t, currBlock, expected); res == false {
+ if res := assert.Equal(t, expected, currBlock); res == false {
break
}
}
diff --git a/internal/cli/server/testdata/default.toml b/internal/cli/server/testdata/default.toml
index 72f166a8c2..0df37d610c 100644
--- a/internal/cli/server/testdata/default.toml
+++ b/internal/cli/server/testdata/default.toml
@@ -58,7 +58,7 @@ devfakeauthor = false
nolocals = false
journal = "transactions.rlp"
rejournal = "1h0m0s"
- pricelimit = 30000000000
+ pricelimit = 25000000000
pricebump = 10
accountslots = 16
globalslots = 32768
@@ -71,7 +71,7 @@ devfakeauthor = false
etherbase = ""
extradata = ""
gaslimit = 30000000
- gasprice = "30000000000"
+ gasprice = "25000000000"
recommit = "2m5s"
commitinterrupt = true
@@ -127,7 +127,7 @@ devfakeauthor = false
maxheaderhistory = 1024
maxblockhistory = 1024
maxprice = "500000000000"
- ignoreprice = "30000000000"
+ ignoreprice = "25000000000"
[telemetry]
metrics = false
diff --git a/internal/cli/server/testdata/test.toml b/internal/cli/server/testdata/test.toml
index 04b2dbed35..e1ff535956 100644
--- a/internal/cli/server/testdata/test.toml
+++ b/internal/cli/server/testdata/test.toml
@@ -11,7 +11,7 @@ snapshot = true
"32000000" = "0x875500011e5eecc0c554f95d07b31cf59df4ca2505f4dbbfffa7d4e4da917c68"
[miner]
- gasprice = "30000000000"
+ gasprice = "25000000000"
recommit = "20s"
[jsonrpc]
diff --git a/internal/cli/snapshot.go b/internal/cli/snapshot.go
index a575210bb5..b610f6b71f 100644
--- a/internal/cli/snapshot.go
+++ b/internal/cli/snapshot.go
@@ -17,7 +17,7 @@ import (
"github.com/ethereum/go-ethereum/internal/cli/server"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
"github.com/prometheus/tsdb/fileutil"
@@ -32,7 +32,7 @@ type SnapshotCommand struct {
}
// MarkDown implements cli.MarkDown interface
-func (a *SnapshotCommand) MarkDown() string {
+func (c *SnapshotCommand) MarkDown() string {
items := []string{
"# snapshot",
"The ```snapshot``` command groups snapshot related actions:",
@@ -373,7 +373,7 @@ func (c *PruneBlockCommand) validateAgainstSnapshot(stack *node.Node, dbHandles
}
// Make sure the MPT and snapshot matches before pruning, otherwise the node can not start.
- snaptree, err := snapshot.New(snapconfig, chaindb, trie.NewDatabase(chaindb, trie.HashDefaults), headBlock.Root())
+ snaptree, err := snapshot.New(snapconfig, chaindb, triedb.NewDatabase(chaindb, triedb.HashDefaults), headBlock.Root())
if err != nil {
log.Error("Unable to load snapshot", "err", err)
return err // The relevant snapshot(s) might not exist
@@ -445,6 +445,28 @@ func (c *PruneBlockCommand) validateAgainstSnapshot(stack *node.Node, dbHandles
return nil
}
+// checkDeletePermissions checks if the user has the permission to
+// delete the given `path`.
+func checkDeletePermissions(path string) (bool, error) {
+ dirInfo, err := os.Stat(path)
+ if err != nil {
+ return false, err
+ }
+ // Check if the user has write and execute permissions on the directory
+ if dirInfo.Mode().Perm()&(0200|0100) == (0200 | 0100) {
+ // Also check if the parent directory has write permissions because delete needs them
+ parentDir := filepath.Dir(path)
+ parentDirInfo, err := os.Stat(parentDir)
+ if err != nil {
+ return false, err
+ }
+ if parentDirInfo.Mode().Perm()&0200 != 0 {
+ return true, nil
+ }
+ }
+ return false, nil
+}
+
// pruneBlock is the entry point for the ancient pruning process. Based on the user specified
// params, it will prune the ancient data. It also handles the case where the pruning process
// was interrupted earlier.
@@ -466,6 +488,17 @@ func (c *PruneBlockCommand) pruneBlock(stack *node.Node, fdHandles int) error {
}
newAncientPath := filepath.Join(path, "ancient_back")
+
+ // Check if we have delete permissions on the ancient datadir path beforehand
+ allow, err := checkDeletePermissions(oldAncientPath)
+ if err != nil {
+ log.Error("Failed to check delete permissions for ancient datadir", "path", oldAncientPath, "err", err)
+ return err
+ }
+ if !allow {
+ return fmt.Errorf("user doesn't have delete permissions on ancient datadir: %s", oldAncientPath)
+ }
+
blockpruner := pruner.NewBlockPruner(stack, oldAncientPath, newAncientPath, c.blockAmountReserved)
lock, exist, err := fileutil.Flock(filepath.Join(oldAncientPath, "PRUNEFLOCK"))
diff --git a/internal/cli/snapshot_test.go b/internal/cli/snapshot_test.go
index d17893ddda..51c1e30503 100644
--- a/internal/cli/snapshot_test.go
+++ b/internal/cli/snapshot_test.go
@@ -22,7 +22,7 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
"github.com/stretchr/testify/require"
)
@@ -33,7 +33,7 @@ var (
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey)
balance = big.NewInt(1_000000000000000000)
- gspec = &core.Genesis{Config: params.TestChainConfig, Alloc: core.GenesisAlloc{address: {Balance: balance}}}
+ gspec = &core.Genesis{Config: params.TestChainConfig, Alloc: types.GenesisAlloc{address: {Balance: balance}}}
signer = types.LatestSigner(gspec.Config)
config = &core.CacheConfig{
TrieCleanLimit: 256,
@@ -46,6 +46,7 @@ var (
)
func TestOfflineBlockPrune(t *testing.T) {
+ t.Skip("PBSS does not support ancient block pruning")
t.Parallel()
// Corner case for 0 remain in ancinetStore.
@@ -158,7 +159,7 @@ func BlockchainCreator(t *testing.T, chaindbPath, AncientPath string, blockRemai
defer db.Close()
- genesis := gspec.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults))
+ genesis := gspec.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
// Initialize a fresh chain with only a genesis block
blockchain, err := core.NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil, nil)
require.NoError(t, err, "failed to create chain")
@@ -179,11 +180,11 @@ func BlockchainCreator(t *testing.T, chaindbPath, AncientPath string, blockRemai
// Force run a freeze cycle
type freezer interface {
- Freeze(threshold uint64) error
+ Freeze() error
Ancients() (uint64, error)
}
- err = db.(freezer).Freeze(10)
+ err = db.(freezer).Freeze()
require.NoError(t, err, "failed to perform freeze operation")
// make sure there're frozen items
diff --git a/internal/cli/status.go b/internal/cli/status.go
index 63386d9680..1939a84fdb 100644
--- a/internal/cli/status.go
+++ b/internal/cli/status.go
@@ -30,7 +30,7 @@ func (c *StatusCommand) Flags() *flagset.Flagset {
}
// MarkDown implements cli.MarkDown interface
-func (p *StatusCommand) MarkDown() string {
+func (c *StatusCommand) MarkDown() string {
items := []string{
"# Status",
"The ```status``` command outputs the status of the client.",
@@ -40,7 +40,7 @@ func (p *StatusCommand) MarkDown() string {
}
// Help implements the cli.Command interface
-func (p *StatusCommand) Help() string {
+func (c *StatusCommand) Help() string {
return `Usage: bor status
Output the status of the client`
diff --git a/internal/cli/version.go b/internal/cli/version.go
index 949599904e..b603da141e 100644
--- a/internal/cli/version.go
+++ b/internal/cli/version.go
@@ -14,7 +14,7 @@ type VersionCommand struct {
}
// MarkDown implements cli.MarkDown interface
-func (d *VersionCommand) MarkDown() string {
+func (c *VersionCommand) MarkDown() string {
examples := []string{
"## Usage",
CodeBlock([]string{
diff --git a/internal/debug/api.go b/internal/debug/api.go
index 0b7e034359..b4141c3487 100644
--- a/internal/debug/api.go
+++ b/internal/debug/api.go
@@ -36,8 +36,7 @@ import (
"time"
"github.com/ethereum/go-ethereum/log"
- "github.com/hashicorp/go-bexpr"
- "golang.org/x/exp/slog"
+ bexpr "github.com/hashicorp/go-bexpr"
)
// Handler is the global debugging handler.
@@ -57,7 +56,7 @@ type HandlerT struct {
// Verbosity sets the log verbosity ceiling. The verbosity of individual packages
// and source files can be raised using Vmodule.
func (*HandlerT) Verbosity(level int) {
- glogger.Verbosity(slog.Level(level))
+ glogger.Verbosity(log.FromLegacyLevel(level))
}
// Vmodule sets the log verbosity pattern. See package log for details on the
diff --git a/internal/debug/flags.go b/internal/debug/flags.go
index 23e4745e8c..0e05975c7e 100644
--- a/internal/debug/flags.go
+++ b/internal/debug/flags.go
@@ -19,6 +19,7 @@ package debug
import (
"fmt"
"io"
+ "log/slog"
"net"
"net/http"
_ "net/http/pprof"
@@ -30,16 +31,12 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/metrics/exp"
- "github.com/fjl/memsize/memsizeui"
"github.com/mattn/go-colorable"
"github.com/mattn/go-isatty"
"github.com/urfave/cli/v2"
- "golang.org/x/exp/slog"
"gopkg.in/natefinch/lumberjack.v2"
)
-var Memsize memsizeui.Handler
-
var (
verbosityFlag = &cli.IntFlag{
Name: "verbosity",
@@ -168,22 +165,12 @@ var Flags = []cli.Flag{
}
var (
- glogger *log.GlogHandler
- logOutputFile io.WriteCloser
- defaultTerminalHandler *log.TerminalHandler
+ glogger *log.GlogHandler
+ logOutputFile io.WriteCloser
)
func init() {
- defaultTerminalHandler = log.NewTerminalHandler(os.Stderr, false)
- glogger = log.NewGlogHandler(defaultTerminalHandler)
- glogger.Verbosity(log.LvlInfo)
- log.SetDefault(log.NewLogger(glogger))
-}
-
-func ResetLogging() {
- if defaultTerminalHandler != nil {
- defaultTerminalHandler.ResetFieldPadding()
- }
+ glogger = log.NewGlogHandler(log.NewTerminalHandler(os.Stderr, false))
}
// Setup initializes profiling and logging based on the CLI flags.
@@ -323,7 +310,6 @@ func StartPProf(address string, withMetrics bool) {
if withMetrics {
exp.Exp(metrics.DefaultRegistry)
}
- http.Handle("/memsize/", http.StripPrefix("/memsize", &Memsize))
log.Info("Starting pprof server", "addr", fmt.Sprintf("http://%s/debug/pprof", address))
go func() {
if err := http.ListenAndServe(address, nil); err != nil {
diff --git a/internal/era/accumulator.go b/internal/era/accumulator.go
new file mode 100644
index 0000000000..2ece2755e1
--- /dev/null
+++ b/internal/era/accumulator.go
@@ -0,0 +1,91 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package era
+
+import (
+ "errors"
+ "fmt"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ ssz "github.com/ferranbt/fastssz"
+)
+
+// ComputeAccumulator calculates the SSZ hash tree root of the Era1
+// accumulator of header records.
+func ComputeAccumulator(hashes []common.Hash, tds []*big.Int) (common.Hash, error) {
+ if len(hashes) != len(tds) {
+ return common.Hash{}, errors.New("must have equal number hashes as td values")
+ }
+ if len(hashes) > MaxEra1Size {
+ return common.Hash{}, fmt.Errorf("too many records: have %d, max %d", len(hashes), MaxEra1Size)
+ }
+ hh := ssz.NewHasher()
+ for i := range hashes {
+ rec := headerRecord{hashes[i], tds[i]}
+ root, err := rec.HashTreeRoot()
+ if err != nil {
+ return common.Hash{}, err
+ }
+ hh.Append(root[:])
+ }
+ hh.MerkleizeWithMixin(0, uint64(len(hashes)), uint64(MaxEra1Size))
+ return hh.HashRoot()
+}
+
+// headerRecord is an individual record for a historical header.
+//
+// See https://github.com/ethereum/portal-network-specs/blob/master/history-network.md#the-header-accumulator
+// for more information.
+type headerRecord struct {
+ Hash common.Hash
+ TotalDifficulty *big.Int
+}
+
+// GetTree completes the ssz.HashRoot interface, but is unused.
+func (h *headerRecord) GetTree() (*ssz.Node, error) {
+ return nil, nil
+}
+
+// HashTreeRoot ssz hashes the headerRecord object.
+func (h *headerRecord) HashTreeRoot() ([32]byte, error) {
+ return ssz.HashWithDefaultHasher(h)
+}
+
+// HashTreeRootWith ssz hashes the headerRecord object with a hasher.
+func (h *headerRecord) HashTreeRootWith(hh ssz.HashWalker) (err error) {
+ hh.PutBytes(h.Hash[:])
+ td := bigToBytes32(h.TotalDifficulty)
+ hh.PutBytes(td[:])
+ hh.Merkleize(0)
+ return
+}
+
+// bigToBytes32 converts a big.Int into a little-endian 32-byte array.
+func bigToBytes32(n *big.Int) (b [32]byte) {
+ n.FillBytes(b[:])
+ reverseOrder(b[:])
+ return
+}
+
+// reverseOrder reverses the byte order of a slice.
+func reverseOrder(b []byte) []byte {
+ for i := 0; i < 16; i++ {
+ b[i], b[32-i-1] = b[32-i-1], b[i]
+ }
+ return b
+}
diff --git a/internal/era/builder.go b/internal/era/builder.go
new file mode 100644
index 0000000000..75782a08c2
--- /dev/null
+++ b/internal/era/builder.go
@@ -0,0 +1,225 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+package era
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/internal/era/e2store"
+ "github.com/ethereum/go-ethereum/rlp"
+ "github.com/golang/snappy"
+)
+
+// Builder is used to create Era1 archives of block data.
+//
+// Era1 files are themselves e2store files. For more information on this format,
+// see https://github.com/status-im/nimbus-eth2/blob/stable/docs/e2store.md.
+//
+// The overall structure of an Era1 file follows closely the structure of an Era file
+// which contains consensus Layer data (and as a byproduct, EL data after the merge).
+//
+// The structure can be summarized through this definition:
+//
+// era1 := Version | block-tuple* | other-entries* | Accumulator | BlockIndex
+// block-tuple := CompressedHeader | CompressedBody | CompressedReceipts | TotalDifficulty
+//
+// Each basic element is its own entry:
+//
+// Version = { type: [0x65, 0x32], data: nil }
+// CompressedHeader = { type: [0x03, 0x00], data: snappyFramed(rlp(header)) }
+// CompressedBody = { type: [0x04, 0x00], data: snappyFramed(rlp(body)) }
+// CompressedReceipts = { type: [0x05, 0x00], data: snappyFramed(rlp(receipts)) }
+// TotalDifficulty = { type: [0x06, 0x00], data: uint256(header.total_difficulty) }
+// AccumulatorRoot = { type: [0x07, 0x00], data: accumulator-root }
+// BlockIndex = { type: [0x32, 0x66], data: block-index }
+//
+// Accumulator is computed by constructing an SSZ list of header-records of length at most
+// 8192 and then calculating the hash_tree_root of that list.
+//
+// header-record := { block-hash: Bytes32, total-difficulty: Uint256 }
+// accumulator := hash_tree_root([]header-record, 8192)
+//
+// BlockIndex stores relative offsets to each compressed block entry. The
+// format is:
+//
+// block-index := starting-number | index | index | index ... | count
+//
+// starting-number is the first block number in the archive. Every index is a
+// defined relative to beginning of the record. The total number of block
+// entries in the file is recorded with count.
+//
+// Due to the accumulator size limit of 8192, the maximum number of blocks in
+// an Era1 batch is also 8192.
+type Builder struct {
+ w *e2store.Writer
+ startNum *uint64
+ startTd *big.Int
+ indexes []uint64
+ hashes []common.Hash
+ tds []*big.Int
+ written int
+
+ buf *bytes.Buffer
+ snappy *snappy.Writer
+}
+
+// NewBuilder returns a new Builder instance.
+func NewBuilder(w io.Writer) *Builder {
+ buf := bytes.NewBuffer(nil)
+ return &Builder{
+ w: e2store.NewWriter(w),
+ buf: buf,
+ snappy: snappy.NewBufferedWriter(buf),
+ }
+}
+
+// Add writes a compressed block entry and compressed receipts entry to the
+// underlying e2store file.
+func (b *Builder) Add(block *types.Block, receipts types.Receipts, td *big.Int) error {
+ eh, err := rlp.EncodeToBytes(block.Header())
+ if err != nil {
+ return err
+ }
+ eb, err := rlp.EncodeToBytes(block.Body())
+ if err != nil {
+ return err
+ }
+ er, err := rlp.EncodeToBytes(receipts)
+ if err != nil {
+ return err
+ }
+ return b.AddRLP(eh, eb, er, block.NumberU64(), block.Hash(), td, block.Difficulty())
+}
+
+// AddRLP writes a compressed block entry and compressed receipts entry to the
+// underlying e2store file.
+func (b *Builder) AddRLP(header, body, receipts []byte, number uint64, hash common.Hash, td, difficulty *big.Int) error {
+ // Write Era1 version entry before first block.
+ if b.startNum == nil {
+ n, err := b.w.Write(TypeVersion, nil)
+ if err != nil {
+ return err
+ }
+ startNum := number
+ b.startNum = &startNum
+ b.startTd = new(big.Int).Sub(td, difficulty)
+ b.written += n
+ }
+ if len(b.indexes) >= MaxEra1Size {
+ return fmt.Errorf("exceeds maximum batch size of %d", MaxEra1Size)
+ }
+
+ b.indexes = append(b.indexes, uint64(b.written))
+ b.hashes = append(b.hashes, hash)
+ b.tds = append(b.tds, td)
+
+ // Write block data.
+ if err := b.snappyWrite(TypeCompressedHeader, header); err != nil {
+ return err
+ }
+ if err := b.snappyWrite(TypeCompressedBody, body); err != nil {
+ return err
+ }
+ if err := b.snappyWrite(TypeCompressedReceipts, receipts); err != nil {
+ return err
+ }
+
+ // Also write total difficulty, but don't snappy encode.
+ btd := bigToBytes32(td)
+ n, err := b.w.Write(TypeTotalDifficulty, btd[:])
+ b.written += n
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// Finalize computes the accumulator and block index values, then writes the
+// corresponding e2store entries.
+func (b *Builder) Finalize() (common.Hash, error) {
+ if b.startNum == nil {
+ return common.Hash{}, errors.New("finalize called on empty builder")
+ }
+ // Compute accumulator root and write entry.
+ root, err := ComputeAccumulator(b.hashes, b.tds)
+ if err != nil {
+ return common.Hash{}, fmt.Errorf("error calculating accumulator root: %w", err)
+ }
+ n, err := b.w.Write(TypeAccumulator, root[:])
+ b.written += n
+ if err != nil {
+ return common.Hash{}, fmt.Errorf("error writing accumulator: %w", err)
+ }
+ // Get beginning of index entry to calculate block relative offset.
+ base := int64(b.written)
+
+ // Construct block index. Detailed format described in Builder
+ // documentation, but it is essentially encoded as:
+ // "start | index | index | ... | count"
+ var (
+ count = len(b.indexes)
+ index = make([]byte, 16+count*8)
+ )
+ binary.LittleEndian.PutUint64(index, *b.startNum)
+ // Each offset is relative from the position it is encoded in the
+ // index. This means that even if the same block was to be included in
+ // the index twice (this would be invalid anyways), the relative offset
+ // would be different. The idea with this is that after reading a
+ // relative offset, the corresponding block can be quickly read by
+ // performing a seek relative to the current position.
+ for i, offset := range b.indexes {
+ relative := int64(offset) - base
+ binary.LittleEndian.PutUint64(index[8+i*8:], uint64(relative))
+ }
+ binary.LittleEndian.PutUint64(index[8+count*8:], uint64(count))
+
+ // Finally, write the block index entry.
+ if _, err := b.w.Write(TypeBlockIndex, index); err != nil {
+ return common.Hash{}, fmt.Errorf("unable to write block index: %w", err)
+ }
+
+ return root, nil
+}
+
+// snappyWrite is a small helper to take care snappy encoding and writing an e2store entry.
+func (b *Builder) snappyWrite(typ uint16, in []byte) error {
+ var (
+ buf = b.buf
+ s = b.snappy
+ )
+ buf.Reset()
+ s.Reset(buf)
+ if _, err := b.snappy.Write(in); err != nil {
+ return fmt.Errorf("error snappy encoding: %w", err)
+ }
+ if err := s.Flush(); err != nil {
+ return fmt.Errorf("error flushing snappy encoding: %w", err)
+ }
+ n, err := b.w.Write(typ, b.buf.Bytes())
+ b.written += n
+ if err != nil {
+ return fmt.Errorf("error writing e2store entry: %w", err)
+ }
+ return nil
+}
diff --git a/internal/era/e2store/e2store.go b/internal/era/e2store/e2store.go
new file mode 100644
index 0000000000..8e4d5dd24a
--- /dev/null
+++ b/internal/era/e2store/e2store.go
@@ -0,0 +1,221 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package e2store
+
+import (
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+)
+
+const (
+ headerSize = 8
+ valueSizeLimit = 1024 * 1024 * 50
+)
+
+// Entry is a variable-length-data record in an e2store.
+type Entry struct {
+ Type uint16
+ Value []byte
+}
+
+// Writer writes entries using e2store encoding.
+// For more information on this format, see:
+// https://github.com/status-im/nimbus-eth2/blob/stable/docs/e2store.md
+type Writer struct {
+ w io.Writer
+}
+
+// NewWriter returns a new Writer that writes to w.
+func NewWriter(w io.Writer) *Writer {
+ return &Writer{w}
+}
+
+// Write writes a single e2store entry to w.
+// An entry is encoded in a type-length-value format. The first 8 bytes of the
+// record store the type (2 bytes), the length (4 bytes), and some reserved
+// data (2 bytes). The remaining bytes store b.
+func (w *Writer) Write(typ uint16, b []byte) (int, error) {
+ buf := make([]byte, headerSize)
+ binary.LittleEndian.PutUint16(buf, typ)
+ binary.LittleEndian.PutUint32(buf[2:], uint32(len(b)))
+
+ // Write header.
+ if n, err := w.w.Write(buf); err != nil {
+ return n, err
+ }
+ // Write value, return combined write size.
+ n, err := w.w.Write(b)
+ return n + headerSize, err
+}
+
+// A Reader reads entries from an e2store-encoded file.
+// For more information on this format, see
+// https://github.com/status-im/nimbus-eth2/blob/stable/docs/e2store.md
+type Reader struct {
+ r io.ReaderAt
+ offset int64
+}
+
+// NewReader returns a new Reader that reads from r.
+func NewReader(r io.ReaderAt) *Reader {
+ return &Reader{r, 0}
+}
+
+// Read reads one Entry from r.
+func (r *Reader) Read() (*Entry, error) {
+ var e Entry
+ n, err := r.ReadAt(&e, r.offset)
+ if err != nil {
+ return nil, err
+ }
+ r.offset += int64(n)
+ return &e, nil
+}
+
+// ReadAt reads one Entry from r at the specified offset.
+func (r *Reader) ReadAt(entry *Entry, off int64) (int, error) {
+ typ, length, err := r.ReadMetadataAt(off)
+ if err != nil {
+ return 0, err
+ }
+ entry.Type = typ
+
+ // Check length bounds.
+ if length > valueSizeLimit {
+ return headerSize, fmt.Errorf("item larger than item size limit %d: have %d", valueSizeLimit, length)
+ }
+ if length == 0 {
+ return headerSize, nil
+ }
+
+ // Read value.
+ val := make([]byte, length)
+ if n, err := r.r.ReadAt(val, off+headerSize); err != nil {
+ n += headerSize
+ // An entry with a non-zero length should not return EOF when
+ // reading the value.
+ if err == io.EOF {
+ return n, io.ErrUnexpectedEOF
+ }
+ return n, err
+ }
+ entry.Value = val
+ return int(headerSize + length), nil
+}
+
+// ReaderAt returns an io.Reader delivering value data for the entry at
+// the specified offset. If the entry type does not match the expected type, an
+// error is returned.
+func (r *Reader) ReaderAt(expectedType uint16, off int64) (io.Reader, int, error) {
+ // problem = need to return length+headerSize not just value length via section reader
+ typ, length, err := r.ReadMetadataAt(off)
+ if err != nil {
+ return nil, headerSize, err
+ }
+ if typ != expectedType {
+ return nil, headerSize, fmt.Errorf("wrong type, want %d have %d", expectedType, typ)
+ }
+ if length > valueSizeLimit {
+ return nil, headerSize, fmt.Errorf("item larger than item size limit %d: have %d", valueSizeLimit, length)
+ }
+ return io.NewSectionReader(r.r, off+headerSize, int64(length)), headerSize + int(length), nil
+}
+
+// LengthAt reads the header at off and returns the total length of the entry,
+// including header.
+func (r *Reader) LengthAt(off int64) (int64, error) {
+ _, length, err := r.ReadMetadataAt(off)
+ if err != nil {
+ return 0, err
+ }
+ return int64(length) + headerSize, nil
+}
+
+// ReadMetadataAt reads the header metadata at the given offset.
+func (r *Reader) ReadMetadataAt(off int64) (typ uint16, length uint32, err error) {
+ b := make([]byte, headerSize)
+ if n, err := r.r.ReadAt(b, off); err != nil {
+ if err == io.EOF && n > 0 {
+ return 0, 0, io.ErrUnexpectedEOF
+ }
+ return 0, 0, err
+ }
+ typ = binary.LittleEndian.Uint16(b)
+ length = binary.LittleEndian.Uint32(b[2:])
+
+ // Check reserved bytes of header.
+ if b[6] != 0 || b[7] != 0 {
+ return 0, 0, errors.New("reserved bytes are non-zero")
+ }
+
+ return typ, length, nil
+}
+
+// Find returns the first entry with the matching type.
+func (r *Reader) Find(want uint16) (*Entry, error) {
+ var (
+ off int64
+ typ uint16
+ length uint32
+ err error
+ )
+ for {
+ typ, length, err = r.ReadMetadataAt(off)
+ if err == io.EOF {
+ return nil, io.EOF
+ } else if err != nil {
+ return nil, err
+ }
+ if typ == want {
+ var e Entry
+ if _, err := r.ReadAt(&e, off); err != nil {
+ return nil, err
+ }
+ return &e, nil
+ }
+ off += int64(headerSize + length)
+ }
+}
+
+// FindAll returns all entries with the matching type.
+func (r *Reader) FindAll(want uint16) ([]*Entry, error) {
+ var (
+ off int64
+ typ uint16
+ length uint32
+ entries []*Entry
+ err error
+ )
+ for {
+ typ, length, err = r.ReadMetadataAt(off)
+ if err == io.EOF {
+ return entries, nil
+ } else if err != nil {
+ return entries, err
+ }
+ if typ == want {
+ e := new(Entry)
+ if _, err := r.ReadAt(e, off); err != nil {
+ return entries, err
+ }
+ entries = append(entries, e)
+ }
+ off += int64(headerSize + length)
+ }
+}
diff --git a/internal/era/e2store/e2store_test.go b/internal/era/e2store/e2store_test.go
new file mode 100644
index 0000000000..b0803493c7
--- /dev/null
+++ b/internal/era/e2store/e2store_test.go
@@ -0,0 +1,150 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package e2store
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+func TestEncode(t *testing.T) {
+ for _, test := range []struct {
+ entries []Entry
+ want string
+ name string
+ }{
+ {
+ name: "emptyEntry",
+ entries: []Entry{{0xffff, nil}},
+ want: "ffff000000000000",
+ },
+ {
+ name: "beef",
+ entries: []Entry{{42, common.Hex2Bytes("beef")}},
+ want: "2a00020000000000beef",
+ },
+ {
+ name: "twoEntries",
+ entries: []Entry{
+ {42, common.Hex2Bytes("beef")},
+ {9, common.Hex2Bytes("abcdabcd")},
+ },
+ want: "2a00020000000000beef0900040000000000abcdabcd",
+ },
+ } {
+ tt := test
+ t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
+ var (
+ b = bytes.NewBuffer(nil)
+ w = NewWriter(b)
+ )
+ for _, e := range tt.entries {
+ if _, err := w.Write(e.Type, e.Value); err != nil {
+ t.Fatalf("encoding error: %v", err)
+ }
+ }
+ if want, have := common.FromHex(tt.want), b.Bytes(); !bytes.Equal(want, have) {
+ t.Fatalf("encoding mismatch (want %x, have %x", want, have)
+ }
+ r := NewReader(bytes.NewReader(b.Bytes()))
+ for _, want := range tt.entries {
+ have, err := r.Read()
+ if err != nil {
+ t.Fatalf("decoding error: %v", err)
+ }
+ if have.Type != want.Type {
+ t.Fatalf("decoded entry does type mismatch (want %v, got %v)", want.Type, have.Type)
+ }
+ if !bytes.Equal(have.Value, want.Value) {
+ t.Fatalf("decoded entry does not match (want %#x, got %#x)", want.Value, have.Value)
+ }
+ }
+ })
+ }
+}
+
+func TestDecode(t *testing.T) {
+ for i, tt := range []struct {
+ have string
+ err error
+ }{
+ { // basic valid decoding
+ have: "ffff000000000000",
+ },
+ { // basic invalid decoding
+ have: "ffff000000000001",
+ err: errors.New("reserved bytes are non-zero"),
+ },
+ { // no more entries to read, returns EOF
+ have: "",
+ err: io.EOF,
+ },
+ { // malformed type
+ have: "bad",
+ err: io.ErrUnexpectedEOF,
+ },
+ { // malformed length
+ have: "badbeef",
+ err: io.ErrUnexpectedEOF,
+ },
+ { // specified length longer than actual value
+ have: "beef010000000000",
+ err: io.ErrUnexpectedEOF,
+ },
+ } {
+ r := NewReader(bytes.NewReader(common.FromHex(tt.have)))
+ if tt.err != nil {
+ _, err := r.Read()
+ if err == nil && tt.err != nil {
+ t.Fatalf("test %d, expected error, got none", i)
+ }
+ if err != nil && tt.err == nil {
+ t.Fatalf("test %d, expected no error, got %v", i, err)
+ }
+ if err != nil && tt.err != nil && err.Error() != tt.err.Error() {
+ t.Fatalf("expected error %v, got %v", tt.err, err)
+ }
+ continue
+ }
+ }
+}
+
+func FuzzCodec(f *testing.F) {
+ f.Fuzz(func(t *testing.T, input []byte) {
+ r := NewReader(bytes.NewReader(input))
+ entry, err := r.Read()
+ if err != nil {
+ return
+ }
+ var (
+ b = bytes.NewBuffer(nil)
+ w = NewWriter(b)
+ )
+ w.Write(entry.Type, entry.Value)
+ output := b.Bytes()
+ // Only care about the input that was actually consumed
+ input = input[:r.offset]
+ if !bytes.Equal(input, output) {
+ t.Fatalf("decode-encode mismatch, input %#x output %#x", input, output)
+ }
+ })
+}
diff --git a/internal/era/era.go b/internal/era/era.go
new file mode 100644
index 0000000000..6ad7339b36
--- /dev/null
+++ b/internal/era/era.go
@@ -0,0 +1,277 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package era
+
+import (
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "math/big"
+ "os"
+ "path"
+ "strconv"
+ "strings"
+ "sync"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/internal/era/e2store"
+ "github.com/ethereum/go-ethereum/rlp"
+ "github.com/golang/snappy"
+)
+
+var (
+ TypeVersion uint16 = 0x3265
+ TypeCompressedHeader uint16 = 0x03
+ TypeCompressedBody uint16 = 0x04
+ TypeCompressedReceipts uint16 = 0x05
+ TypeTotalDifficulty uint16 = 0x06
+ TypeAccumulator uint16 = 0x07
+ TypeBlockIndex uint16 = 0x3266
+
+ MaxEra1Size = 8192
+)
+
+// Filename returns a recognizable Era1-formatted file name for the specified
+// epoch and network.
+func Filename(network string, epoch int, root common.Hash) string {
+ return fmt.Sprintf("%s-%05d-%s.era1", network, epoch, root.Hex()[2:10])
+}
+
+// ReadDir reads all the era1 files in a directory for a given network.
+// Format: --.era1
+func ReadDir(dir, network string) ([]string, error) {
+ entries, err := os.ReadDir(dir)
+ if err != nil {
+ return nil, fmt.Errorf("error reading directory %s: %w", dir, err)
+ }
+ var (
+ next = uint64(0)
+ eras []string
+ )
+ for _, entry := range entries {
+ if path.Ext(entry.Name()) != ".era1" {
+ continue
+ }
+ parts := strings.Split(entry.Name(), "-")
+ if len(parts) != 3 || parts[0] != network {
+ // invalid era1 filename, skip
+ continue
+ }
+ if epoch, err := strconv.ParseUint(parts[1], 10, 64); err != nil {
+ return nil, fmt.Errorf("malformed era1 filename: %s", entry.Name())
+ } else if epoch != next {
+ return nil, fmt.Errorf("missing epoch %d", next)
+ }
+ next += 1
+ eras = append(eras, entry.Name())
+ }
+ return eras, nil
+}
+
+type ReadAtSeekCloser interface {
+ io.ReaderAt
+ io.Seeker
+ io.Closer
+}
+
+// Era reads and Era1 file.
+type Era struct {
+ f ReadAtSeekCloser // backing era1 file
+ s *e2store.Reader // e2store reader over f
+ m metadata // start, count, length info
+ mu *sync.Mutex // lock for buf
+ buf [8]byte // buffer reading entry offsets
+}
+
+// From returns an Era backed by f.
+func From(f ReadAtSeekCloser) (*Era, error) {
+ m, err := readMetadata(f)
+ if err != nil {
+ return nil, err
+ }
+ return &Era{
+ f: f,
+ s: e2store.NewReader(f),
+ m: m,
+ mu: new(sync.Mutex),
+ }, nil
+}
+
+// Open returns an Era backed by the given filename.
+func Open(filename string) (*Era, error) {
+ f, err := os.Open(filename)
+ if err != nil {
+ return nil, err
+ }
+ return From(f)
+}
+
+func (e *Era) Close() error {
+ return e.f.Close()
+}
+
+func (e *Era) GetBlockByNumber(num uint64) (*types.Block, error) {
+ if e.m.start > num || e.m.start+e.m.count <= num {
+ return nil, errors.New("out-of-bounds")
+ }
+ off, err := e.readOffset(num)
+ if err != nil {
+ return nil, err
+ }
+ r, n, err := newSnappyReader(e.s, TypeCompressedHeader, off)
+ if err != nil {
+ return nil, err
+ }
+ var header types.Header
+ if err := rlp.Decode(r, &header); err != nil {
+ return nil, err
+ }
+ off += n
+ r, _, err = newSnappyReader(e.s, TypeCompressedBody, off)
+ if err != nil {
+ return nil, err
+ }
+ var body types.Body
+ if err := rlp.Decode(r, &body); err != nil {
+ return nil, err
+ }
+ return types.NewBlockWithHeader(&header).WithBody(body), nil
+}
+
+// Accumulator reads the accumulator entry in the Era1 file.
+func (e *Era) Accumulator() (common.Hash, error) {
+ entry, err := e.s.Find(TypeAccumulator)
+ if err != nil {
+ return common.Hash{}, err
+ }
+ return common.BytesToHash(entry.Value), nil
+}
+
+// InitialTD returns initial total difficulty before the difficulty of the
+// first block of the Era1 is applied.
+func (e *Era) InitialTD() (*big.Int, error) {
+ var (
+ r io.Reader
+ header types.Header
+ rawTd []byte
+ n int64
+ off int64
+ err error
+ )
+
+ // Read first header.
+ if off, err = e.readOffset(e.m.start); err != nil {
+ return nil, err
+ }
+ if r, n, err = newSnappyReader(e.s, TypeCompressedHeader, off); err != nil {
+ return nil, err
+ }
+ if err := rlp.Decode(r, &header); err != nil {
+ return nil, err
+ }
+ off += n
+
+ // Skip over next two records.
+ for i := 0; i < 2; i++ {
+ length, err := e.s.LengthAt(off)
+ if err != nil {
+ return nil, err
+ }
+ off += length
+ }
+
+ // Read total difficulty after first block.
+ if r, _, err = e.s.ReaderAt(TypeTotalDifficulty, off); err != nil {
+ return nil, err
+ }
+ rawTd, err = io.ReadAll(r)
+ if err != nil {
+ return nil, err
+ }
+ td := new(big.Int).SetBytes(reverseOrder(rawTd))
+ return td.Sub(td, header.Difficulty), nil
+}
+
+// Start returns the listed start block.
+func (e *Era) Start() uint64 {
+ return e.m.start
+}
+
+// Count returns the total number of blocks in the Era1.
+func (e *Era) Count() uint64 {
+ return e.m.count
+}
+
+// readOffset reads a specific block's offset from the block index. The value n
+// is the absolute block number desired.
+func (e *Era) readOffset(n uint64) (int64, error) {
+ var (
+ blockIndexRecordOffset = e.m.length - 24 - int64(e.m.count)*8 // skips start, count, and header
+ firstIndex = blockIndexRecordOffset + 16 // first index after header / start-num
+ indexOffset = int64(n-e.m.start) * 8 // desired index * size of indexes
+ offOffset = firstIndex + indexOffset // offset of block offset
+ )
+ e.mu.Lock()
+ defer e.mu.Unlock()
+ clear(e.buf[:])
+ if _, err := e.f.ReadAt(e.buf[:], offOffset); err != nil {
+ return 0, err
+ }
+ // Since the block offset is relative from the start of the block index record
+ // we need to add the record offset to it's offset to get the block's absolute
+ // offset.
+ return blockIndexRecordOffset + int64(binary.LittleEndian.Uint64(e.buf[:])), nil
+}
+
+// newSnappyReader returns a snappy.Reader for the e2store entry value at off.
+func newSnappyReader(e *e2store.Reader, expectedType uint16, off int64) (io.Reader, int64, error) {
+ r, n, err := e.ReaderAt(expectedType, off)
+ if err != nil {
+ return nil, 0, err
+ }
+ return snappy.NewReader(r), int64(n), err
+}
+
+// metadata wraps the metadata in the block index.
+type metadata struct {
+ start uint64
+ count uint64
+ length int64
+}
+
+// readMetadata reads the metadata stored in an Era1 file's block index.
+func readMetadata(f ReadAtSeekCloser) (m metadata, err error) {
+ // Determine length of reader.
+ if m.length, err = f.Seek(0, io.SeekEnd); err != nil {
+ return
+ }
+ b := make([]byte, 16)
+ // Read count. It's the last 8 bytes of the file.
+ if _, err = f.ReadAt(b[:8], m.length-8); err != nil {
+ return
+ }
+ m.count = binary.LittleEndian.Uint64(b)
+ // Read start. It's at the offset -sizeof(m.count) -
+ // count*sizeof(indexEntry) - sizeof(m.start)
+ if _, err = f.ReadAt(b[8:], m.length-16-int64(m.count*8)); err != nil {
+ return
+ }
+ m.start = binary.LittleEndian.Uint64(b[8:])
+ return
+}
diff --git a/internal/era/era_test.go b/internal/era/era_test.go
new file mode 100644
index 0000000000..ee5d9e82a0
--- /dev/null
+++ b/internal/era/era_test.go
@@ -0,0 +1,142 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package era
+
+import (
+ "bytes"
+ "io"
+ "math/big"
+ "os"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+type testchain struct {
+ headers [][]byte
+ bodies [][]byte
+ receipts [][]byte
+ tds []*big.Int
+}
+
+func TestEra1Builder(t *testing.T) {
+ // Get temp directory.
+ f, err := os.CreateTemp("", "era1-test")
+ if err != nil {
+ t.Fatalf("error creating temp file: %v", err)
+ }
+ defer f.Close()
+
+ var (
+ builder = NewBuilder(f)
+ chain = testchain{}
+ )
+ for i := 0; i < 128; i++ {
+ chain.headers = append(chain.headers, []byte{byte('h'), byte(i)})
+ chain.bodies = append(chain.bodies, []byte{byte('b'), byte(i)})
+ chain.receipts = append(chain.receipts, []byte{byte('r'), byte(i)})
+ chain.tds = append(chain.tds, big.NewInt(int64(i)))
+ }
+
+ // Write blocks to Era1.
+ for i := 0; i < len(chain.headers); i++ {
+ var (
+ header = chain.headers[i]
+ body = chain.bodies[i]
+ receipts = chain.receipts[i]
+ hash = common.Hash{byte(i)}
+ td = chain.tds[i]
+ )
+ if err = builder.AddRLP(header, body, receipts, uint64(i), hash, td, big.NewInt(1)); err != nil {
+ t.Fatalf("error adding entry: %v", err)
+ }
+ }
+
+ // Finalize Era1.
+ if _, err := builder.Finalize(); err != nil {
+ t.Fatalf("error finalizing era1: %v", err)
+ }
+
+ // Verify Era1 contents.
+ e, err := Open(f.Name())
+ if err != nil {
+ t.Fatalf("failed to open era: %v", err)
+ }
+ it, err := NewRawIterator(e)
+ if err != nil {
+ t.Fatalf("failed to make iterator: %s", err)
+ }
+ for i := uint64(0); i < uint64(len(chain.headers)); i++ {
+ if !it.Next() {
+ t.Fatalf("expected more entries")
+ }
+ if it.Error() != nil {
+ t.Fatalf("unexpected error %v", it.Error())
+ }
+ // Check headers.
+ header, err := io.ReadAll(it.Header)
+ if err != nil {
+ t.Fatalf("error reading header: %v", err)
+ }
+ if !bytes.Equal(header, chain.headers[i]) {
+ t.Fatalf("mismatched header: want %s, got %s", chain.headers[i], header)
+ }
+ // Check bodies.
+ body, err := io.ReadAll(it.Body)
+ if err != nil {
+ t.Fatalf("error reading body: %v", err)
+ }
+ if !bytes.Equal(body, chain.bodies[i]) {
+ t.Fatalf("mismatched body: want %s, got %s", chain.bodies[i], body)
+ }
+ // Check receipts.
+ receipts, err := io.ReadAll(it.Receipts)
+ if err != nil {
+ t.Fatalf("error reading receipts: %v", err)
+ }
+ if !bytes.Equal(receipts, chain.receipts[i]) {
+ t.Fatalf("mismatched receipts: want %s, got %s", chain.receipts[i], receipts)
+ }
+
+ // Check total difficulty.
+ rawTd, err := io.ReadAll(it.TotalDifficulty)
+ if err != nil {
+ t.Fatalf("error reading td: %v", err)
+ }
+ td := new(big.Int).SetBytes(reverseOrder(rawTd))
+ if td.Cmp(chain.tds[i]) != 0 {
+ t.Fatalf("mismatched tds: want %s, got %s", chain.tds[i], td)
+ }
+ }
+}
+
+func TestEraFilename(t *testing.T) {
+ for i, tt := range []struct {
+ network string
+ epoch int
+ root common.Hash
+ expected string
+ }{
+ {"mainnet", 1, common.Hash{1}, "mainnet-00001-01000000.era1"},
+ {"goerli", 99999, common.HexToHash("0xdeadbeef00000000000000000000000000000000000000000000000000000000"), "goerli-99999-deadbeef.era1"},
+ } {
+ got := Filename(tt.network, tt.epoch, tt.root)
+ if tt.expected != got {
+ t.Errorf("test %d: invalid filename: want %s, got %s", i, tt.expected, got)
+ }
+ }
+}
diff --git a/internal/era/iterator.go b/internal/era/iterator.go
new file mode 100644
index 0000000000..f48aab46b4
--- /dev/null
+++ b/internal/era/iterator.go
@@ -0,0 +1,197 @@
+// Copyright 2023 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package era
+
+import (
+ "errors"
+ "io"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+// Iterator wraps RawIterator and returns decoded Era1 entries.
+type Iterator struct {
+ inner *RawIterator
+}
+
+// NewIterator returns a new Iterator instance. Next must be immediately
+// called on new iterators to load the first item.
+func NewIterator(e *Era) (*Iterator, error) {
+ inner, err := NewRawIterator(e)
+ if err != nil {
+ return nil, err
+ }
+ return &Iterator{inner}, nil
+}
+
+// Next moves the iterator to the next block entry. It returns false when all
+// items have been read or an error has halted its progress. Block, Receipts,
+// and BlockAndReceipts should no longer be called after false is returned.
+func (it *Iterator) Next() bool {
+ return it.inner.Next()
+}
+
+// Number returns the current number block the iterator will return.
+func (it *Iterator) Number() uint64 {
+ return it.inner.next - 1
+}
+
+// Error returns the error status of the iterator. It should be called before
+// reading from any of the iterator's values.
+func (it *Iterator) Error() error {
+ return it.inner.Error()
+}
+
+// Block returns the block for the iterator's current position.
+func (it *Iterator) Block() (*types.Block, error) {
+ if it.inner.Header == nil || it.inner.Body == nil {
+ return nil, errors.New("header and body must be non-nil")
+ }
+ var (
+ header types.Header
+ body types.Body
+ )
+ if err := rlp.Decode(it.inner.Header, &header); err != nil {
+ return nil, err
+ }
+ if err := rlp.Decode(it.inner.Body, &body); err != nil {
+ return nil, err
+ }
+ return types.NewBlockWithHeader(&header).WithBody(body), nil
+}
+
+// Receipts returns the receipts for the iterator's current position.
+func (it *Iterator) Receipts() (types.Receipts, error) {
+ if it.inner.Receipts == nil {
+ return nil, errors.New("receipts must be non-nil")
+ }
+ var receipts types.Receipts
+ err := rlp.Decode(it.inner.Receipts, &receipts)
+ return receipts, err
+}
+
+// BlockAndReceipts returns the block and receipts for the iterator's current
+// position.
+func (it *Iterator) BlockAndReceipts() (*types.Block, types.Receipts, error) {
+ b, err := it.Block()
+ if err != nil {
+ return nil, nil, err
+ }
+ r, err := it.Receipts()
+ if err != nil {
+ return nil, nil, err
+ }
+ return b, r, nil
+}
+
+// TotalDifficulty returns the total difficulty for the iterator's current
+// position.
+func (it *Iterator) TotalDifficulty() (*big.Int, error) {
+ td, err := io.ReadAll(it.inner.TotalDifficulty)
+ if err != nil {
+ return nil, err
+ }
+ return new(big.Int).SetBytes(reverseOrder(td)), nil
+}
+
+// RawIterator reads an RLP-encode Era1 entries.
+type RawIterator struct {
+ e *Era // backing Era1
+ next uint64 // next block to read
+ err error // last error
+
+ Header io.Reader
+ Body io.Reader
+ Receipts io.Reader
+ TotalDifficulty io.Reader
+}
+
+// NewRawIterator returns a new RawIterator instance. Next must be immediately
+// called on new iterators to load the first item.
+func NewRawIterator(e *Era) (*RawIterator, error) {
+ return &RawIterator{
+ e: e,
+ next: e.m.start,
+ }, nil
+}
+
+// Next moves the iterator to the next block entry. It returns false when all
+// items have been read or an error has halted its progress. Header, Body,
+// Receipts, TotalDifficulty will be set to nil in the case returning false or
+// finding an error and should therefore no longer be read from.
+func (it *RawIterator) Next() bool {
+ // Clear old errors.
+ it.err = nil
+ if it.e.m.start+it.e.m.count <= it.next {
+ it.clear()
+ return false
+ }
+ off, err := it.e.readOffset(it.next)
+ if err != nil {
+ // Error here means block index is corrupted, so don't
+ // continue.
+ it.clear()
+ it.err = err
+ return false
+ }
+ var n int64
+ if it.Header, n, it.err = newSnappyReader(it.e.s, TypeCompressedHeader, off); it.err != nil {
+ it.clear()
+ return true
+ }
+ off += n
+ if it.Body, n, it.err = newSnappyReader(it.e.s, TypeCompressedBody, off); it.err != nil {
+ it.clear()
+ return true
+ }
+ off += n
+ if it.Receipts, n, it.err = newSnappyReader(it.e.s, TypeCompressedReceipts, off); it.err != nil {
+ it.clear()
+ return true
+ }
+ off += n
+ if it.TotalDifficulty, _, it.err = it.e.s.ReaderAt(TypeTotalDifficulty, off); it.err != nil {
+ it.clear()
+ return true
+ }
+ it.next += 1
+ return true
+}
+
+// Number returns the current number block the iterator will return.
+func (it *RawIterator) Number() uint64 {
+ return it.next - 1
+}
+
+// Error returns the error status of the iterator. It should be called before
+// reading from any of the iterator's values.
+func (it *RawIterator) Error() error {
+ if it.err == io.EOF {
+ return nil
+ }
+ return it.err
+}
+
+// clear sets all the outputs to nil.
+func (it *RawIterator) clear() {
+ it.Header = nil
+ it.Body = nil
+ it.Receipts = nil
+ it.TotalDifficulty = nil
+}
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index 03f13af417..a469a8c0e0 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -30,7 +30,6 @@ import (
"github.com/tyler-smith/go-bip39"
"github.com/ethereum/go-ethereum/accounts"
- "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/accounts/scwallet"
"github.com/ethereum/go-ethereum/common"
@@ -41,6 +40,7 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
@@ -53,12 +53,15 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie"
+ "github.com/holiman/uint256"
)
// estimateGasErrorRatio is the amount of overestimation eth_estimateGas is
// allowed to produce in order to speed up calculations.
const estimateGasErrorRatio = 0.015
+var errBlobTxNotSupported = errors.New("signing blob transactions not supported")
+
// EthereumAPI provides an API to access Ethereum related information.
type EthereumAPI struct {
b Backend
@@ -70,13 +73,12 @@ func NewEthereumAPI(b Backend) *EthereumAPI {
}
// GasPrice returns a suggestion for a gas price for legacy transactions.
-func (s *EthereumAPI) GasPrice(ctx context.Context) (*hexutil.Big, error) {
- tipcap, err := s.b.SuggestGasTipCap(ctx)
+func (api *EthereumAPI) GasPrice(ctx context.Context) (*hexutil.Big, error) {
+ tipcap, err := api.b.SuggestGasTipCap(ctx)
if err != nil {
return nil, err
}
-
- if head := s.b.CurrentHeader(); head.BaseFee != nil {
+ if head := api.b.CurrentHeader(); head.BaseFee != nil {
tipcap.Add(tipcap, head.BaseFee)
}
@@ -84,8 +86,8 @@ func (s *EthereumAPI) GasPrice(ctx context.Context) (*hexutil.Big, error) {
}
// MaxPriorityFeePerGas returns a suggestion for a gas tip cap for dynamic fee transactions.
-func (s *EthereumAPI) MaxPriorityFeePerGas(ctx context.Context) (*hexutil.Big, error) {
- tipcap, err := s.b.SuggestGasTipCap(ctx)
+func (api *EthereumAPI) MaxPriorityFeePerGas(ctx context.Context) (*hexutil.Big, error) {
+ tipcap, err := api.b.SuggestGasTipCap(ctx)
if err != nil {
return nil, err
}
@@ -94,15 +96,17 @@ func (s *EthereumAPI) MaxPriorityFeePerGas(ctx context.Context) (*hexutil.Big, e
}
type feeHistoryResult struct {
- OldestBlock *hexutil.Big `json:"oldestBlock"`
- Reward [][]*hexutil.Big `json:"reward,omitempty"`
- BaseFee []*hexutil.Big `json:"baseFeePerGas,omitempty"`
- GasUsedRatio []float64 `json:"gasUsedRatio"`
+ OldestBlock *hexutil.Big `json:"oldestBlock"`
+ Reward [][]*hexutil.Big `json:"reward,omitempty"`
+ BaseFee []*hexutil.Big `json:"baseFeePerGas,omitempty"`
+ GasUsedRatio []float64 `json:"gasUsedRatio"`
+ BlobBaseFee []*hexutil.Big `json:"baseFeePerBlobGas,omitempty"`
+ BlobGasUsedRatio []float64 `json:"blobGasUsedRatio,omitempty"`
}
// FeeHistory returns the fee market history.
-func (s *EthereumAPI) FeeHistory(ctx context.Context, blockCount math.HexOrDecimal64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*feeHistoryResult, error) {
- oldest, reward, baseFee, gasUsed, err := s.b.FeeHistory(ctx, uint64(blockCount), lastBlock, rewardPercentiles)
+func (api *EthereumAPI) FeeHistory(ctx context.Context, blockCount math.HexOrDecimal64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*feeHistoryResult, error) {
+ oldest, reward, baseFee, gasUsed, blobBaseFee, blobGasUsed, err := api.b.FeeHistory(ctx, uint64(blockCount), lastBlock, rewardPercentiles)
if err != nil {
return nil, err
}
@@ -127,41 +131,56 @@ func (s *EthereumAPI) FeeHistory(ctx context.Context, blockCount math.HexOrDecim
results.BaseFee[i] = (*hexutil.Big)(v)
}
}
-
+ if blobBaseFee != nil {
+ results.BlobBaseFee = make([]*hexutil.Big, len(blobBaseFee))
+ for i, v := range blobBaseFee {
+ results.BlobBaseFee[i] = (*hexutil.Big)(v)
+ }
+ }
+ if blobGasUsed != nil {
+ results.BlobGasUsedRatio = blobGasUsed
+ }
return results, nil
}
+// BlobBaseFee returns the base fee for blob gas at the current head.
+func (api *EthereumAPI) BlobBaseFee(ctx context.Context) *hexutil.Big {
+ return (*hexutil.Big)(api.b.BlobBaseFee(ctx))
+}
+
// Syncing returns false in case the node is currently not syncing with the network. It can be up-to-date or has not
-// yet received the latest block headers from its pears. In case it is synchronizing:
+// yet received the latest block headers from its peers. In case it is synchronizing:
// - startingBlock: block number this node started to synchronize from
// - currentBlock: block number this node is currently importing
// - highestBlock: block number of the highest block header this node has received from peers
// - pulledStates: number of state entries processed until now
// - knownStates: number of known state entries that still need to be pulled
-func (s *EthereumAPI) Syncing() (interface{}, error) {
- progress := s.b.SyncProgress()
+func (api *EthereumAPI) Syncing() (interface{}, error) {
+ progress := api.b.SyncProgress()
// Return not syncing if the synchronisation already completed
- if progress.CurrentBlock >= progress.HighestBlock {
+ if progress.Done() {
return false, nil
}
// Otherwise gather the block sync stats
return map[string]interface{}{
- "startingBlock": hexutil.Uint64(progress.StartingBlock),
- "currentBlock": hexutil.Uint64(progress.CurrentBlock),
- "highestBlock": hexutil.Uint64(progress.HighestBlock),
- "syncedAccounts": hexutil.Uint64(progress.SyncedAccounts),
- "syncedAccountBytes": hexutil.Uint64(progress.SyncedAccountBytes),
- "syncedBytecodes": hexutil.Uint64(progress.SyncedBytecodes),
- "syncedBytecodeBytes": hexutil.Uint64(progress.SyncedBytecodeBytes),
- "syncedStorage": hexutil.Uint64(progress.SyncedStorage),
- "syncedStorageBytes": hexutil.Uint64(progress.SyncedStorageBytes),
- "healedTrienodes": hexutil.Uint64(progress.HealedTrienodes),
- "healedTrienodeBytes": hexutil.Uint64(progress.HealedTrienodeBytes),
- "healedBytecodes": hexutil.Uint64(progress.HealedBytecodes),
- "healedBytecodeBytes": hexutil.Uint64(progress.HealedBytecodeBytes),
- "healingTrienodes": hexutil.Uint64(progress.HealingTrienodes),
- "healingBytecode": hexutil.Uint64(progress.HealingBytecode),
+ "startingBlock": hexutil.Uint64(progress.StartingBlock),
+ "currentBlock": hexutil.Uint64(progress.CurrentBlock),
+ "highestBlock": hexutil.Uint64(progress.HighestBlock),
+ "syncedAccounts": hexutil.Uint64(progress.SyncedAccounts),
+ "syncedAccountBytes": hexutil.Uint64(progress.SyncedAccountBytes),
+ "syncedBytecodes": hexutil.Uint64(progress.SyncedBytecodes),
+ "syncedBytecodeBytes": hexutil.Uint64(progress.SyncedBytecodeBytes),
+ "syncedStorage": hexutil.Uint64(progress.SyncedStorage),
+ "syncedStorageBytes": hexutil.Uint64(progress.SyncedStorageBytes),
+ "healedTrienodes": hexutil.Uint64(progress.HealedTrienodes),
+ "healedTrienodeBytes": hexutil.Uint64(progress.HealedTrienodeBytes),
+ "healedBytecodes": hexutil.Uint64(progress.HealedBytecodes),
+ "healedBytecodeBytes": hexutil.Uint64(progress.HealedBytecodeBytes),
+ "healingTrienodes": hexutil.Uint64(progress.HealingTrienodes),
+ "healingBytecode": hexutil.Uint64(progress.HealingBytecode),
+ "txIndexFinishedBlocks": hexutil.Uint64(progress.TxIndexFinishedBlocks),
+ "txIndexRemainingBlocks": hexutil.Uint64(progress.TxIndexRemainingBlocks),
}, nil
}
@@ -176,18 +195,18 @@ func NewTxPoolAPI(b Backend) *TxPoolAPI {
}
// Content returns the transactions contained within the transaction pool.
-func (s *TxPoolAPI) Content() map[string]map[string]map[string]*RPCTransaction {
+func (api *TxPoolAPI) Content() map[string]map[string]map[string]*RPCTransaction {
content := map[string]map[string]map[string]*RPCTransaction{
"pending": make(map[string]map[string]*RPCTransaction),
"queued": make(map[string]map[string]*RPCTransaction),
}
- pending, queue := s.b.TxPoolContent()
- curHeader := s.b.CurrentHeader()
+ pending, queue := api.b.TxPoolContent()
+ curHeader := api.b.CurrentHeader()
// Flatten the pending transactions
for account, txs := range pending {
dump := make(map[string]*RPCTransaction)
for _, tx := range txs {
- dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig())
+ dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, api.b.ChainConfig())
}
content["pending"][account.Hex()] = dump
@@ -196,7 +215,7 @@ func (s *TxPoolAPI) Content() map[string]map[string]map[string]*RPCTransaction {
for account, txs := range queue {
dump := make(map[string]*RPCTransaction)
for _, tx := range txs {
- dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig())
+ dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, api.b.ChainConfig())
}
content["queued"][account.Hex()] = dump
@@ -206,15 +225,15 @@ func (s *TxPoolAPI) Content() map[string]map[string]map[string]*RPCTransaction {
}
// ContentFrom returns the transactions contained within the transaction pool.
-func (s *TxPoolAPI) ContentFrom(addr common.Address) map[string]map[string]*RPCTransaction {
+func (api *TxPoolAPI) ContentFrom(addr common.Address) map[string]map[string]*RPCTransaction {
content := make(map[string]map[string]*RPCTransaction, 2)
- pending, queue := s.b.TxPoolContentFrom(addr)
- curHeader := s.b.CurrentHeader()
+ pending, queue := api.b.TxPoolContentFrom(addr)
+ curHeader := api.b.CurrentHeader()
// Build the pending transactions
dump := make(map[string]*RPCTransaction, len(pending))
for _, tx := range pending {
- dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig())
+ dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, api.b.ChainConfig())
}
content["pending"] = dump
@@ -222,7 +241,7 @@ func (s *TxPoolAPI) ContentFrom(addr common.Address) map[string]map[string]*RPCT
// Build the queued transactions
dump = make(map[string]*RPCTransaction, len(queue))
for _, tx := range queue {
- dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig())
+ dump[fmt.Sprintf("%d", tx.Nonce())] = NewRPCPendingTransaction(tx, curHeader, api.b.ChainConfig())
}
content["queued"] = dump
@@ -231,9 +250,8 @@ func (s *TxPoolAPI) ContentFrom(addr common.Address) map[string]map[string]*RPCT
}
// Status returns the number of pending and queued transaction in the pool.
-func (s *TxPoolAPI) Status() map[string]hexutil.Uint {
- pending, queue := s.b.Stats()
-
+func (api *TxPoolAPI) Status() map[string]hexutil.Uint {
+ pending, queue := api.b.Stats()
return map[string]hexutil.Uint{
"pending": hexutil.Uint(pending),
"queued": hexutil.Uint(queue),
@@ -242,12 +260,12 @@ func (s *TxPoolAPI) Status() map[string]hexutil.Uint {
// Inspect retrieves the content of the transaction pool and flattens it into an
// easily inspectable list.
-func (s *TxPoolAPI) Inspect() map[string]map[string]map[string]string {
+func (api *TxPoolAPI) Inspect() map[string]map[string]map[string]string {
content := map[string]map[string]map[string]string{
"pending": make(map[string]map[string]string),
"queued": make(map[string]map[string]string),
}
- pending, queue := s.b.TxPoolContent()
+ pending, queue := api.b.TxPoolContent()
// Define a formatter to flatten a transaction into a string
var format = func(tx *types.Transaction) string {
@@ -290,8 +308,8 @@ func NewEthereumAccountAPI(am *accounts.Manager) *EthereumAccountAPI {
}
// Accounts returns the collection of accounts this node manages.
-func (s *EthereumAccountAPI) Accounts() []common.Address {
- return s.am.Accounts()
+func (api *EthereumAccountAPI) Accounts() []common.Address {
+ return api.am.Accounts()
}
// PersonalAccountAPI provides an API to access accounts managed by this node.
@@ -303,7 +321,7 @@ type PersonalAccountAPI struct {
b Backend
}
-// NewPersonalAccountAPI create a new PersonalAccountAPI.
+// NewPersonalAccountAPI creates a new PersonalAccountAPI.
func NewPersonalAccountAPI(b Backend, nonceLock *AddrLocker) *PersonalAccountAPI {
return &PersonalAccountAPI{
am: b.AccountManager(),
@@ -313,8 +331,8 @@ func NewPersonalAccountAPI(b Backend, nonceLock *AddrLocker) *PersonalAccountAPI
}
// ListAccounts will return a list of addresses for accounts this node manages.
-func (s *PersonalAccountAPI) ListAccounts() []common.Address {
- return s.am.Accounts()
+func (api *PersonalAccountAPI) ListAccounts() []common.Address {
+ return api.am.Accounts()
}
// rawWallet is a JSON representation of an accounts.Wallet interface, with its
@@ -327,10 +345,9 @@ type rawWallet struct {
}
// ListWallets will return a list of wallets this node manages.
-func (s *PersonalAccountAPI) ListWallets() []rawWallet {
+func (api *PersonalAccountAPI) ListWallets() []rawWallet {
wallets := make([]rawWallet, 0) // return [] instead of nil if empty
-
- for _, wallet := range s.am.Wallets() {
+ for _, wallet := range api.am.Wallets() {
status, failure := wallet.Status()
raw := rawWallet{
@@ -352,8 +369,8 @@ func (s *PersonalAccountAPI) ListWallets() []rawWallet {
// connection and attempting to authenticate via the provided passphrase. Note,
// the method may return an extra challenge requiring a second open (e.g. the
// Trezor PIN matrix challenge).
-func (s *PersonalAccountAPI) OpenWallet(url string, passphrase *string) error {
- wallet, err := s.am.Wallet(url)
+func (api *PersonalAccountAPI) OpenWallet(url string, passphrase *string) error {
+ wallet, err := api.am.Wallet(url)
if err != nil {
return err
}
@@ -368,8 +385,8 @@ func (s *PersonalAccountAPI) OpenWallet(url string, passphrase *string) error {
// DeriveAccount requests an HD wallet to derive a new account, optionally pinning
// it for later reuse.
-func (s *PersonalAccountAPI) DeriveAccount(url string, path string, pin *bool) (accounts.Account, error) {
- wallet, err := s.am.Wallet(url)
+func (api *PersonalAccountAPI) DeriveAccount(url string, path string, pin *bool) (accounts.Account, error) {
+ wallet, err := api.am.Wallet(url)
if err != nil {
return accounts.Account{}, err
}
@@ -387,8 +404,8 @@ func (s *PersonalAccountAPI) DeriveAccount(url string, path string, pin *bool) (
}
// NewAccount will create a new account and returns the address for the new account.
-func (s *PersonalAccountAPI) NewAccount(password string) (common.AddressEIP55, error) {
- ks, err := fetchKeystore(s.am)
+func (api *PersonalAccountAPI) NewAccount(password string) (common.AddressEIP55, error) {
+ ks, err := fetchKeystore(api.am)
if err != nil {
return common.AddressEIP55{}, err
}
@@ -415,13 +432,12 @@ func fetchKeystore(am *accounts.Manager) (*keystore.KeyStore, error) {
// ImportRawKey stores the given hex encoded ECDSA key into the key directory,
// encrypting it with the passphrase.
-func (s *PersonalAccountAPI) ImportRawKey(privkey string, password string) (common.Address, error) {
+func (api *PersonalAccountAPI) ImportRawKey(privkey string, password string) (common.Address, error) {
key, err := crypto.HexToECDSA(privkey)
if err != nil {
return common.Address{}, err
}
-
- ks, err := fetchKeystore(s.am)
+ ks, err := fetchKeystore(api.am)
if err != nil {
return common.Address{}, err
}
@@ -434,11 +450,11 @@ func (s *PersonalAccountAPI) ImportRawKey(privkey string, password string) (comm
// UnlockAccount will unlock the account associated with the given address with
// the given password for duration seconds. If duration is nil it will use a
// default of 300 seconds. It returns an indication if the account was unlocked.
-func (s *PersonalAccountAPI) UnlockAccount(ctx context.Context, addr common.Address, password string, duration *uint64) (bool, error) {
+func (api *PersonalAccountAPI) UnlockAccount(ctx context.Context, addr common.Address, password string, duration *uint64) (bool, error) {
// When the API is exposed by external RPC(http, ws etc), unless the user
// explicitly specifies to allow the insecure account unlocking, otherwise
// it is disabled.
- if s.b.ExtRPCEnabled() && !s.b.AccountManager().Config().InsecureUnlockAllowed {
+ if api.b.ExtRPCEnabled() && !api.b.AccountManager().Config().InsecureUnlockAllowed {
return false, errors.New("account unlock with HTTP access is forbidden")
}
@@ -452,8 +468,7 @@ func (s *PersonalAccountAPI) UnlockAccount(ctx context.Context, addr common.Addr
} else {
d = time.Duration(*duration) * time.Second
}
-
- ks, err := fetchKeystore(s.am)
+ ks, err := fetchKeystore(api.am)
if err != nil {
return false, err
}
@@ -467,8 +482,8 @@ func (s *PersonalAccountAPI) UnlockAccount(ctx context.Context, addr common.Addr
}
// LockAccount will lock the account associated with the given address when it's unlocked.
-func (s *PersonalAccountAPI) LockAccount(addr common.Address) bool {
- if ks, err := fetchKeystore(s.am); err == nil {
+func (api *PersonalAccountAPI) LockAccount(addr common.Address) bool {
+ if ks, err := fetchKeystore(api.am); err == nil {
return ks.Lock(addr) == nil
}
@@ -478,49 +493,49 @@ func (s *PersonalAccountAPI) LockAccount(addr common.Address) bool {
// signTransaction sets defaults and signs the given transaction
// NOTE: the caller needs to ensure that the nonceLock is held, if applicable,
// and release it after the transaction has been submitted to the tx pool
-func (s *PersonalAccountAPI) signTransaction(ctx context.Context, args *TransactionArgs, passwd string) (*types.Transaction, error) {
+func (api *PersonalAccountAPI) signTransaction(ctx context.Context, args *TransactionArgs, passwd string) (*types.Transaction, error) {
// Look up the wallet containing the requested signer
account := accounts.Account{Address: args.from()}
-
- wallet, err := s.am.Find(account)
+ wallet, err := api.am.Find(account)
if err != nil {
return nil, err
}
// Set some sanity defaults and terminate on failure
- if err := args.setDefaults(ctx, s.b); err != nil {
+ if err := args.setDefaults(ctx, api.b, false); err != nil {
return nil, err
}
// Assemble the transaction and sign with the wallet
- tx := args.toTransaction()
+ tx := args.ToTransaction()
- return wallet.SignTxWithPassphrase(account, passwd, tx, s.b.ChainConfig().ChainID)
+ return wallet.SignTxWithPassphrase(account, passwd, tx, api.b.ChainConfig().ChainID)
}
// SendTransaction will create a transaction from the given arguments and
// tries to sign it with the key associated with args.From. If the given
// passwd isn't able to decrypt the key it fails.
-func (s *PersonalAccountAPI) SendTransaction(ctx context.Context, args TransactionArgs, passwd string) (common.Hash, error) {
+func (api *PersonalAccountAPI) SendTransaction(ctx context.Context, args TransactionArgs, passwd string) (common.Hash, error) {
if args.Nonce == nil {
// Hold the mutex around signing to prevent concurrent assignment of
// the same nonce to multiple accounts.
- s.nonceLock.LockAddr(args.from())
- defer s.nonceLock.UnlockAddr(args.from())
+ api.nonceLock.LockAddr(args.from())
+ defer api.nonceLock.UnlockAddr(args.from())
}
-
- signed, err := s.signTransaction(ctx, &args, passwd)
+ if args.IsEIP4844() {
+ return common.Hash{}, errBlobTxNotSupported
+ }
+ signed, err := api.signTransaction(ctx, &args, passwd)
if err != nil {
log.Warn("Failed transaction send attempt", "from", args.from(), "to", args.To, "value", args.Value.ToInt(), "err", err)
return common.Hash{}, err
}
-
- return SubmitTransaction(ctx, s.b, signed)
+ return SubmitTransaction(ctx, api.b, signed)
}
// SignTransaction will create a transaction from the given arguments and
// tries to sign it with the key associated with args.From. If the given passwd isn't
// able to decrypt the key it fails. The transaction is returned in RLP-form, not broadcast
// to other nodes
-func (s *PersonalAccountAPI) SignTransaction(ctx context.Context, args TransactionArgs, passwd string) (*SignTransactionResult, error) {
+func (api *PersonalAccountAPI) SignTransaction(ctx context.Context, args TransactionArgs, passwd string) (*SignTransactionResult, error) {
// No need to obtain the noncelock mutex, since we won't be sending this
// tx into the transaction pool, but right back to the user
if args.From == nil {
@@ -534,17 +549,18 @@ func (s *PersonalAccountAPI) SignTransaction(ctx context.Context, args Transacti
if args.GasPrice == nil && (args.MaxFeePerGas == nil || args.MaxPriorityFeePerGas == nil) {
return nil, errors.New("missing gasPrice or maxFeePerGas/maxPriorityFeePerGas")
}
-
+ if args.IsEIP4844() {
+ return nil, errBlobTxNotSupported
+ }
if args.Nonce == nil {
return nil, errors.New("nonce not specified")
}
// Before actually signing the transaction, ensure the transaction fee is reasonable.
- tx := args.toTransaction()
- if err := checkTxFee(tx.GasPrice(), tx.Gas(), s.b.RPCTxFeeCap()); err != nil {
+ tx := args.ToTransaction()
+ if err := checkTxFee(tx.GasPrice(), tx.Gas(), api.b.RPCTxFeeCap()); err != nil {
return nil, err
}
-
- signed, err := s.signTransaction(ctx, &args, passwd)
+ signed, err := api.signTransaction(ctx, &args, passwd)
if err != nil {
log.Warn("Failed transaction sign attempt", "from", args.from(), "to", args.To, "value", args.Value.ToInt(), "err", err)
return nil, err
@@ -566,12 +582,12 @@ func (s *PersonalAccountAPI) SignTransaction(ctx context.Context, args Transacti
//
// The key used to calculate the signature is decrypted with the given password.
//
-// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_sign
-func (s *PersonalAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr common.Address, passwd string) (hexutil.Bytes, error) {
+// https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-personal#personal-sign
+func (api *PersonalAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr common.Address, passwd string) (hexutil.Bytes, error) {
// Look up the wallet containing the requested signer
account := accounts.Account{Address: addr}
- wallet, err := s.b.AccountManager().Find(account)
+ wallet, err := api.b.AccountManager().Find(account)
if err != nil {
return nil, err
}
@@ -596,8 +612,8 @@ func (s *PersonalAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr
// Note, the signature must conform to the secp256k1 curve R, S and V values, where
// the V value must be 27 or 28 for legacy reasons.
//
-// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover
-func (s *PersonalAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) {
+// https://geth.ethereum.org/docs/interacting-with-geth/rpc/ns-personal#personal-ecrecover
+func (api *PersonalAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) {
if len(sig) != crypto.SignatureLength {
return common.Address{}, fmt.Errorf("signature must be %d bytes long", crypto.SignatureLength)
}
@@ -617,8 +633,8 @@ func (s *PersonalAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.By
}
// InitializeWallet initializes a new wallet at the provided URL, by generating and returning a new private key.
-func (s *PersonalAccountAPI) InitializeWallet(ctx context.Context, url string) (string, error) {
- wallet, err := s.am.Wallet(url)
+func (api *PersonalAccountAPI) InitializeWallet(ctx context.Context, url string) (string, error) {
+ wallet, err := api.am.Wallet(url)
if err != nil {
return "", err
}
@@ -644,8 +660,8 @@ func (s *PersonalAccountAPI) InitializeWallet(ctx context.Context, url string) (
}
// Unpair deletes a pairing between wallet and geth.
-func (s *PersonalAccountAPI) Unpair(ctx context.Context, url string, pin string) error {
- wallet, err := s.am.Wallet(url)
+func (api *PersonalAccountAPI) Unpair(ctx context.Context, url string, pin string) error {
+ wallet, err := api.am.Wallet(url)
if err != nil {
return err
}
@@ -669,8 +685,8 @@ func NewBlockChainAPI(b Backend) *BlockChainAPI {
}
// GetTransactionReceiptsByBlock returns the transaction receipts for the given block number or hash.
-func (s *BlockChainAPI) GetTransactionReceiptsByBlock(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]map[string]interface{}, error) {
- block, err := s.b.BlockByNumberOrHash(ctx, blockNrOrHash)
+func (api *BlockChainAPI) GetTransactionReceiptsByBlock(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]map[string]interface{}, error) {
+ block, err := api.b.BlockByNumberOrHash(ctx, blockNrOrHash)
if err != nil {
return nil, err
}
@@ -679,7 +695,7 @@ func (s *BlockChainAPI) GetTransactionReceiptsByBlock(ctx context.Context, block
return nil, errors.New("block not found")
}
- receipts, err := s.b.GetReceipts(ctx, block.Hash())
+ receipts, err := api.b.GetReceipts(ctx, block.Hash())
if err != nil {
return nil, err
}
@@ -688,13 +704,13 @@ func (s *BlockChainAPI) GetTransactionReceiptsByBlock(ctx context.Context, block
var txHash common.Hash
- borReceipt := rawdb.ReadBorReceipt(s.b.ChainDb(), block.Hash(), block.NumberU64(), s.b.ChainConfig())
+ borReceipt := rawdb.ReadBorReceipt(api.b.ChainDb(), block.Hash(), block.NumberU64(), api.b.ChainConfig())
if borReceipt != nil {
receipts = append(receipts, borReceipt)
txHash = types.GetDerivedBorTxHash(types.BorReceiptKey(block.Number().Uint64(), block.Hash()))
if txHash != (common.Hash{}) {
- borTx, _, _, _, _ := s.b.GetBorBlockTransactionWithBlockHash(ctx, txHash, block.Hash())
+ borTx, _, _, _, _ := api.b.GetBorBlockTransactionWithBlockHash(ctx, txHash, block.Hash())
txs = append(txs, borTx)
}
}
@@ -708,7 +724,7 @@ func (s *BlockChainAPI) GetTransactionReceiptsByBlock(ctx context.Context, block
for idx, receipt := range receipts {
tx := txs[idx]
- signer := types.MakeSigner(s.b.ChainConfig(), block.Number(), block.Time())
+ signer := types.MakeSigner(api.b.ChainConfig(), block.Number(), block.Time())
from, _ := types.Sender(signer, tx)
fields := map[string]interface{}{
@@ -768,24 +784,24 @@ func (api *BlockChainAPI) ChainId() *hexutil.Big {
}
// BlockNumber returns the block number of the chain head.
-func (s *BlockChainAPI) BlockNumber() hexutil.Uint64 {
- header, _ := s.b.HeaderByNumber(context.Background(), rpc.LatestBlockNumber) // latest header should always be available
+func (api *BlockChainAPI) BlockNumber() hexutil.Uint64 {
+ header, _ := api.b.HeaderByNumber(context.Background(), rpc.LatestBlockNumber) // latest header should always be available
return hexutil.Uint64(header.Number.Uint64())
}
// GetBalance returns the amount of wei for the given address in the state of the
// given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta
// block numbers are also allowed.
-func (s *BlockChainAPI) GetBalance(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Big, error) {
- state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
+func (api *BlockChainAPI) GetBalance(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Big, error) {
+ state, _, err := api.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
if state == nil || err != nil {
return nil, err
}
-
- return (*hexutil.Big)(state.GetBalance(address)), state.Error()
+ b := state.GetBalance(address).ToBig()
+ return (*hexutil.Big)(b), state.Error()
}
-// Result structs for GetProof
+// AccountResult structs for GetProof
type AccountResult struct {
Address common.Address `json:"address"`
AccountProof []string `json:"accountProof"`
@@ -816,7 +832,7 @@ func (n *proofList) Delete(key []byte) error {
}
// GetProof returns the Merkle-proof for a given account and optionally some storage keys.
-func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*AccountResult, error) {
+func (api *BlockChainAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*AccountResult, error) {
var (
keys = make([]common.Hash, len(storageKeys))
keyLengths = make([]int, len(storageKeys))
@@ -830,7 +846,7 @@ func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, st
return nil, err
}
}
- statedb, header, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
+ statedb, header, err := api.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
if statedb == nil || err != nil {
return nil, err
}
@@ -880,10 +896,11 @@ func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, st
if err := tr.Prove(crypto.Keccak256(address.Bytes()), &accountProof); err != nil {
return nil, err
}
+ balance := statedb.GetBalance(address).ToBig()
return &AccountResult{
Address: address,
AccountProof: accountProof,
- Balance: (*hexutil.Big)(statedb.GetBalance(address)),
+ Balance: (*hexutil.Big)(balance),
CodeHash: codeHash,
Nonce: hexutil.Uint64(statedb.GetNonce(address)),
StorageHash: storageRoot,
@@ -918,10 +935,10 @@ func decodeHash(s string) (h common.Hash, inputLength int, err error) {
// - When blockNr is -2 the chain latest header is returned.
// - When blockNr is -3 the chain finalized header is returned.
// - When blockNr is -4 the chain safe header is returned.
-func (s *BlockChainAPI) GetHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (map[string]interface{}, error) {
- header, err := s.b.HeaderByNumber(ctx, number)
+func (api *BlockChainAPI) GetHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (map[string]interface{}, error) {
+ header, err := api.b.HeaderByNumber(ctx, number)
if header != nil && err == nil {
- response := s.rpcMarshalHeader(ctx, header)
+ response := api.rpcMarshalHeader(ctx, header)
if number == rpc.PendingBlockNumber {
// Pending header need to nil out a few fields
for _, field := range []string{"hash", "nonce", "miner"} {
@@ -934,10 +951,10 @@ func (s *BlockChainAPI) GetHeaderByNumber(ctx context.Context, number rpc.BlockN
}
// GetHeaderByHash returns the requested header by hash.
-func (s *BlockChainAPI) GetHeaderByHash(ctx context.Context, hash common.Hash) map[string]interface{} {
- header, _ := s.b.HeaderByHash(ctx, hash)
+func (api *BlockChainAPI) GetHeaderByHash(ctx context.Context, hash common.Hash) map[string]interface{} {
+ header, _ := api.b.HeaderByHash(ctx, hash)
if header != nil {
- return s.rpcMarshalHeader(ctx, header)
+ return api.rpcMarshalHeader(ctx, header)
}
return nil
@@ -950,10 +967,10 @@ func (s *BlockChainAPI) GetHeaderByHash(ctx context.Context, hash common.Hash) m
// - When blockNr is -4 the chain safe block is returned.
// - When fullTx is true all transactions in the block are returned, otherwise
// only the transaction hash is returned.
-func (s *BlockChainAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
- block, err := s.b.BlockByNumber(ctx, number)
+func (api *BlockChainAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
+ block, err := api.b.BlockByNumber(ctx, number)
if block != nil && err == nil {
- response, err := s.rpcMarshalBlock(ctx, block, true, fullTx)
+ response, err := api.rpcMarshalBlock(ctx, block, true, fullTx)
if err == nil && number == rpc.PendingBlockNumber {
// Pending blocks need to nil out a few fields
for _, field := range []string{"hash", "nonce", "miner"} {
@@ -963,7 +980,7 @@ func (s *BlockChainAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNu
// append marshalled bor transaction
if err == nil && response != nil {
- response = s.appendRPCMarshalBorTransaction(ctx, block, response, fullTx)
+ response = api.appendRPCMarshalBorTransaction(ctx, block, response, fullTx)
}
return response, err
@@ -974,13 +991,13 @@ func (s *BlockChainAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNu
// GetBlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full
// detail, otherwise only the transaction hash is returned.
-func (s *BlockChainAPI) GetBlockByHash(ctx context.Context, hash common.Hash, fullTx bool) (map[string]interface{}, error) {
- block, err := s.b.BlockByHash(ctx, hash)
+func (api *BlockChainAPI) GetBlockByHash(ctx context.Context, hash common.Hash, fullTx bool) (map[string]interface{}, error) {
+ block, err := api.b.BlockByHash(ctx, hash)
if block != nil {
- response, err := s.rpcMarshalBlock(ctx, block, true, fullTx)
+ response, err := api.rpcMarshalBlock(ctx, block, true, fullTx)
// append marshalled bor transaction
if err == nil && response != nil {
- return s.appendRPCMarshalBorTransaction(ctx, block, response, fullTx), err
+ return api.appendRPCMarshalBorTransaction(ctx, block, response, fullTx), err
}
return response, err
@@ -990,8 +1007,8 @@ func (s *BlockChainAPI) GetBlockByHash(ctx context.Context, hash common.Hash, fu
}
// GetUncleByBlockNumberAndIndex returns the uncle block for the given block hash and index.
-func (s *BlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (map[string]interface{}, error) {
- block, err := s.b.BlockByNumber(ctx, blockNr)
+func (api *BlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (map[string]interface{}, error) {
+ block, err := api.b.BlockByNumber(ctx, blockNr)
if block != nil {
uncles := block.Uncles()
if index >= hexutil.Uint(len(uncles)) {
@@ -1000,16 +1017,15 @@ func (s *BlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, block
}
block = types.NewBlockWithHeader(uncles[index])
-
- return s.rpcMarshalBlock(ctx, block, false, false)
+ return api.rpcMarshalBlock(ctx, block, false, false)
}
return nil, err
}
// GetUncleByBlockHashAndIndex returns the uncle block for the given block hash and index.
-func (s *BlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) (map[string]interface{}, error) {
- block, err := s.b.BlockByHash(ctx, blockHash)
+func (api *BlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) (map[string]interface{}, error) {
+ block, err := api.b.BlockByHash(ctx, blockHash)
if block != nil {
uncles := block.Uncles()
if index >= hexutil.Uint(len(uncles)) {
@@ -1018,16 +1034,15 @@ func (s *BlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHa
}
block = types.NewBlockWithHeader(uncles[index])
-
- return s.rpcMarshalBlock(ctx, block, false, false)
+ return api.rpcMarshalBlock(ctx, block, false, false)
}
return nil, err
}
// GetUncleCountByBlockNumber returns number of uncles in the block for the given block number
-func (s *BlockChainAPI) GetUncleCountByBlockNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint {
- if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
+func (api *BlockChainAPI) GetUncleCountByBlockNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint {
+ if block, _ := api.b.BlockByNumber(ctx, blockNr); block != nil {
n := hexutil.Uint(len(block.Uncles()))
return &n
}
@@ -1036,8 +1051,8 @@ func (s *BlockChainAPI) GetUncleCountByBlockNumber(ctx context.Context, blockNr
}
// GetUncleCountByBlockHash returns number of uncles in the block for the given block hash
-func (s *BlockChainAPI) GetUncleCountByBlockHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint {
- if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil {
+func (api *BlockChainAPI) GetUncleCountByBlockHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint {
+ if block, _ := api.b.BlockByHash(ctx, blockHash); block != nil {
n := hexutil.Uint(len(block.Uncles()))
return &n
}
@@ -1046,8 +1061,8 @@ func (s *BlockChainAPI) GetUncleCountByBlockHash(ctx context.Context, blockHash
}
// GetCode returns the code stored at the given address in the state for the given block number.
-func (s *BlockChainAPI) GetCode(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
- state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
+func (api *BlockChainAPI) GetCode(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
+ state, _, err := api.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
if state == nil || err != nil {
return nil, err
}
@@ -1060,8 +1075,8 @@ func (s *BlockChainAPI) GetCode(ctx context.Context, address common.Address, blo
// GetStorageAt returns the storage from the state at the given address, key and
// block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block
// numbers are also allowed.
-func (s *BlockChainAPI) GetStorageAt(ctx context.Context, address common.Address, hexKey string, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
- state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
+func (api *BlockChainAPI) GetStorageAt(ctx context.Context, address common.Address, hexKey string, blockNrOrHash rpc.BlockNumberOrHash) (hexutil.Bytes, error) {
+ state, _, err := api.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
if state == nil || err != nil {
return nil, err
}
@@ -1076,14 +1091,14 @@ func (s *BlockChainAPI) GetStorageAt(ctx context.Context, address common.Address
}
// GetBlockReceipts returns the block receipts for the given block hash or number or tag.
-func (s *BlockChainAPI) GetBlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]map[string]interface{}, error) {
- block, err := s.b.BlockByNumberOrHash(ctx, blockNrOrHash)
+func (api *BlockChainAPI) GetBlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) ([]map[string]interface{}, error) {
+ block, err := api.b.BlockByNumberOrHash(ctx, blockNrOrHash)
if block == nil || err != nil {
// When the block doesn't exist, the RPC method should return JSON null
// as per specification.
return nil, nil
}
- receipts, err := s.b.GetReceipts(ctx, block.Hash())
+ receipts, err := api.b.GetReceipts(ctx, block.Hash())
if err != nil {
return nil, err
}
@@ -1093,16 +1108,16 @@ func (s *BlockChainAPI) GetBlockReceipts(ctx context.Context, blockNrOrHash rpc.
}
// Derive the sender.
- signer := types.MakeSigner(s.b.ChainConfig(), block.Number(), block.Time())
+ signer := types.MakeSigner(api.b.ChainConfig(), block.Number(), block.Time())
result := make([]map[string]interface{}, len(receipts))
for i, receipt := range receipts {
result[i] = marshalReceipt(receipt, block.Hash(), block.NumberU64(), signer, txs[i], i, false)
}
- stateSyncReceipt := rawdb.ReadBorReceipt(s.b.ChainDb(), block.Hash(), block.NumberU64(), s.b.ChainConfig())
+ stateSyncReceipt := rawdb.ReadBorReceipt(api.b.ChainDb(), block.Hash(), block.NumberU64(), api.b.ChainConfig())
if stateSyncReceipt != nil {
- tx, _, _, _ := rawdb.ReadBorTransaction(s.b.ChainDb(), stateSyncReceipt.TxHash)
+ tx, _, _, _ := rawdb.ReadBorTransaction(api.b.ChainDb(), stateSyncReceipt.TxHash)
result = append(result, marshalReceipt(stateSyncReceipt, block.Hash(), block.NumberU64(), signer, tx, len(result), true))
}
@@ -1113,7 +1128,7 @@ func (s *BlockChainAPI) GetBlockReceipts(ctx context.Context, blockNrOrHash rpc.
// of a message call.
// Note, state and stateDiff can't be specified at the same time. If state is
// set, message execution will only use the data in the given state. Otherwise
-// if statDiff is set, all diff will be applied first and then execute the call
+// if stateDiff is set, all diff will be applied first and then execute the call
// message.
type OverrideAccount struct {
Nonce *hexutil.Uint64 `json:"nonce"`
@@ -1127,7 +1142,7 @@ type OverrideAccount struct {
type StateOverride map[common.Address]OverrideAccount
// Apply overrides the fields of specified accounts into the given state.
-func (diff *StateOverride) Apply(state *state.StateDB) error {
+func (diff *StateOverride) Apply(statedb *state.StateDB) error {
if diff == nil {
return nil
}
@@ -1135,15 +1150,16 @@ func (diff *StateOverride) Apply(state *state.StateDB) error {
for addr, account := range *diff {
// Override account nonce.
if account.Nonce != nil {
- state.SetNonce(addr, uint64(*account.Nonce))
+ statedb.SetNonce(addr, uint64(*account.Nonce))
}
// Override account(contract) code.
if account.Code != nil {
- state.SetCode(addr, *account.Code)
+ statedb.SetCode(addr, *account.Code)
}
// Override account balance.
if account.Balance != nil {
- state.SetBalance(addr, (*big.Int)(*account.Balance))
+ u256Balance, _ := uint256.FromBig((*big.Int)(*account.Balance))
+ statedb.SetBalance(addr, u256Balance, tracing.BalanceChangeUnspecified)
}
if account.State != nil && account.StateDiff != nil {
@@ -1151,20 +1167,19 @@ func (diff *StateOverride) Apply(state *state.StateDB) error {
}
// Replace entire state if caller requires.
if account.State != nil {
- state.SetStorage(addr, *account.State)
+ statedb.SetStorage(addr, *account.State)
}
// Apply state diff into specified accounts.
if account.StateDiff != nil {
for key, value := range *account.StateDiff {
- state.SetState(addr, key, value)
+ statedb.SetState(addr, key, value)
}
}
}
// Now finalize the changes. Finalize is normally performed between transactions.
// By using finalize, the overrides are semantically behaving as
// if they were created in a transaction just before the tracing occur.
- state.Finalise(false)
-
+ statedb.Finalise(false)
return nil
}
@@ -1272,14 +1287,14 @@ func doCallWithState(ctx context.Context, b Backend, args TransactionArgs, heade
defer cancel()
// Get a new instance of the EVM.
- msg, err := args.ToMessage(globalGasCap, header.BaseFee)
- if err != nil {
- return nil, err
- }
blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil)
if blockOverrides != nil {
blockOverrides.Apply(&blockCtx)
}
+ if err := args.CallDefaults(globalGasCap, blockCtx.BaseFee, b.ChainConfig().ChainID); err != nil {
+ return nil, err
+ }
+ msg := args.ToMessage(blockCtx.BaseFee)
evm := b.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true}, &blockCtx)
// Wait for the context to be done and cancel the evm. Even if the
@@ -1338,46 +1353,14 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash
return doCall(ctx, b, args, state, header, overrides, blockOverrides, timeout, globalGasCap)
}
-func newRevertError(revert []byte) *revertError {
- err := vm.ErrExecutionReverted
-
- reason, errUnpack := abi.UnpackRevert(revert)
- if errUnpack == nil {
- err = fmt.Errorf("%w: %v", vm.ErrExecutionReverted, reason)
- }
-
- return &revertError{
- error: err,
- reason: hexutil.Encode(revert),
- }
-}
-
-// revertError is an API error that encompasses an EVM revertal with JSON error
-// code and a binary data blob.
-type revertError struct {
- error
- reason string // revert reason hex encoded
-}
-
-// ErrorCode returns the JSON error code for a revertal.
-// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal
-func (e *revertError) ErrorCode() int {
- return 3
-}
-
-// ErrorData returns the hex encoded revert reason.
-func (e *revertError) ErrorData() interface{} {
- return e.reason
-}
-
// Call executes the given transaction on the state for the given block number.
//
// Additionally, the caller can specify a batch of contract for fields overriding.
//
// Note, this function doesn't make and changes in the state/blockchain and is
// useful to execute and retrieve values.
-func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides) (hexutil.Bytes, error) {
- return s.CallWithState(ctx, args, *blockNrOrHash, nil, overrides, blockOverrides)
+func (api *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides) (hexutil.Bytes, error) {
+ return api.CallWithState(ctx, args, blockNrOrHash, nil, overrides, blockOverrides)
}
// CallWithState executes the given transaction on the given state for
@@ -1389,14 +1372,18 @@ func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrO
//
// Note, this function doesn't make and changes in the state/blockchain and is
// useful to execute and retrieve values.
-func (s *BlockChainAPI) CallWithState(ctx context.Context, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, state *state.StateDB, overrides *StateOverride, blockOverrides *BlockOverrides) (hexutil.Bytes, error) {
- result, err := DoCall(ctx, s.b, args, blockNrOrHash, state, overrides, blockOverrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap())
+func (api *BlockChainAPI) CallWithState(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, state *state.StateDB, overrides *StateOverride, blockOverrides *BlockOverrides) (hexutil.Bytes, error) {
+ if blockNrOrHash == nil {
+ latest := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
+ blockNrOrHash = &latest
+ }
+ result, err := DoCall(ctx, api.b, args, *blockNrOrHash, state, overrides, blockOverrides, api.b.RPCEVMTimeout(), api.b.RPCGasCap())
if err != nil {
return nil, err
}
- if int(s.b.RPCRpcReturnDataLimit()) > 0 && len(result.ReturnData) > int(s.b.RPCRpcReturnDataLimit()) {
- return nil, fmt.Errorf("call returned result of length %d exceeding limit %d", len(result.ReturnData), int(s.b.RPCRpcReturnDataLimit()))
+ if int(api.b.RPCRpcReturnDataLimit()) > 0 && len(result.ReturnData) > int(api.b.RPCRpcReturnDataLimit()) {
+ return nil, fmt.Errorf("call returned result of length %d exceeding limit %d", len(result.ReturnData), int(api.b.RPCRpcReturnDataLimit()))
}
// If the result contains a revert reason, try to unpack and return it.
@@ -1428,11 +1415,17 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
State: state,
ErrorRatio: estimateGasErrorRatio,
}
- // Run the gas estimation andwrap any revertals into a custom return
- call, err := args.ToMessage(gasCap, header.BaseFee)
- if err != nil {
+ // Set any required transaction default, but make sure the gas cap itself is not messed with
+ // if it was not specified in the original argument list.
+ if args.Gas == nil {
+ args.Gas = new(hexutil.Uint64)
+ }
+ if err := args.CallDefaults(gasCap, header.BaseFee, b.ChainConfig().ChainID); err != nil {
return 0, err
}
+ call := args.ToMessage(header.BaseFee)
+
+ // Run the gas estimation and wrap any revertals into a custom return
estimate, revert, err := gasestimator.Estimate(ctx, call, opts, gasCap)
if err != nil {
if len(revert) > 0 {
@@ -1448,12 +1441,13 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
// returns error if the transaction would revert or if there are unexpected failures. The returned
// value is capped by both `args.Gas` (if non-nil & non-zero) and the backend's RPCGasCap
// configuration (if non-zero).
-func (s *BlockChainAPI) EstimateGas(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *StateOverride) (hexutil.Uint64, error) {
+// Note: Required blob gas is not computed in this method.
+func (api *BlockChainAPI) EstimateGas(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *StateOverride) (hexutil.Uint64, error) {
bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
if blockNrOrHash != nil {
bNrOrHash = *blockNrOrHash
}
- return DoEstimateGas(ctx, s.b, args, bNrOrHash, overrides, s.b.RPCGasCap())
+ return DoEstimateGas(ctx, api.b, args, bNrOrHash, overrides, api.b.RPCGasCap())
}
// ExecutionResult groups all structured logs emitted by the EVM
@@ -1604,18 +1598,18 @@ func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool, config *param
// rpcMarshalHeader uses the generalized output filler, then adds the total difficulty field, which requires
// a `BlockchainAPI`.
-func (s *BlockChainAPI) rpcMarshalHeader(ctx context.Context, header *types.Header) map[string]interface{} {
+func (api *BlockChainAPI) rpcMarshalHeader(ctx context.Context, header *types.Header) map[string]interface{} {
fields := RPCMarshalHeader(header)
- fields["totalDifficulty"] = (*hexutil.Big)(s.b.GetTd(ctx, header.Hash()))
+ fields["totalDifficulty"] = (*hexutil.Big)(api.b.GetTd(ctx, header.Hash()))
return fields
}
// rpcMarshalBlock uses the generalized output filler, then adds the total difficulty field, which requires
// a `BlockchainAPI`.
-func (s *BlockChainAPI) rpcMarshalBlock(ctx context.Context, b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
- fields := RPCMarshalBlock(b, inclTx, fullTx, s.b.ChainConfig(), s.b.ChainDb())
+func (api *BlockChainAPI) rpcMarshalBlock(ctx context.Context, b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
+ fields := RPCMarshalBlock(b, inclTx, fullTx, api.b.ChainConfig(), api.b.ChainDb())
if inclTx {
- fields["totalDifficulty"] = (*hexutil.Big)(s.b.GetTd(ctx, b.Hash()))
+ fields["totalDifficulty"] = (*hexutil.Big)(api.b.GetTd(ctx, b.Hash()))
}
return fields, nil
}
@@ -1813,13 +1807,12 @@ type accessListResult struct {
// CreateAccessList creates an EIP-2930 type AccessList for the given transaction.
// Reexec and BlockNrOrHash can be specified to create the accessList on top of a certain state.
-func (s *BlockChainAPI) CreateAccessList(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash) (*accessListResult, error) {
- bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
+func (api *BlockChainAPI) CreateAccessList(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash) (*accessListResult, error) {
+ bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
if blockNrOrHash != nil {
bNrOrHash = *blockNrOrHash
}
-
- acl, gasUsed, vmerr, err := AccessList(ctx, s.b, bNrOrHash, args)
+ acl, gasUsed, vmerr, err := AccessList(ctx, api.b, bNrOrHash, args)
if err != nil {
return nil, err
}
@@ -1841,14 +1834,9 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
if db == nil || err != nil {
return nil, 0, nil, err
}
- // If the gas amount is not set, default to RPC gas cap.
- if args.Gas == nil {
- tmp := hexutil.Uint64(b.RPCGasCap())
- args.Gas = &tmp
- }
// Ensure any missing fields are filled, extract the recipient and input data
- if err := args.setDefaults(ctx, b); err != nil {
+ if err := args.setDefaults(ctx, b, true); err != nil {
return nil, 0, nil, err
}
@@ -1858,8 +1846,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
} else {
to = crypto.CreateAddress(args.from(), uint64(*args.Nonce))
}
-
- isPostMerge := header.Difficulty.Cmp(common.Big0) == 0
+ isPostMerge := header.Difficulty.Sign() == 0
// Retrieve the precompiles since they don't need to be added to the access list
precompiles := vm.ActivePrecompiles(b.ChainConfig().Rules(header.Number, isPostMerge, header.Time))
@@ -1870,6 +1857,9 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
}
for {
+ if err := ctx.Err(); err != nil {
+ return nil, 0, nil, err
+ }
// Retrieve the current access list to expand
accessList := prevTracer.AccessList()
log.Trace("Creating access list", "input", accessList)
@@ -1878,19 +1868,15 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
statedb := db.Copy()
// Set the accesslist to the last al
args.AccessList = &accessList
-
- msg, err := args.ToMessage(b.RPCGasCap(), header.BaseFee)
- if err != nil {
- return nil, 0, nil, err
- }
+ msg := args.ToMessage(header.BaseFee)
// Apply the transaction with the access list tracer
tracer := logger.NewAccessListTracer(accessList, args.from(), to, precompiles)
- config := vm.Config{Tracer: tracer, NoBaseFee: true}
+ config := vm.Config{Tracer: tracer.Hooks(), NoBaseFee: true}
vmenv := b.GetEVM(ctx, msg, statedb, header, &config, nil)
res, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.GasLimit), context.Background())
if err != nil {
- return nil, 0, nil, fmt.Errorf("failed to apply transaction: %v err: %v", args.toTransaction().Hash(), err)
+ return nil, 0, nil, fmt.Errorf("failed to apply transaction: %v err: %v", args.ToTransaction().Hash(), err)
}
if tracer.Equal(prevTracer) {
@@ -1909,7 +1895,7 @@ type TransactionAPI struct {
}
// returns block transactions along with state-sync transaction if present
-// nolint: unparam
+// nolint : unused
func (api *TransactionAPI) getAllBlockTransactions(ctx context.Context, block *types.Block) (types.Transactions, bool) {
txs := block.Transactions()
@@ -1937,11 +1923,10 @@ func NewTransactionAPI(b Backend, nonceLock *AddrLocker) *TransactionAPI {
}
// GetBlockTransactionCountByNumber returns the number of transactions in the block with the given block number.
-func (s *TransactionAPI) GetBlockTransactionCountByNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint {
- if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
- txs, _ := s.getAllBlockTransactions(ctx, block)
+func (api *TransactionAPI) GetBlockTransactionCountByNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint {
+ if block, _ := api.b.BlockByNumber(ctx, blockNr); block != nil {
+ txs, _ := api.getAllBlockTransactions(ctx, block)
n := hexutil.Uint(len(txs))
-
return &n
}
@@ -1949,11 +1934,10 @@ func (s *TransactionAPI) GetBlockTransactionCountByNumber(ctx context.Context, b
}
// GetBlockTransactionCountByHash returns the number of transactions in the block with the given hash.
-func (s *TransactionAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint {
- if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil {
- txs, _ := s.getAllBlockTransactions(ctx, block)
+func (api *TransactionAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint {
+ if block, _ := api.b.BlockByHash(ctx, blockHash); block != nil {
+ txs, _ := api.getAllBlockTransactions(ctx, block)
n := hexutil.Uint(len(txs))
-
return &n
}
@@ -1961,26 +1945,26 @@ func (s *TransactionAPI) GetBlockTransactionCountByHash(ctx context.Context, blo
}
// GetTransactionByBlockNumberAndIndex returns the transaction for the given block number and index.
-func (s *TransactionAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) *RPCTransaction {
- if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
- return newRPCTransactionFromBlockIndex(block, uint64(index), s.b.ChainConfig(), s.b.ChainDb())
+func (api *TransactionAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) *RPCTransaction {
+ if block, _ := api.b.BlockByNumber(ctx, blockNr); block != nil {
+ return newRPCTransactionFromBlockIndex(block, uint64(index), api.b.ChainConfig(), api.b.ChainDb())
}
return nil
}
// GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index.
-func (s *TransactionAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) *RPCTransaction {
- if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil {
- return newRPCTransactionFromBlockIndex(block, uint64(index), s.b.ChainConfig(), s.b.ChainDb())
+func (api *TransactionAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) *RPCTransaction {
+ if block, _ := api.b.BlockByHash(ctx, blockHash); block != nil {
+ return newRPCTransactionFromBlockIndex(block, uint64(index), api.b.ChainConfig(), api.b.ChainDb())
}
return nil
}
// GetRawTransactionByBlockNumberAndIndex returns the bytes of the transaction for the given block number and index.
-func (s *TransactionAPI) GetRawTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) hexutil.Bytes {
- if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
+func (api *TransactionAPI) GetRawTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) hexutil.Bytes {
+ if block, _ := api.b.BlockByNumber(ctx, blockNr); block != nil {
return newRPCRawTransactionFromBlockIndex(block, uint64(index))
}
@@ -1988,8 +1972,8 @@ func (s *TransactionAPI) GetRawTransactionByBlockNumberAndIndex(ctx context.Cont
}
// GetRawTransactionByBlockHashAndIndex returns the bytes of the transaction for the given block hash and index.
-func (s *TransactionAPI) GetRawTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) hexutil.Bytes {
- if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil {
+func (api *TransactionAPI) GetRawTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) hexutil.Bytes {
+ if block, _ := api.b.BlockByHash(ctx, blockHash); block != nil {
return newRPCRawTransactionFromBlockIndex(block, uint64(index))
}
@@ -1997,10 +1981,10 @@ func (s *TransactionAPI) GetRawTransactionByBlockHashAndIndex(ctx context.Contex
}
// GetTransactionCount returns the number of transactions the given address has sent for the given block number
-func (s *TransactionAPI) GetTransactionCount(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Uint64, error) {
+func (api *TransactionAPI) GetTransactionCount(ctx context.Context, address common.Address, blockNrOrHash rpc.BlockNumberOrHash) (*hexutil.Uint64, error) {
// Ask transaction pool for the nonce which includes pending transactions
if blockNr, ok := blockNrOrHash.Number(); ok && blockNr == rpc.PendingBlockNumber {
- nonce, err := s.b.GetPoolNonce(ctx, address)
+ nonce, err := api.b.GetPoolNonce(ctx, address)
if err != nil {
return nil, err
}
@@ -2008,7 +1992,7 @@ func (s *TransactionAPI) GetTransactionCount(ctx context.Context, address common
return (*hexutil.Uint64)(&nonce), nil
}
// Resolve block number and use its state to ask for the nonce
- state, _, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
+ state, _, err := api.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
if state == nil || err != nil {
return nil, err
}
@@ -2019,17 +2003,18 @@ func (s *TransactionAPI) GetTransactionCount(ctx context.Context, address common
}
// GetTransactionByHash returns the transaction for the given hash
-func (s *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (*RPCTransaction, error) {
+func (api *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (*RPCTransaction, error) {
borTx := false
// Try to return an already finalized transaction
- tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash)
+ found, tx, blockHash, blockNumber, index, err := api.b.GetTransaction(ctx, hash)
if err != nil {
return nil, err
}
+
// fetch bor block tx if necessary
- if tx == nil {
- if tx, blockHash, blockNumber, index, err = s.b.GetBorBlockTransaction(ctx, hash); err != nil {
+ if !found {
+ if tx, blockHash, blockNumber, index, err = api.b.GetBorBlockTransaction(ctx, hash); err != nil {
return nil, err
}
@@ -2037,12 +2022,12 @@ func (s *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.H
}
if tx != nil {
- header, err := s.b.HeaderByHash(ctx, blockHash)
+ header, err := api.b.HeaderByHash(ctx, blockHash)
if err != nil {
return nil, err
}
- resultTx := newRPCTransaction(tx, blockHash, blockNumber, header.Time, index, header.BaseFee, s.b.ChainConfig())
+ resultTx := newRPCTransaction(tx, blockHash, blockNumber, header.Time, index, header.BaseFee, api.b.ChainConfig())
if borTx {
// newRPCTransaction calculates hash based on RLP of the transaction data.
@@ -2054,8 +2039,8 @@ func (s *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.H
return resultTx, nil
}
// No finalized transaction, try to retrieve it from the pool
- if tx := s.b.GetPoolTransaction(hash); tx != nil {
- return NewRPCPendingTransaction(tx, s.b.CurrentHeader(), s.b.ChainConfig()), nil
+ if tx := api.b.GetPoolTransaction(hash); tx != nil {
+ return NewRPCPendingTransaction(tx, api.b.CurrentHeader(), api.b.ChainConfig()), nil
}
// Transaction unknown, return as such
@@ -2063,35 +2048,33 @@ func (s *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.H
}
// GetRawTransactionByHash returns the bytes of the transaction for the given hash.
-func (s *TransactionAPI) GetRawTransactionByHash(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
+func (api *TransactionAPI) GetRawTransactionByHash(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
// Retrieve a finalized transaction, or a pooled otherwise
- tx, _, _, _, err := s.b.GetTransaction(ctx, hash)
- if err != nil {
- return nil, err
- }
-
- if tx == nil {
- if tx = s.b.GetPoolTransaction(hash); tx == nil {
- // Transaction not found anywhere, abort
+ found, tx, _, _, _, err := api.b.GetTransaction(ctx, hash)
+ if !found {
+ if tx = api.b.GetPoolTransaction(hash); tx != nil {
+ return tx.MarshalBinary()
+ }
+ if err == nil {
return nil, nil
}
+
+ return nil, NewTxIndexingError()
}
- // Serialize to RLP and return
return tx.MarshalBinary()
}
// GetTransactionReceipt returns the transaction receipt for the given transaction hash.
-func (s *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) {
+func (api *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common.Hash) (map[string]interface{}, error) {
borTx := false
- tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash)
+ found, tx, blockHash, blockNumber, index, err := api.b.GetTransaction(ctx, hash)
if err != nil {
- // When the transaction doesn't exist, the RPC method should return JSON null
- // as per specification.
- return nil, nil
+ return nil, NewTxIndexingError() // transaction is not fully indexed
}
- if tx == nil {
- tx, blockHash, blockNumber, index = rawdb.ReadBorTransaction(s.b.ChainDb(), hash)
+
+ if !found {
+ tx, blockHash, blockNumber, index = rawdb.ReadBorTransaction(api.b.ChainDb(), hash)
borTx = true
}
@@ -2103,9 +2086,9 @@ func (s *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common.
if borTx {
// Fetch bor block receipt
- receipt = rawdb.ReadBorReceipt(s.b.ChainDb(), blockHash, blockNumber, s.b.ChainConfig())
+ receipt = rawdb.ReadBorReceipt(api.b.ChainDb(), blockHash, blockNumber, api.b.ChainConfig())
} else {
- receipts, err := s.b.GetReceipts(ctx, blockHash)
+ receipts, err := api.b.GetReceipts(ctx, blockHash)
if err != nil {
return nil, err
}
@@ -2117,13 +2100,13 @@ func (s *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common.
receipt = receipts[index]
}
- header, err := s.b.HeaderByHash(ctx, blockHash)
+ header, err := api.b.HeaderByHash(ctx, blockHash)
if err != nil {
return nil, err
}
// Derive the sender.
- signer := types.MakeSigner(s.b.ChainConfig(), header.Number, header.Time)
+ signer := types.MakeSigner(api.b.ChainConfig(), header.Number, header.Time)
return marshalReceipt(receipt, blockHash, blockNumber, signer, tx, int(index), borTx), nil
}
@@ -2183,16 +2166,16 @@ func marshalReceipt(receipt *types.Receipt, blockHash common.Hash, blockNumber u
}
// sign is a helper function that signs a transaction with the private key of the given address.
-func (s *TransactionAPI) sign(addr common.Address, tx *types.Transaction) (*types.Transaction, error) {
+func (api *TransactionAPI) sign(addr common.Address, tx *types.Transaction) (*types.Transaction, error) {
// Look up the wallet containing the requested signer
account := accounts.Account{Address: addr}
- wallet, err := s.b.AccountManager().Find(account)
+ wallet, err := api.b.AccountManager().Find(account)
if err != nil {
return nil, err
}
// Request the wallet to sign the transaction
- return wallet.SignTx(account, tx, s.b.ChainConfig().ChainID)
+ return wallet.SignTx(account, tx, api.b.ChainConfig().ChainID)
}
// SubmitTransaction is a helper function that submits tx to txPool and logs a message.
@@ -2232,11 +2215,11 @@ func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (c
// SendTransaction creates a transaction for the given argument, sign it and submit it to the
// transaction pool.
-func (s *TransactionAPI) SendTransaction(ctx context.Context, args TransactionArgs) (common.Hash, error) {
+func (api *TransactionAPI) SendTransaction(ctx context.Context, args TransactionArgs) (common.Hash, error) {
// Look up the wallet containing the requested signer
account := accounts.Account{Address: args.from()}
- wallet, err := s.b.AccountManager().Find(account)
+ wallet, err := api.b.AccountManager().Find(account)
if err != nil {
return common.Hash{}, err
}
@@ -2244,36 +2227,39 @@ func (s *TransactionAPI) SendTransaction(ctx context.Context, args TransactionAr
if args.Nonce == nil {
// Hold the mutex around signing to prevent concurrent assignment of
// the same nonce to multiple accounts.
- s.nonceLock.LockAddr(args.from())
- defer s.nonceLock.UnlockAddr(args.from())
+ api.nonceLock.LockAddr(args.from())
+ defer api.nonceLock.UnlockAddr(args.from())
+ }
+ if args.IsEIP4844() {
+ return common.Hash{}, errBlobTxNotSupported
}
// Set some sanity defaults and terminate on failure
- if err := args.setDefaults(ctx, s.b); err != nil {
+ if err := args.setDefaults(ctx, api.b, false); err != nil {
return common.Hash{}, err
}
// Assemble the transaction and sign with the wallet
- tx := args.toTransaction()
+ tx := args.ToTransaction()
- signed, err := wallet.SignTx(account, tx, s.b.ChainConfig().ChainID)
+ signed, err := wallet.SignTx(account, tx, api.b.ChainConfig().ChainID)
if err != nil {
return common.Hash{}, err
}
-
- return SubmitTransaction(ctx, s.b, signed)
+ return SubmitTransaction(ctx, api.b, signed)
}
// FillTransaction fills the defaults (nonce, gas, gasPrice or 1559 fields)
// on a given unsigned transaction, and returns it to the caller for further
// processing (signing + broadcast).
-func (s *TransactionAPI) FillTransaction(ctx context.Context, args TransactionArgs) (*SignTransactionResult, error) {
+func (api *TransactionAPI) FillTransaction(ctx context.Context, args TransactionArgs) (*SignTransactionResult, error) {
+ args.blobSidecarAllowed = true
+
// Set some sanity defaults and terminate on failure
- if err := args.setDefaults(ctx, s.b); err != nil {
+ if err := args.setDefaults(ctx, api.b, false); err != nil {
return nil, err
}
// Assemble the transaction and obtain rlp
- tx := args.toTransaction()
-
+ tx := args.ToTransaction()
data, err := tx.MarshalBinary()
if err != nil {
return nil, err
@@ -2284,13 +2270,12 @@ func (s *TransactionAPI) FillTransaction(ctx context.Context, args TransactionAr
// SendRawTransaction will add the signed transaction to the transaction pool.
// The sender is responsible for signing the transaction and using the correct nonce.
-func (s *TransactionAPI) SendRawTransaction(ctx context.Context, input hexutil.Bytes) (common.Hash, error) {
+func (api *TransactionAPI) SendRawTransaction(ctx context.Context, input hexutil.Bytes) (common.Hash, error) {
tx := new(types.Transaction)
if err := tx.UnmarshalBinary(input); err != nil {
return common.Hash{}, err
}
-
- return SubmitTransaction(ctx, s.b, tx)
+ return SubmitTransaction(ctx, api.b, tx)
}
// Sign calculates an ECDSA signature for:
@@ -2302,11 +2287,11 @@ func (s *TransactionAPI) SendRawTransaction(ctx context.Context, input hexutil.B
// The account associated with addr must be unlocked.
//
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign
-func (s *TransactionAPI) Sign(addr common.Address, data hexutil.Bytes) (hexutil.Bytes, error) {
+func (api *TransactionAPI) Sign(addr common.Address, data hexutil.Bytes) (hexutil.Bytes, error) {
// Look up the wallet containing the requested signer
account := accounts.Account{Address: addr}
- wallet, err := s.b.AccountManager().Find(account)
+ wallet, err := api.b.AccountManager().Find(account)
if err != nil {
return nil, err
}
@@ -2328,7 +2313,9 @@ type SignTransactionResult struct {
// SignTransaction will sign the given transaction with the from account.
// The node needs to have the private key of the account corresponding with
// the given from address and it needs to be unlocked.
-func (s *TransactionAPI) SignTransaction(ctx context.Context, args TransactionArgs) (*SignTransactionResult, error) {
+func (api *TransactionAPI) SignTransaction(ctx context.Context, args TransactionArgs) (*SignTransactionResult, error) {
+ args.blobSidecarAllowed = true
+
if args.Gas == nil {
return nil, errors.New("gas not specified")
}
@@ -2336,25 +2323,31 @@ func (s *TransactionAPI) SignTransaction(ctx context.Context, args TransactionAr
if args.GasPrice == nil && (args.MaxPriorityFeePerGas == nil || args.MaxFeePerGas == nil) {
return nil, errors.New("missing gasPrice or maxFeePerGas/maxPriorityFeePerGas")
}
-
if args.Nonce == nil {
return nil, errors.New("nonce not specified")
}
-
- if err := args.setDefaults(ctx, s.b); err != nil {
+ if err := args.setDefaults(ctx, api.b, false); err != nil {
return nil, err
}
// Before actually sign the transaction, ensure the transaction fee is reasonable.
- tx := args.toTransaction()
- if err := checkTxFee(tx.GasPrice(), tx.Gas(), s.b.RPCTxFeeCap()); err != nil {
+ tx := args.ToTransaction()
+ if err := checkTxFee(tx.GasPrice(), tx.Gas(), api.b.RPCTxFeeCap()); err != nil {
return nil, err
}
-
- signed, err := s.sign(args.from(), tx)
+ signed, err := api.sign(args.from(), tx)
if err != nil {
return nil, err
}
-
+ // If the transaction-to-sign was a blob transaction, then the signed one
+ // no longer retains the blobs, only the blob hashes. In this step, we need
+ // to put back the blob(s).
+ if args.IsEIP4844() {
+ signed = signed.WithBlobTxSidecar(&types.BlobTxSidecar{
+ Blobs: args.Blobs,
+ Commitments: args.Commitments,
+ Proofs: args.Proofs,
+ })
+ }
data, err := signed.MarshalBinary()
if err != nil {
return nil, err
@@ -2365,27 +2358,25 @@ func (s *TransactionAPI) SignTransaction(ctx context.Context, args TransactionAr
// PendingTransactions returns the transactions that are in the transaction pool
// and have a from address that is one of the accounts this node manages.
-func (s *TransactionAPI) PendingTransactions() ([]*RPCTransaction, error) {
- pending, err := s.b.GetPoolTransactions()
+func (api *TransactionAPI) PendingTransactions() ([]*RPCTransaction, error) {
+ pending, err := api.b.GetPoolTransactions()
if err != nil {
return nil, err
}
accounts := make(map[common.Address]struct{})
-
- for _, wallet := range s.b.AccountManager().Wallets() {
+ for _, wallet := range api.b.AccountManager().Wallets() {
for _, account := range wallet.Accounts() {
accounts[account.Address] = struct{}{}
}
}
-
- curHeader := s.b.CurrentHeader()
+ curHeader := api.b.CurrentHeader()
transactions := make([]*RPCTransaction, 0, len(pending))
for _, tx := range pending {
- from, _ := types.Sender(s.signer, tx)
+ from, _ := types.Sender(api.signer, tx)
if _, exists := accounts[from]; exists {
- transactions = append(transactions, NewRPCPendingTransaction(tx, curHeader, s.b.ChainConfig()))
+ transactions = append(transactions, NewRPCPendingTransaction(tx, curHeader, api.b.ChainConfig()))
}
}
@@ -2394,17 +2385,14 @@ func (s *TransactionAPI) PendingTransactions() ([]*RPCTransaction, error) {
// Resend accepts an existing transaction and a new gas price and limit. It will remove
// the given transaction from the pool and reinsert it with the new gas price and limit.
-// nolint:gocognit
-func (s *TransactionAPI) Resend(ctx context.Context, sendArgs TransactionArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error) {
+func (api *TransactionAPI) Resend(ctx context.Context, sendArgs TransactionArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error) {
if sendArgs.Nonce == nil {
return common.Hash{}, errors.New("missing transaction nonce in transaction spec")
}
-
- if err := sendArgs.setDefaults(ctx, s.b); err != nil {
+ if err := sendArgs.setDefaults(ctx, api.b, false); err != nil {
return common.Hash{}, err
}
-
- matchTx := sendArgs.toTransaction()
+ matchTx := sendArgs.ToTransaction()
// Before replacing the old transaction, ensure the _new_ transaction fee is reasonable.
var price = matchTx.GasPrice()
@@ -2416,25 +2404,24 @@ func (s *TransactionAPI) Resend(ctx context.Context, sendArgs TransactionArgs, g
if gasLimit != nil {
gas = uint64(*gasLimit)
}
-
- if err := checkTxFee(price, gas, s.b.RPCTxFeeCap()); err != nil {
+ if err := checkTxFee(price, gas, api.b.RPCTxFeeCap()); err != nil {
return common.Hash{}, err
}
// Iterate the pending list for replacement
- pending, err := s.b.GetPoolTransactions()
+ pending, err := api.b.GetPoolTransactions()
if err != nil {
return common.Hash{}, err
}
for _, p := range pending {
- wantSigHash := s.signer.Hash(matchTx)
- pFrom, err := types.Sender(s.signer, p)
+ wantSigHash := api.signer.Hash(matchTx)
+ pFrom, err := types.Sender(api.signer, p)
- if err != nil && (s.b.UnprotectedAllowed() && err == types.ErrInvalidChainId) {
+ if err != nil && (api.b.UnprotectedAllowed() && err == types.ErrInvalidChainId) {
err = nil
}
- if err == nil && pFrom == sendArgs.from() && s.signer.Hash(p) == wantSigHash {
+ if err == nil && pFrom == sendArgs.from() && api.signer.Hash(p) == wantSigHash {
// Match. Re-sign and send the transaction.
if gasPrice != nil && (*big.Int)(gasPrice).Sign() != 0 {
sendArgs.GasPrice = gasPrice
@@ -2444,12 +2431,12 @@ func (s *TransactionAPI) Resend(ctx context.Context, sendArgs TransactionArgs, g
sendArgs.Gas = gasLimit
}
- signedTx, err := s.sign(sendArgs.from(), sendArgs.toTransaction())
+ signedTx, err := api.sign(sendArgs.from(), sendArgs.ToTransaction())
if err != nil {
return common.Hash{}, err
}
- if err = s.b.SendTx(ctx, signedTx); err != nil {
+ if err = api.b.SendTx(ctx, signedTx); err != nil {
return common.Hash{}, err
}
@@ -2549,18 +2536,17 @@ func (api *DebugAPI) GetRawReceipts(ctx context.Context, blockNrOrHash rpc.Block
}
// GetRawTransaction returns the bytes of the transaction for the given hash.
-func (s *DebugAPI) GetRawTransaction(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
+func (api *DebugAPI) GetRawTransaction(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
// Retrieve a finalized transaction, or a pooled otherwise
- tx, _, _, _, err := s.b.GetTransaction(ctx, hash)
- if err != nil {
- return nil, err
- }
-
- if tx == nil {
- if tx = s.b.GetPoolTransaction(hash); tx == nil {
- // Transaction not found anywhere, abort
+ found, tx, _, _, _, err := api.b.GetTransaction(ctx, hash)
+ if !found {
+ if tx = api.b.GetPoolTransaction(hash); tx != nil {
+ return tx.MarshalBinary()
+ }
+ if err == nil {
return nil, nil
}
+ return nil, NewTxIndexingError()
}
return tx.MarshalBinary()
@@ -2577,8 +2563,8 @@ func (api *DebugAPI) PrintBlock(ctx context.Context, number uint64) (string, err
}
// ChaindbProperty returns leveldb properties of the key-value database.
-func (api *DebugAPI) ChaindbProperty(property string) (string, error) {
- return api.b.ChainDb().Stat(property)
+func (api *DebugAPI) ChaindbProperty() (string, error) {
+ return api.b.ChainDb().Stat()
}
// ChaindbCompact flattens the entire key-value database into a single level,
@@ -2641,18 +2627,18 @@ func NewNetAPI(net *p2p.Server, networkVersion uint64) *NetAPI {
}
// Listening returns an indication if the node is listening for network connections.
-func (s *NetAPI) Listening() bool {
+func (api *NetAPI) Listening() bool {
return true // always listening
}
// PeerCount returns the number of connected peers
-func (s *NetAPI) PeerCount() hexutil.Uint {
- return hexutil.Uint(s.net.PeerCount())
+func (api *NetAPI) PeerCount() hexutil.Uint {
+ return hexutil.Uint(api.net.PeerCount())
}
// Version returns the current ethereum protocol version.
-func (s *NetAPI) Version() string {
- return fmt.Sprintf("%d", s.networkVersion)
+func (api *NetAPI) Version() string {
+ return fmt.Sprintf("%d", api.networkVersion)
}
// checkTxFee is an internal function used to check whether the fee of
diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go
index 082032f54a..07e5761951 100644
--- a/internal/ethapi/api_test.go
+++ b/internal/ethapi/api_test.go
@@ -17,6 +17,7 @@
package ethapi
import (
+ "bytes"
"context"
"crypto/ecdsa"
"encoding/json"
@@ -26,11 +27,16 @@ import (
"os"
"path/filepath"
"reflect"
+ "slices"
"testing"
"time"
+ "github.com/holiman/uint256"
+ "github.com/stretchr/testify/require"
+
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts"
+ "github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus"
@@ -48,9 +54,6 @@ import (
"github.com/ethereum/go-ethereum/internal/blocktest"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
- "github.com/holiman/uint256"
- "github.com/stretchr/testify/require"
- "golang.org/x/exp/slices"
)
func testTransactionMarshal(t *testing.T, tests []txData, config *params.ChainConfig) {
@@ -403,10 +406,30 @@ func allBlobTxs(addr common.Address, config *params.ChainConfig) []txData {
}
}
+func newTestAccountManager(t *testing.T) (*accounts.Manager, accounts.Account) {
+ var (
+ dir = t.TempDir()
+ am = accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: true})
+ b = keystore.NewKeyStore(dir, 2, 1)
+ testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ )
+ acc, err := b.ImportECDSA(testKey, "")
+ if err != nil {
+ t.Fatalf("failed to create test account: %v", err)
+ }
+ if err := b.Unlock(acc, ""); err != nil {
+ t.Fatalf("failed to unlock account: %v\n", err)
+ }
+ am.AddBackend(b)
+ return am, acc
+}
+
type testBackend struct {
db ethdb.Database
chain *core.BlockChain
pending *types.Block
+ accman *accounts.Manager
+ acc accounts.Account
}
func newTestBackend(t *testing.T, n int, gspec *core.Genesis, engine consensus.Engine, generator func(i int, b *core.BlockGen)) *testBackend {
@@ -419,6 +442,8 @@ func newTestBackend(t *testing.T, n int, gspec *core.Genesis, engine consensus.E
TrieDirtyDisabled: true, // Archive mode
}
)
+ accman, acc := newTestAccountManager(t)
+ // gspec.Alloc[acc.Address] = types.Account{Balance: big.NewInt(params.Ether)}
// Generate blocks for testing
db, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, n, generator)
txlookupLimit := uint64(0)
@@ -430,7 +455,7 @@ func newTestBackend(t *testing.T, n int, gspec *core.Genesis, engine consensus.E
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
}
- backend := &testBackend{db: db, chain: chain}
+ backend := &testBackend{db: db, chain: chain, accman: accman, acc: acc}
return backend
}
@@ -442,17 +467,18 @@ func (b testBackend) SyncProgress() ethereum.SyncProgress { return ethereum.Sync
func (b testBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
return big.NewInt(0), nil
}
-func (b testBackend) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, error) {
- return nil, nil, nil, nil, nil
-}
-func (b testBackend) ChainDb() ethdb.Database { return b.db }
-func (b testBackend) AccountManager() *accounts.Manager { return nil }
-func (b testBackend) ExtRPCEnabled() bool { return false }
-func (b testBackend) RPCGasCap() uint64 { return 10000000 }
-func (b testBackend) RPCEVMTimeout() time.Duration { return time.Second }
-func (b testBackend) RPCTxFeeCap() float64 { return 0 }
-func (b testBackend) UnprotectedAllowed() bool { return false }
-func (b testBackend) SetHead(number uint64) {}
+func (b testBackend) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, []*big.Int, []float64, error) {
+ return nil, nil, nil, nil, nil, nil, nil
+}
+func (b testBackend) BlobBaseFee(ctx context.Context) *big.Int { return new(big.Int) }
+func (b testBackend) ChainDb() ethdb.Database { return b.db }
+func (b testBackend) AccountManager() *accounts.Manager { return b.accman }
+func (b testBackend) ExtRPCEnabled() bool { return false }
+func (b testBackend) RPCGasCap() uint64 { return 10000000 }
+func (b testBackend) RPCEVMTimeout() time.Duration { return time.Second }
+func (b testBackend) RPCTxFeeCap() float64 { return 0 }
+func (b testBackend) UnprotectedAllowed() bool { return false }
+func (b testBackend) SetHead(number uint64) {}
func (b testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
if number == rpc.LatestBlockNumber {
return b.chain.CurrentBlock(), nil
@@ -521,7 +547,7 @@ func (b testBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOr
}
panic("only implemented for number")
}
-func (b testBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) { panic("implement me") }
+func (b testBackend) Pending() (*types.Block, types.Receipts, *state.StateDB) { panic("implement me") }
func (b testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
header, err := b.HeaderByHash(ctx, hash)
if header == nil || err != nil {
@@ -559,14 +585,14 @@ func (b testBackend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) even
func (b testBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
panic("implement me")
}
-func (b testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
+func (b testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.db, txHash)
- return tx, blockHash, blockNumber, index, nil
+ return true, tx, blockHash, blockNumber, index, nil
}
func (b testBackend) GetPoolTransactions() (types.Transactions, error) { panic("implement me") }
func (b testBackend) GetPoolTransaction(txHash common.Hash) *types.Transaction { panic("implement me") }
func (b testBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
- panic("implement me")
+ return 0, nil
}
func (b testBackend) Stats() (pending int, queued int) { panic("implement me") }
func (b testBackend) TxPoolContent() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) {
@@ -676,8 +702,8 @@ func TestEstimateGas(t *testing.T) {
var (
accounts = newAccounts(2)
genesis = &core.Genesis{
- Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Config: params.MergedTestChainConfig,
+ Alloc: types.GenesisAlloc{
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
},
@@ -686,12 +712,13 @@ func TestEstimateGas(t *testing.T) {
signer = types.HomesteadSigner{}
randomAccounts = newAccounts(2)
)
- api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, ethash.NewFaker(), func(i int, b *core.BlockGen) {
+ api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
// Transfer from account[0] to account[1]
// value: 1000 wei
// fee: 0 wei
tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &accounts[1].addr, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: b.BaseFee(), Data: nil}), signer, accounts[0].key)
b.AddTx(tx)
+ b.SetPoS()
}))
var testSuite = []struct {
blockNumber rpc.BlockNumber
@@ -791,6 +818,18 @@ func TestEstimateGas(t *testing.T) {
expectErr: nil,
want: 67595,
},
+ // Blobs should have no effect on gas estimate
+ {
+ blockNumber: rpc.LatestBlockNumber,
+ call: TransactionArgs{
+ From: &accounts[0].addr,
+ To: &accounts[1].addr,
+ Value: (*hexutil.Big)(big.NewInt(1)),
+ BlobHashes: []common.Hash{{0x01, 0x22}},
+ BlobFeeCap: (*hexutil.Big)(big.NewInt(1)),
+ },
+ want: 21000,
+ },
}
for i, tc := range testSuite {
result, err := api.EstimateGas(context.Background(), tc.call, &rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides)
@@ -820,8 +859,8 @@ func TestCall(t *testing.T) {
var (
accounts = newAccounts(3)
genesis = &core.Genesis{
- Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Config: params.MergedTestChainConfig,
+ Alloc: types.GenesisAlloc{
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
@@ -830,12 +869,13 @@ func TestCall(t *testing.T) {
genBlocks = 10
signer = types.HomesteadSigner{}
)
- api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, ethash.NewFaker(), func(i int, b *core.BlockGen) {
+ api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
// Transfer from account[0] to account[1]
// value: 1000 wei
// fee: 0 wei
tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &accounts[1].addr, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: b.BaseFee(), Data: nil}), signer, accounts[0].key)
b.AddTx(tx)
+ b.SetPoS()
}))
randomAccounts := newAccounts(3)
var testSuite = []struct {
@@ -957,6 +997,33 @@ func TestCall(t *testing.T) {
blockOverrides: BlockOverrides{Number: (*hexutil.Big)(big.NewInt(11))},
want: "0x000000000000000000000000000000000000000000000000000000000000000b",
},
+ // Invalid blob tx
+ {
+ blockNumber: rpc.LatestBlockNumber,
+ call: TransactionArgs{
+ From: &accounts[1].addr,
+ Input: &hexutil.Bytes{0x00},
+ BlobHashes: []common.Hash{},
+ },
+ expectErr: core.ErrBlobTxCreate,
+ },
+ // BOR Doens't support blob tx
+ // BLOBHASH opcode
+ // {
+ // blockNumber: rpc.LatestBlockNumber,
+ // call: TransactionArgs{
+ // From: &accounts[1].addr,
+ // To: &randomAccounts[2].addr,
+ // BlobHashes: []common.Hash{{0x01, 0x22}},
+ // BlobFeeCap: (*hexutil.Big)(big.NewInt(1)),
+ // },
+ // overrides: StateOverride{
+ // randomAccounts[2].addr: {
+ // Code: hex2Bytes("60004960005260206000f3"),
+ // },
+ // },
+ // want: "0x0122000000000000000000000000000000000000000000000000000000000000",
+ // },
}
for i, tc := range testSuite {
result, err := api.Call(context.Background(), tc.call, &rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides, &tc.blockOverrides)
@@ -983,6 +1050,326 @@ func TestCall(t *testing.T) {
}
}
+func TestSignTransaction(t *testing.T) {
+ t.Parallel()
+ // Initialize test accounts
+ var (
+ key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
+ to = crypto.PubkeyToAddress(key.PublicKey)
+ genesis = &core.Genesis{
+ Config: params.MergedTestChainConfig,
+ Alloc: types.GenesisAlloc{},
+ }
+ )
+ _, acc := newTestAccountManager(t)
+ genesis.Alloc[acc.Address] = types.Account{Balance: big.NewInt(params.Ether)}
+ b := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
+ b.SetPoS()
+ })
+ api := NewTransactionAPI(b, nil)
+ res, err := api.FillTransaction(context.Background(), TransactionArgs{
+ From: &b.acc.Address,
+ To: &to,
+ Value: (*hexutil.Big)(big.NewInt(1)),
+ })
+ if err != nil {
+ t.Fatalf("failed to fill tx defaults: %v\n", err)
+ }
+
+ res, err = api.SignTransaction(context.Background(), argsFromTransaction(res.Tx, b.acc.Address))
+ if err != nil {
+ t.Fatalf("failed to sign tx: %v\n", err)
+ }
+ tx, err := json.Marshal(res.Tx)
+ if err != nil {
+ t.Fatal(err)
+ }
+ expect := `{"type":"0x2","chainId":"0x1","nonce":"0x0","to":"0x703c4b2bd70c169f5717101caee543299fc946c7","gas":"0x5208","gasPrice":null,"maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x684ee180","value":"0x1","input":"0x","accessList":[],"v":"0x0","r":"0x8fabeb142d585dd9247f459f7e6fe77e2520c88d50ba5d220da1533cea8b34e1","s":"0x582dd68b21aef36ba23f34e49607329c20d981d30404daf749077f5606785ce7","yParity":"0x0","hash":"0x93927839207cfbec395da84b8a2bc38b7b65d2cb2819e9fef1f091f5b1d4cc8f"}`
+ if !bytes.Equal(tx, []byte(expect)) {
+ t.Errorf("result mismatch. Have:\n%s\nWant:\n%s\n", tx, expect)
+ }
+}
+
+// func TestSignBlobTransaction(t *testing.T) {
+// t.Parallel()
+// // Initialize test accounts
+// var (
+// key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
+// to = crypto.PubkeyToAddress(key.PublicKey)
+// genesis = &core.Genesis{
+// Config: params.MergedTestChainConfig,
+// Alloc: types.GenesisAlloc{},
+// }
+// )
+// b := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
+// b.SetPoS()
+// })
+// api := NewTransactionAPI(b, nil)
+// res, err := api.FillTransaction(context.Background(), TransactionArgs{
+// From: &b.acc.Address,
+// To: &to,
+// Value: (*hexutil.Big)(big.NewInt(1)),
+// BlobHashes: []common.Hash{{0x01, 0x22}},
+// })
+// if err != nil {
+// t.Fatalf("failed to fill tx defaults: %v\n", err)
+// }
+
+// _, err = api.SignTransaction(context.Background(), argsFromTransaction(res.Tx, b.acc.Address))
+// if err != nil {
+// t.Fatalf("should not fail on blob transaction")
+// }
+// }
+
+// func TestSendBlobTransaction(t *testing.T) {
+// t.Parallel()
+// // Initialize test accounts
+// var (
+// key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
+// to = crypto.PubkeyToAddress(key.PublicKey)
+// genesis = &core.Genesis{
+// Config: params.MergedTestChainConfig,
+// Alloc: types.GenesisAlloc{},
+// }
+// )
+// b := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
+// b.SetPoS()
+// })
+// api := NewTransactionAPI(b, nil)
+// res, err := api.FillTransaction(context.Background(), TransactionArgs{
+// From: &b.acc.Address,
+// To: &to,
+// Value: (*hexutil.Big)(big.NewInt(1)),
+// BlobHashes: []common.Hash{{0x01, 0x22}},
+// })
+// if err != nil {
+// t.Fatalf("failed to fill tx defaults: %v\n", err)
+// }
+
+// _, err = api.SendTransaction(context.Background(), argsFromTransaction(res.Tx, b.acc.Address))
+// if err == nil {
+// t.Errorf("sending tx should have failed")
+// } else if !errors.Is(err, errBlobTxNotSupported) {
+// t.Errorf("unexpected error. Have %v, want %v\n", err, errBlobTxNotSupported)
+// }
+// }
+
+// func TestFillBlobTransaction(t *testing.T) {
+// t.Parallel()
+// // Initialize test accounts
+// var (
+// key, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
+// to = crypto.PubkeyToAddress(key.PublicKey)
+// genesis = &core.Genesis{
+// Config: params.MergedTestChainConfig,
+// Alloc: types.GenesisAlloc{},
+// }
+// emptyBlob = new(kzg4844.Blob)
+// emptyBlobs = []kzg4844.Blob{*emptyBlob}
+// emptyBlobCommit, _ = kzg4844.BlobToCommitment(emptyBlob)
+// emptyBlobProof, _ = kzg4844.ComputeBlobProof(emptyBlob, emptyBlobCommit)
+// emptyBlobHash common.Hash = kzg4844.CalcBlobHashV1(sha256.New(), &emptyBlobCommit)
+// )
+// b := newTestBackend(t, 1, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
+// b.SetPoS()
+// })
+// api := NewTransactionAPI(b, nil)
+// type result struct {
+// Hashes []common.Hash
+// Sidecar *types.BlobTxSidecar
+// }
+// suite := []struct {
+// name string
+// args TransactionArgs
+// err string
+// want *result
+// }{
+// {
+// name: "TestInvalidParamsCombination1",
+// args: TransactionArgs{
+// From: &b.acc.Address,
+// To: &to,
+// Value: (*hexutil.Big)(big.NewInt(1)),
+// Blobs: []kzg4844.Blob{{}},
+// Proofs: []kzg4844.Proof{{}},
+// },
+// err: `blob proofs provided while commitments were not`,
+// },
+// {
+// name: "TestInvalidParamsCombination2",
+// args: TransactionArgs{
+// From: &b.acc.Address,
+// To: &to,
+// Value: (*hexutil.Big)(big.NewInt(1)),
+// Blobs: []kzg4844.Blob{{}},
+// Commitments: []kzg4844.Commitment{{}},
+// },
+// err: `blob commitments provided while proofs were not`,
+// },
+// {
+// name: "TestInvalidParamsCount1",
+// args: TransactionArgs{
+// From: &b.acc.Address,
+// To: &to,
+// Value: (*hexutil.Big)(big.NewInt(1)),
+// Blobs: []kzg4844.Blob{{}},
+// Commitments: []kzg4844.Commitment{{}, {}},
+// Proofs: []kzg4844.Proof{{}, {}},
+// },
+// err: `number of blobs and commitments mismatch (have=2, want=1)`,
+// },
+// {
+// name: "TestInvalidParamsCount2",
+// args: TransactionArgs{
+// From: &b.acc.Address,
+// To: &to,
+// Value: (*hexutil.Big)(big.NewInt(1)),
+// Blobs: []kzg4844.Blob{{}, {}},
+// Commitments: []kzg4844.Commitment{{}, {}},
+// Proofs: []kzg4844.Proof{{}},
+// },
+// err: `number of blobs and proofs mismatch (have=1, want=2)`,
+// },
+// {
+// name: "TestInvalidProofVerification",
+// args: TransactionArgs{
+// From: &b.acc.Address,
+// To: &to,
+// Value: (*hexutil.Big)(big.NewInt(1)),
+// Blobs: []kzg4844.Blob{{}, {}},
+// Commitments: []kzg4844.Commitment{{}, {}},
+// Proofs: []kzg4844.Proof{{}, {}},
+// },
+// err: `failed to verify blob proof: short buffer`,
+// },
+// {
+// name: "TestGenerateBlobHashes",
+// args: TransactionArgs{
+// From: &b.acc.Address,
+// To: &to,
+// Value: (*hexutil.Big)(big.NewInt(1)),
+// Blobs: emptyBlobs,
+// Commitments: []kzg4844.Commitment{emptyBlobCommit},
+// Proofs: []kzg4844.Proof{emptyBlobProof},
+// },
+// want: &result{
+// Hashes: []common.Hash{emptyBlobHash},
+// Sidecar: &types.BlobTxSidecar{
+// Blobs: emptyBlobs,
+// Commitments: []kzg4844.Commitment{emptyBlobCommit},
+// Proofs: []kzg4844.Proof{emptyBlobProof},
+// },
+// },
+// },
+// {
+// name: "TestValidBlobHashes",
+// args: TransactionArgs{
+// From: &b.acc.Address,
+// To: &to,
+// Value: (*hexutil.Big)(big.NewInt(1)),
+// BlobHashes: []common.Hash{emptyBlobHash},
+// Blobs: emptyBlobs,
+// Commitments: []kzg4844.Commitment{emptyBlobCommit},
+// Proofs: []kzg4844.Proof{emptyBlobProof},
+// },
+// want: &result{
+// Hashes: []common.Hash{emptyBlobHash},
+// Sidecar: &types.BlobTxSidecar{
+// Blobs: emptyBlobs,
+// Commitments: []kzg4844.Commitment{emptyBlobCommit},
+// Proofs: []kzg4844.Proof{emptyBlobProof},
+// },
+// },
+// },
+// {
+// name: "TestInvalidBlobHashes",
+// args: TransactionArgs{
+// From: &b.acc.Address,
+// To: &to,
+// Value: (*hexutil.Big)(big.NewInt(1)),
+// BlobHashes: []common.Hash{{0x01, 0x22}},
+// Blobs: emptyBlobs,
+// Commitments: []kzg4844.Commitment{emptyBlobCommit},
+// Proofs: []kzg4844.Proof{emptyBlobProof},
+// },
+// err: fmt.Sprintf("blob hash verification failed (have=%s, want=%s)", common.Hash{0x01, 0x22}, emptyBlobHash),
+// },
+// {
+// name: "TestGenerateBlobProofs",
+// args: TransactionArgs{
+// From: &b.acc.Address,
+// To: &to,
+// Value: (*hexutil.Big)(big.NewInt(1)),
+// Blobs: emptyBlobs,
+// },
+// want: &result{
+// Hashes: []common.Hash{emptyBlobHash},
+// Sidecar: &types.BlobTxSidecar{
+// Blobs: emptyBlobs,
+// Commitments: []kzg4844.Commitment{emptyBlobCommit},
+// Proofs: []kzg4844.Proof{emptyBlobProof},
+// },
+// },
+// },
+// }
+// for _, tc := range suite {
+// t.Run(tc.name, func(t *testing.T) {
+// res, err := api.FillTransaction(context.Background(), tc.args)
+// if len(tc.err) > 0 {
+// if err == nil {
+// t.Fatalf("missing error. want: %s", tc.err)
+// } else if err.Error() != tc.err {
+// t.Fatalf("error mismatch. want: %s, have: %s", tc.err, err.Error())
+// }
+// return
+// }
+// if err != nil && len(tc.err) == 0 {
+// t.Fatalf("expected no error. have: %s", err)
+// }
+// if res == nil {
+// t.Fatal("result missing")
+// }
+// want, err := json.Marshal(tc.want)
+// if err != nil {
+// t.Fatalf("failed to encode expected: %v", err)
+// }
+// have, err := json.Marshal(result{Hashes: res.Tx.BlobHashes(), Sidecar: res.Tx.BlobTxSidecar()})
+// if err != nil {
+// t.Fatalf("failed to encode computed sidecar: %v", err)
+// }
+// if !bytes.Equal(have, want) {
+// t.Errorf("blob sidecar mismatch. Have: %s, want: %s", have, want)
+// }
+// })
+// }
+// }
+
+func argsFromTransaction(tx *types.Transaction, from common.Address) TransactionArgs {
+ var (
+ gas = tx.Gas()
+ nonce = tx.Nonce()
+ input = tx.Data()
+ accessList *types.AccessList
+ )
+ if acl := tx.AccessList(); acl != nil {
+ accessList = &acl
+ }
+ return TransactionArgs{
+ From: &from,
+ To: tx.To(),
+ Gas: (*hexutil.Uint64)(&gas),
+ MaxFeePerGas: (*hexutil.Big)(tx.GasFeeCap()),
+ MaxPriorityFeePerGas: (*hexutil.Big)(tx.GasTipCap()),
+ Value: (*hexutil.Big)(tx.Value()),
+ Nonce: (*hexutil.Uint64)(&nonce),
+ Input: (*hexutil.Bytes)(&input),
+ ChainID: (*hexutil.Big)(tx.ChainId()),
+ AccessList: accessList,
+ BlobFeeCap: (*hexutil.Big)(tx.BlobGasFeeCap()),
+ BlobHashes: tx.BlobHashes(),
+ }
+}
+
type account struct {
key *ecdsa.PrivateKey
addr common.Address
@@ -1038,7 +1425,7 @@ func TestRPCMarshalBlock(t *testing.T) {
}
txs = append(txs, tx)
}
- block := types.NewBlock(&types.Header{Number: big.NewInt(100)}, txs, nil, nil, blocktest.NewHasher())
+ block := types.NewBlock(&types.Header{Number: big.NewInt(100)}, &types.Body{Transactions: txs}, nil, blocktest.NewHasher())
var testSuite = []struct {
inclTx bool
@@ -1218,6 +1605,10 @@ func TestRPCMarshalBlock(t *testing.T) {
}
func TestRPCGetBlockOrHeader(t *testing.T) {
+ // Note: Upstream (geth) tests have a different genesis hash as it has a different
+ // state root hash due to allocating balance separately in test backend. Because
+ // that is commented out in bor, we use the old genesis hash in the test files.
+
t.Parallel()
// Initialize test accounts
@@ -1228,7 +1619,7 @@ func TestRPCGetBlockOrHeader(t *testing.T) {
acc2Addr = crypto.PubkeyToAddress(acc2Key.PublicKey)
genesis = &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
acc1Addr: {Balance: big.NewInt(params.Ether)},
acc2Addr: {Balance: big.NewInt(params.Ether)},
},
@@ -1249,7 +1640,7 @@ func TestRPCGetBlockOrHeader(t *testing.T) {
Address: common.Address{0x12, 0x34},
Amount: 10,
}
- pending = types.NewBlockWithWithdrawals(&types.Header{Number: big.NewInt(11), Time: 42}, []*types.Transaction{tx}, nil, nil, []*types.Withdrawal{withdrawal}, blocktest.NewHasher())
+ pending = types.NewBlock(&types.Header{Number: big.NewInt(11), Time: 42}, &types.Body{Transactions: types.Transactions{tx}, Withdrawals: types.Withdrawals{withdrawal}}, nil, blocktest.NewHasher())
)
backend := newTestBackend(t, genBlocks, genesis, ethash.NewFaker(), func(i int, b *core.BlockGen) {
// Transfer from account[0] to account[1]
@@ -1427,6 +1818,11 @@ func TestRPCGetBlockOrHeader(t *testing.T) {
fullTx: true,
file: "hash-pending-fullTx",
},
+ // 26. safe block
+ {
+ blockNumber: rpc.SafeBlockNumber,
+ file: "tag-safe",
+ },
}
for i, tt := range testSuite {
@@ -1473,6 +1869,7 @@ func TestRPCGetBlockOrHeader(t *testing.T) {
func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Hash) {
config := *params.TestChainConfig
+
config.ShanghaiBlock = big.NewInt(0)
config.CancunBlock = big.NewInt(0)
@@ -1486,7 +1883,7 @@ func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Ha
Config: &config,
ExcessBlobGas: new(uint64),
BlobGasUsed: new(uint64),
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
acc1Addr: {Balance: big.NewInt(params.Ether)},
acc2Addr: {Balance: big.NewInt(params.Ether)},
// // SPDX-License-Identifier: GPL-3.0
@@ -1509,11 +1906,13 @@ func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Ha
// Set the terminal total difficulty in the config
genesis.Config.TerminalTotalDifficulty = big.NewInt(0)
genesis.Config.TerminalTotalDifficultyPassed = true
+
backend := newTestBackend(t, genBlocks, genesis, beacon.New(ethash.NewFaker()), func(i int, b *core.BlockGen) {
var (
tx *types.Transaction
err error
)
+ b.SetPoS()
switch i {
case 0:
// transfer 1000wei
@@ -1562,7 +1961,6 @@ func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Ha
b.AddTx(tx)
txHashes[i] = tx.Hash()
}
- b.SetPoS()
})
return backend, txHashes
}
@@ -1664,7 +2062,7 @@ func TestRPCGetTransactionReceiptsByBlock(t *testing.T) {
contract = common.HexToAddress("0000000000000000000000000000000000031ec7")
genesis = &core.Genesis{
Config: params.TestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
acc1Addr: {Balance: big.NewInt(params.Ether)},
acc2Addr: {Balance: big.NewInt(params.Ether)},
contract: {Balance: big.NewInt(params.Ether), Code: common.FromHex("0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a9059cbb14610030575b600080fd5b61004a6004803603810190610045919061016a565b610060565b60405161005791906101c5565b60405180910390f35b60008273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516100bf91906101ef565b60405180910390a36001905092915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610101826100d6565b9050919050565b610111816100f6565b811461011c57600080fd5b50565b60008135905061012e81610108565b92915050565b6000819050919050565b61014781610134565b811461015257600080fd5b50565b6000813590506101648161013e565b92915050565b60008060408385031215610181576101806100d1565b5b600061018f8582860161011f565b92505060206101a085828601610155565b9150509250929050565b60008115159050919050565b6101bf816101aa565b82525050565b60006020820190506101da60008301846101b6565b92915050565b6101e981610134565b82525050565b600060208201905061020460008301846101e0565b9291505056fea2646970667358221220b469033f4b77b9565ee84e0a2f04d496b18160d26034d54f9487e57788fd36d564736f6c63430008120033")},
diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go
index 59facc5108..ab1100245f 100644
--- a/internal/ethapi/backend.go
+++ b/internal/ethapi/backend.go
@@ -44,7 +44,8 @@ type Backend interface {
SyncProgress() ethereum.SyncProgress
SuggestGasTipCap(ctx context.Context) (*big.Int, error)
- FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, error)
+ FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, []*big.Int, []float64, error)
+ BlobBaseFee(ctx context.Context) *big.Int
ChainDb() ethdb.Database
AccountManager() *accounts.Manager
ExtRPCEnabled() bool
@@ -66,7 +67,7 @@ type Backend interface {
BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error)
StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error)
StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error)
- PendingBlockAndReceipts() (*types.Block, types.Receipts)
+ Pending() (*types.Block, types.Receipts, *state.StateDB)
GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
GetTd(ctx context.Context, hash common.Hash) *big.Int
GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM
@@ -76,7 +77,7 @@ type Backend interface {
// Transaction pool API
SendTx(ctx context.Context, signedTx *types.Transaction) error
- GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
+ GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error)
GetPoolTransactions() (types.Transactions, error)
GetPoolTransaction(txHash common.Hash) *types.Transaction
GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error)
diff --git a/internal/ethapi/bor_api.go b/internal/ethapi/bor_api.go
index 80ed986166..7443b1f19b 100644
--- a/internal/ethapi/bor_api.go
+++ b/internal/ethapi/bor_api.go
@@ -67,7 +67,7 @@ func NewBorAPI(b Backend) *BorAPI {
// SendRawTransactionConditional will add the signed transaction to the transaction pool.
// The sender/bundler is responsible for signing the transaction
-func (api *BorAPI) SendRawTransactionConditional(ctx context.Context, input hexutil.Bytes, options types.OptionsAA4337) (common.Hash, error) {
+func (api *BorAPI) SendRawTransactionConditional(ctx context.Context, input hexutil.Bytes, options types.OptionsPIP15) (common.Hash, error) {
tx := new(types.Transaction)
if err := tx.UnmarshalBinary(input); err != nil {
return common.Hash{}, err
@@ -81,12 +81,12 @@ func (api *BorAPI) SendRawTransactionConditional(ctx context.Context, input hexu
}
// check block number range
- if err := currentHeader.ValidateBlockNumberOptions4337(options.BlockNumberMin, options.BlockNumberMax); err != nil {
+ if err := currentHeader.ValidateBlockNumberOptionsPIP15(options.BlockNumberMin, options.BlockNumberMax); err != nil {
return common.Hash{}, &rpc.OptionsValidateError{Message: "out of block range. err: " + err.Error()}
}
// check timestamp range
- if err := currentHeader.ValidateTimestampOptions4337(options.TimestampMin, options.TimestampMax); err != nil {
+ if err := currentHeader.ValidateTimestampOptionsPIP15(options.TimestampMin, options.TimestampMax); err != nil {
return common.Hash{}, &rpc.OptionsValidateError{Message: "out of time range. err: " + err.Error()}
}
diff --git a/internal/ethapi/errors.go b/internal/ethapi/errors.go
new file mode 100644
index 0000000000..b5e668a805
--- /dev/null
+++ b/internal/ethapi/errors.go
@@ -0,0 +1,78 @@
+// Copyright 2024 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 ethapi
+
+import (
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/core/vm"
+)
+
+// revertError is an API error that encompasses an EVM revert with JSON error
+// code and a binary data blob.
+type revertError struct {
+ error
+ reason string // revert reason hex encoded
+}
+
+// ErrorCode returns the JSON error code for a revert.
+// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal
+func (e *revertError) ErrorCode() int {
+ return 3
+}
+
+// ErrorData returns the hex encoded revert reason.
+func (e *revertError) ErrorData() interface{} {
+ return e.reason
+}
+
+// newRevertError creates a revertError instance with the provided revert data.
+func newRevertError(revert []byte) *revertError {
+ err := vm.ErrExecutionReverted
+
+ reason, errUnpack := abi.UnpackRevert(revert)
+ if errUnpack == nil {
+ err = fmt.Errorf("%w: %v", vm.ErrExecutionReverted, reason)
+ }
+ return &revertError{
+ error: err,
+ reason: hexutil.Encode(revert),
+ }
+}
+
+// TxIndexingError is an API error that indicates the transaction indexing is not
+// fully finished yet with JSON error code and a binary data blob.
+type TxIndexingError struct{}
+
+// NewTxIndexingError creates a TxIndexingError instance.
+func NewTxIndexingError() *TxIndexingError { return &TxIndexingError{} }
+
+// Error implement error interface, returning the error message.
+func (e *TxIndexingError) Error() string {
+ return "transaction indexing is in progress"
+}
+
+// ErrorCode returns the JSON error code for a revert.
+// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal
+func (e *TxIndexingError) ErrorCode() int {
+ return -32000 // to be decided
+}
+
+// ErrorData returns the hex encoded revert reason.
+func (e *TxIndexingError) ErrorData() interface{} { return "transaction indexing is in progress" }
diff --git a/internal/ethapi/testdata/eth_getBlockByNumber-tag-safe.json b/internal/ethapi/testdata/eth_getBlockByNumber-tag-safe.json
new file mode 100644
index 0000000000..ec747fa47d
--- /dev/null
+++ b/internal/ethapi/testdata/eth_getBlockByNumber-tag-safe.json
@@ -0,0 +1 @@
+null
\ No newline at end of file
diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go
index 0408bc2690..a06a499b98 100644
--- a/internal/ethapi/transaction_args.go
+++ b/internal/ethapi/transaction_args.go
@@ -19,6 +19,7 @@ package ethapi
import (
"bytes"
"context"
+ "crypto/sha256"
"errors"
"fmt"
"math/big"
@@ -26,10 +27,18 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
+ "github.com/holiman/uint256"
+)
+
+var (
+ maxBlobsPerTransaction = params.MaxBlobGasPerBlock / params.BlobTxBlobGasPerBlob
)
// TransactionArgs represents the arguments to construct a new transaction
@@ -53,6 +62,18 @@ type TransactionArgs struct {
// Introduced by AccessListTxType transaction.
AccessList *types.AccessList `json:"accessList,omitempty"`
ChainID *hexutil.Big `json:"chainId,omitempty"`
+
+ // For BlobTxType
+ BlobFeeCap *hexutil.Big `json:"maxFeePerBlobGas"`
+ BlobHashes []common.Hash `json:"blobVersionedHashes,omitempty"`
+
+ // For BlobTxType transactions with blob sidecar
+ Blobs []kzg4844.Blob `json:"blobs"`
+ Commitments []kzg4844.Commitment `json:"commitments"`
+ Proofs []kzg4844.Proof `json:"proofs"`
+
+ // This configures whether blobs are allowed to be passed.
+ blobSidecarAllowed bool
}
// from retrieves the transaction sender address.
@@ -78,7 +99,10 @@ func (args *TransactionArgs) data() []byte {
}
// setDefaults fills in default values for unspecified tx fields.
-func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
+func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend, skipGasEstimation bool) error {
+ if err := args.setBlobTxSidecar(ctx); err != nil {
+ return err
+ }
if err := args.setFeeDefaults(ctx, b); err != nil {
return err
}
@@ -100,35 +124,59 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
return errors.New(`both "data" and "input" are set and not equal. Please use "input" to pass transaction call data`)
}
- if args.To == nil && len(args.data()) == 0 {
- return errors.New(`contract creation without any data provided`)
+ // BlobTx fields
+ if args.BlobHashes != nil && len(args.BlobHashes) == 0 {
+ return errors.New(`need at least 1 blob for a blob transaction`)
+ }
+ if args.BlobHashes != nil && len(args.BlobHashes) > maxBlobsPerTransaction {
+ return fmt.Errorf(`too many blobs in transaction (have=%d, max=%d)`, len(args.BlobHashes), maxBlobsPerTransaction)
}
- // Estimate the gas usage if necessary.
- if args.Gas == nil {
- // These fields are immutable during the estimation, safe to
- // pass the pointer directly.
- data := args.data()
- callArgs := TransactionArgs{
- From: args.From,
- To: args.To,
- GasPrice: args.GasPrice,
- MaxFeePerGas: args.MaxFeePerGas,
- MaxPriorityFeePerGas: args.MaxPriorityFeePerGas,
- Value: args.Value,
- Data: (*hexutil.Bytes)(&data),
- AccessList: args.AccessList,
- }
-
- pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
- estimated, err := DoEstimateGas(ctx, b, callArgs, pendingBlockNr, nil, b.RPCGasCap())
- if err != nil {
- return err
+ // create check
+ if args.To == nil {
+ if args.BlobHashes != nil {
+ return errors.New(`missing "to" in blob transaction`)
}
+ if len(args.data()) == 0 {
+ return errors.New(`contract creation without any data provided`)
+ }
+ }
+
+ if args.Gas == nil {
+ if skipGasEstimation { // Skip gas usage estimation if a precise gas limit is not critical, e.g., in non-transaction calls.
+ gas := hexutil.Uint64(b.RPCGasCap())
+ if gas == 0 {
+ gas = hexutil.Uint64(math.MaxUint64 / 2)
+ }
+ args.Gas = &gas
+ } else { // Estimate the gas usage otherwise.
+ // These fields are immutable during the estimation, safe to
+ // pass the pointer directly.
+ data := args.data()
+ callArgs := TransactionArgs{
+ From: args.From,
+ To: args.To,
+ GasPrice: args.GasPrice,
+ MaxFeePerGas: args.MaxFeePerGas,
+ MaxPriorityFeePerGas: args.MaxPriorityFeePerGas,
+ Value: args.Value,
+ Data: (*hexutil.Bytes)(&data),
+ AccessList: args.AccessList,
+ BlobFeeCap: args.BlobFeeCap,
+ BlobHashes: args.BlobHashes,
+ }
- args.Gas = &estimated
- log.Trace("Estimate gas usage automatically", "gas", args.Gas)
+ latestBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
+ estimated, err := DoEstimateGas(ctx, b, callArgs, latestBlockNr, nil, b.RPCGasCap())
+ if err != nil {
+ return err
+ }
+
+ args.Gas = &estimated
+ log.Trace("Estimate gas usage automatically", "gas", args.Gas)
+ }
}
+
// If chain id is provided, ensure it matches the local chain id. Otherwise, set the local
// chain id as the default.
want := b.ChainConfig().ChainID
@@ -145,25 +193,46 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
// setFeeDefaults fills in default fee values for unspecified tx fields.
func (args *TransactionArgs) setFeeDefaults(ctx context.Context, b Backend) error {
+ head := b.CurrentHeader()
+ // Sanity check the EIP-4844 fee parameters.
+ if args.BlobFeeCap != nil && args.BlobFeeCap.ToInt().Sign() == 0 {
+ return errors.New("maxFeePerBlobGas, if specified, must be non-zero")
+ }
+ if err := args.setCancunFeeDefaults(ctx, head, b); err != nil {
+ return err
+ }
// If both gasPrice and at least one of the EIP-1559 fee parameters are specified, error.
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
return errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
}
- // If the tx has completely specified a fee mechanism, no default is needed. This allows users
- // who are not yet synced past London to get defaults for other tx values. See
- // https://github.com/ethereum/go-ethereum/pull/23274 for more information.
+ // If the tx has completely specified a fee mechanism, no default is needed.
+ // This allows users who are not yet synced past London to get defaults for
+ // other tx values. See https://github.com/ethereum/go-ethereum/pull/23274
+ // for more information.
eip1559ParamsSet := args.MaxFeePerGas != nil && args.MaxPriorityFeePerGas != nil
- if (args.GasPrice != nil && !eip1559ParamsSet) || (args.GasPrice == nil && eip1559ParamsSet) {
- // Sanity check the EIP-1559 fee parameters if present.
- if args.GasPrice == nil && args.MaxFeePerGas.ToInt().Cmp(args.MaxPriorityFeePerGas.ToInt()) < 0 {
+ // Sanity check the EIP-1559 fee parameters if present.
+ if args.GasPrice == nil && eip1559ParamsSet {
+ if args.MaxFeePerGas.ToInt().Sign() == 0 {
+ return errors.New("maxFeePerGas must be non-zero")
+ }
+ if args.MaxFeePerGas.ToInt().Cmp(args.MaxPriorityFeePerGas.ToInt()) < 0 {
return fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", args.MaxFeePerGas, args.MaxPriorityFeePerGas)
}
+ return nil // No need to set anything, user already set MaxFeePerGas and MaxPriorityFeePerGas
+ }
- return nil
+ // Sanity check the non-EIP-1559 fee parameters.
+ isLondon := b.ChainConfig().IsLondon(head.Number)
+ if args.GasPrice != nil && !eip1559ParamsSet {
+ // Zero gas-price is not allowed after London fork
+ if args.GasPrice.ToInt().Sign() == 0 && isLondon {
+ return errors.New("gasPrice must be non-zero after london fork")
+ }
+ return nil // No need to set anything, user already set GasPrice
}
+
// Now attempt to fill in default value depending on whether London is active or not.
- head := b.CurrentHeader()
- if b.ChainConfig().IsLondon(head.Number) {
+ if isLondon {
// London is active, set maxPriorityFeePerGas and maxFeePerGas.
if err := args.setLondonFeeDefaults(ctx, head, b); err != nil {
return err
@@ -184,6 +253,25 @@ func (args *TransactionArgs) setFeeDefaults(ctx context.Context, b Backend) erro
return nil
}
+// setCancunFeeDefaults fills in reasonable default fee values for unspecified fields.
+func (args *TransactionArgs) setCancunFeeDefaults(ctx context.Context, head *types.Header, b Backend) error {
+ // Set maxFeePerBlobGas if it is missing.
+ if args.BlobHashes != nil && args.BlobFeeCap == nil {
+ var excessBlobGas uint64
+ if head.ExcessBlobGas != nil {
+ excessBlobGas = *head.ExcessBlobGas
+ }
+ // ExcessBlobGas must be set for a Cancun block.
+ blobBaseFee := eip4844.CalcBlobFee(excessBlobGas)
+ // Set the max fee to be 2 times larger than the previous block's blob base fee.
+ // The additional slack allows the tx to not become invalidated if the base
+ // fee is rising.
+ val := new(big.Int).Mul(blobBaseFee, big.NewInt(2))
+ args.BlobFeeCap = (*hexutil.Big)(val)
+ }
+ return nil
+}
+
// setLondonFeeDefaults fills in reasonable default fee values for unspecified fields.
func (args *TransactionArgs) setLondonFeeDefaults(ctx context.Context, head *types.Header, b Backend) error {
// Set maxPriorityFeePerGas if it is missing.
@@ -214,36 +302,150 @@ func (args *TransactionArgs) setLondonFeeDefaults(ctx context.Context, head *typ
return nil
}
-// ToMessage converts the transaction arguments to the Message type used by the
-// core evm. This method is used in calls and traces that do not require a real
-// live transaction.
-func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*core.Message, error) {
- // Reject invalid combinations of pre- and post-1559 fee styles
- if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
- return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
+// setBlobTxSidecar adds the blob tx
+func (args *TransactionArgs) setBlobTxSidecar(ctx context.Context) error {
+ // No blobs, we're done.
+ if args.Blobs == nil {
+ return nil
}
- // Set sender address or use zero address if none specified.
- addr := args.from()
+ // Passing blobs is not allowed in all contexts, only in specific methods.
+ if !args.blobSidecarAllowed {
+ return errors.New(`"blobs" is not supported for this RPC method`)
+ }
- // Gas set for system calls
- systemCallGas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
+ n := len(args.Blobs)
+ // Assume user provides either only blobs (w/o hashes), or
+ // blobs together with commitments and proofs.
+ if args.Commitments == nil && args.Proofs != nil {
+ return errors.New(`blob proofs provided while commitments were not`)
+ } else if args.Commitments != nil && args.Proofs == nil {
+ return errors.New(`blob commitments provided while proofs were not`)
+ }
- // Set default gas & gas price if none were set
- gas := globalGasCap
- if gas == 0 {
- gas = uint64(math.MaxUint64 / 2)
+ // len(blobs) == len(commitments) == len(proofs) == len(hashes)
+ if args.Commitments != nil && len(args.Commitments) != n {
+ return fmt.Errorf("number of blobs and commitments mismatch (have=%d, want=%d)", len(args.Commitments), n)
+ }
+ if args.Proofs != nil && len(args.Proofs) != n {
+ return fmt.Errorf("number of blobs and proofs mismatch (have=%d, want=%d)", len(args.Proofs), n)
+ }
+ if args.BlobHashes != nil && len(args.BlobHashes) != n {
+ return fmt.Errorf("number of blobs and hashes mismatch (have=%d, want=%d)", len(args.BlobHashes), n)
}
- if args.Gas != nil && *args.Gas != systemCallGas {
- gas = uint64(*args.Gas)
+ if args.Commitments == nil {
+ // Generate commitment and proof.
+ commitments := make([]kzg4844.Commitment, n)
+ proofs := make([]kzg4844.Proof, n)
+ for i, b := range args.Blobs {
+ c, err := kzg4844.BlobToCommitment(&b)
+ if err != nil {
+ return fmt.Errorf("blobs[%d]: error computing commitment: %v", i, err)
+ }
+ commitments[i] = c
+ p, err := kzg4844.ComputeBlobProof(&b, c)
+ if err != nil {
+ return fmt.Errorf("blobs[%d]: error computing proof: %v", i, err)
+ }
+ proofs[i] = p
+ }
+ args.Commitments = commitments
+ args.Proofs = proofs
+ } else {
+ for i, b := range args.Blobs {
+ if err := kzg4844.VerifyBlobProof(&b, args.Commitments[i], args.Proofs[i]); err != nil {
+ return fmt.Errorf("failed to verify blob proof: %v", err)
+ }
+ }
}
- if globalGasCap != 0 && globalGasCap < gas {
- log.Warn("Caller gas above allowance, capping", "requested", gas, "cap", globalGasCap)
- gas = globalGasCap
+ hashes := make([]common.Hash, n)
+ hasher := sha256.New()
+ for i, c := range args.Commitments {
+ hashes[i] = kzg4844.CalcBlobHashV1(hasher, &c)
+ }
+ if args.BlobHashes != nil {
+ for i, h := range hashes {
+ if h != args.BlobHashes[i] {
+ return fmt.Errorf("blob hash verification failed (have=%s, want=%s)", args.BlobHashes[i], h)
+ }
+ }
+ } else {
+ args.BlobHashes = hashes
}
+ return nil
+}
+// CallDefaults sanitizes the transaction arguments, often filling in zero values,
+// for the purpose of eth_call class of RPC methods.
+func (args *TransactionArgs) CallDefaults(globalGasCap uint64, baseFee *big.Int, chainID *big.Int) error {
+ // Reject invalid combinations of pre- and post-1559 fee styles
+ if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
+ return errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
+ }
+ if args.ChainID == nil {
+ args.ChainID = (*hexutil.Big)(chainID)
+ } else {
+ if have := (*big.Int)(args.ChainID); have.Cmp(chainID) != 0 {
+ return fmt.Errorf("chainId does not match node's (have=%v, want=%v)", have, chainID)
+ }
+ }
+ if args.Gas == nil {
+ gas := globalGasCap
+ if gas == 0 {
+ gas = uint64(math.MaxUint64 / 2)
+ }
+ args.Gas = (*hexutil.Uint64)(&gas)
+ } else {
+ // Gas set for system calls
+ systemCallGas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
+
+ gas := globalGasCap
+ if gas == 0 {
+ gas = uint64(math.MaxUint64 / 2)
+ }
+ if args.Gas != nil && *args.Gas != systemCallGas {
+ gas = uint64(*args.Gas)
+ }
+
+ if globalGasCap > 0 && globalGasCap < gas {
+ log.Warn("Caller gas above allowance, capping", "requested", args.Gas, "cap", globalGasCap)
+ args.Gas = (*hexutil.Uint64)(&globalGasCap)
+ }
+ }
+ if args.Nonce == nil {
+ args.Nonce = new(hexutil.Uint64)
+ }
+ if args.Value == nil {
+ args.Value = new(hexutil.Big)
+ }
+ if baseFee == nil {
+ // If there's no basefee, then it must be a non-1559 execution
+ if args.GasPrice == nil {
+ args.GasPrice = new(hexutil.Big)
+ }
+ } else {
+ // A basefee is provided, necessitating 1559-type execution
+ if args.MaxFeePerGas == nil {
+ args.MaxFeePerGas = new(hexutil.Big)
+ }
+ if args.MaxPriorityFeePerGas == nil {
+ args.MaxPriorityFeePerGas = new(hexutil.Big)
+ }
+ }
+ if args.BlobFeeCap == nil && args.BlobHashes != nil {
+ args.BlobFeeCap = new(hexutil.Big)
+ }
+
+ return nil
+}
+
+// ToMessage converts the transaction arguments to the Message type used by the
+// core evm. This method is used in calls and traces that do not require a real
+// live transaction.
+// Assumes that fields are not nil, i.e. setDefaults or CallDefaults has been called.
+func (args *TransactionArgs) ToMessage(baseFee *big.Int) *core.Message {
var (
gasPrice *big.Int
gasFeeCap *big.Int
@@ -251,12 +453,7 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*
)
if baseFee == nil {
- // If there's no basefee, then it must be a non-1559 execution
- gasPrice = new(big.Int)
- if args.GasPrice != nil {
- gasPrice = args.GasPrice.ToInt()
- }
-
+ gasPrice = args.GasPrice.ToInt()
gasFeeCap, gasTipCap = gasPrice, gasPrice
} else {
// A basefee is provided, necessitating 1559-type execution
@@ -266,18 +463,8 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*
gasFeeCap, gasTipCap = gasPrice, gasPrice
} else {
// User specified 1559 gas fields (or none), use those
- gasFeeCap = new(big.Int)
-
- if args.MaxFeePerGas != nil {
- gasFeeCap = args.MaxFeePerGas.ToInt()
- }
-
- gasTipCap = new(big.Int)
-
- if args.MaxPriorityFeePerGas != nil {
- gasTipCap = args.MaxPriorityFeePerGas.ToInt()
- }
-
+ gasFeeCap = args.MaxFeePerGas.ToInt()
+ gasTipCap = args.MaxPriorityFeePerGas.ToInt()
// Backfill the legacy gasPrice for EVM execution, unless we're all zeroes
gasPrice = new(big.Int)
@@ -286,41 +473,58 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*
}
}
}
-
- value := new(big.Int)
- if args.Value != nil {
- value = args.Value.ToInt()
- }
-
- data := args.data()
-
var accessList types.AccessList
if args.AccessList != nil {
accessList = *args.AccessList
}
-
- msg := &core.Message{
- From: addr,
+ return &core.Message{
+ From: args.from(),
To: args.To,
- Value: value,
- GasLimit: gas,
+ Value: (*big.Int)(args.Value),
+ GasLimit: uint64(*args.Gas),
GasPrice: gasPrice,
GasFeeCap: gasFeeCap,
GasTipCap: gasTipCap,
- Data: data,
+ Data: args.data(),
AccessList: accessList,
+ BlobGasFeeCap: (*big.Int)(args.BlobFeeCap),
+ BlobHashes: args.BlobHashes,
SkipAccountChecks: true,
}
-
- return msg, nil
}
-// toTransaction converts the arguments to a transaction.
+// ToTransaction converts the arguments to a transaction.
// This assumes that setDefaults has been called.
-func (args *TransactionArgs) toTransaction() *types.Transaction {
+func (args *TransactionArgs) ToTransaction() *types.Transaction {
var data types.TxData
switch {
+ case args.BlobHashes != nil:
+ al := types.AccessList{}
+ if args.AccessList != nil {
+ al = *args.AccessList
+ }
+ data = &types.BlobTx{
+ To: *args.To,
+ ChainID: uint256.MustFromBig((*big.Int)(args.ChainID)),
+ Nonce: uint64(*args.Nonce),
+ Gas: uint64(*args.Gas),
+ GasFeeCap: uint256.MustFromBig((*big.Int)(args.MaxFeePerGas)),
+ GasTipCap: uint256.MustFromBig((*big.Int)(args.MaxPriorityFeePerGas)),
+ Value: uint256.MustFromBig((*big.Int)(args.Value)),
+ Data: args.data(),
+ AccessList: al,
+ BlobHashes: args.BlobHashes,
+ BlobFeeCap: uint256.MustFromBig((*big.Int)(args.BlobFeeCap)),
+ }
+ if args.Blobs != nil {
+ data.(*types.BlobTx).Sidecar = &types.BlobTxSidecar{
+ Blobs: args.Blobs,
+ Commitments: args.Commitments,
+ Proofs: args.Proofs,
+ }
+ }
+
case args.MaxFeePerGas != nil:
al := types.AccessList{}
if args.AccessList != nil {
@@ -338,6 +542,7 @@ func (args *TransactionArgs) toTransaction() *types.Transaction {
Data: args.data(),
AccessList: al,
}
+
case args.AccessList != nil:
data = &types.AccessListTx{
To: args.To,
@@ -349,6 +554,7 @@ func (args *TransactionArgs) toTransaction() *types.Transaction {
Data: args.data(),
AccessList: *args.AccessList,
}
+
default:
data = &types.LegacyTx{
To: args.To,
@@ -363,8 +569,7 @@ func (args *TransactionArgs) toTransaction() *types.Transaction {
return types.NewTx(data)
}
-// ToTransaction converts the arguments to a transaction.
-// This assumes that setDefaults has been called.
-func (args *TransactionArgs) ToTransaction() *types.Transaction {
- return args.toTransaction()
+// IsEIP4844 returns an indicator if the args contains EIP4844 fields.
+func (args *TransactionArgs) IsEIP4844() bool {
+ return args.BlobHashes != nil || args.BlobFeeCap != nil
}
diff --git a/internal/ethapi/transaction_args_test.go b/internal/ethapi/transaction_args_test.go
index d7cba3c50d..e8ab2d8eee 100644
--- a/internal/ethapi/transaction_args_test.go
+++ b/internal/ethapi/transaction_args_test.go
@@ -45,15 +45,16 @@ func TestSetFeeDefaults(t *testing.T) {
t.Parallel()
type test struct {
- name string
- isLondon bool
- in *TransactionArgs
- want *TransactionArgs
- err error
+ name string
+ fork string // options: legacy, london, cancun
+ in *TransactionArgs
+ want *TransactionArgs
+ err error
}
var (
b = newBackendMock()
+ zero = (*hexutil.Big)(big.NewInt(0))
fortytwo = (*hexutil.Big)(big.NewInt(42))
maxFee = (*hexutil.Big)(new(big.Int).Add(new(big.Int).Mul(b.current.BaseFee, big.NewInt(2)), fortytwo.ToInt()))
al = &types.AccessList{types.AccessTuple{Address: common.Address{0xaa}, StorageKeys: []common.Hash{{0x01}}}}
@@ -63,51 +64,65 @@ func TestSetFeeDefaults(t *testing.T) {
// Legacy txs
{
"legacy tx pre-London",
- false,
+ "legacy",
&TransactionArgs{},
&TransactionArgs{GasPrice: fortytwo},
nil,
},
+ {
+ "legacy tx pre-London with zero price",
+ "legacy",
+ &TransactionArgs{GasPrice: zero},
+ &TransactionArgs{GasPrice: zero},
+ nil,
+ },
{
"legacy tx post-London, explicit gas price",
- true,
+ "london",
&TransactionArgs{GasPrice: fortytwo},
&TransactionArgs{GasPrice: fortytwo},
nil,
},
+ {
+ "legacy tx post-London with zero price",
+ "london",
+ &TransactionArgs{GasPrice: zero},
+ nil,
+ errors.New("gasPrice must be non-zero after london fork"),
+ },
// Access list txs
{
"access list tx pre-London",
- false,
+ "legacy",
&TransactionArgs{AccessList: al},
&TransactionArgs{AccessList: al, GasPrice: fortytwo},
nil,
},
{
"access list tx post-London, explicit gas price",
- false,
+ "legacy",
&TransactionArgs{AccessList: al, GasPrice: fortytwo},
&TransactionArgs{AccessList: al, GasPrice: fortytwo},
nil,
},
{
"access list tx post-London",
- true,
+ "london",
&TransactionArgs{AccessList: al},
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"access list tx post-London, only max fee",
- true,
+ "london",
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee},
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"access list tx post-London, only priority fee",
- true,
+ "london",
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee},
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
@@ -116,95 +131,127 @@ func TestSetFeeDefaults(t *testing.T) {
// Dynamic fee txs
{
"dynamic tx post-London",
- true,
+ "london",
&TransactionArgs{},
&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"dynamic tx post-London, only max fee",
- true,
+ "london",
&TransactionArgs{MaxFeePerGas: maxFee},
&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"dynamic tx post-London, only priority fee",
- true,
+ "london",
&TransactionArgs{MaxFeePerGas: maxFee},
&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"dynamic fee tx pre-London, maxFee set",
- false,
+ "legacy",
&TransactionArgs{MaxFeePerGas: maxFee},
nil,
errors.New("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active"),
},
{
"dynamic fee tx pre-London, priorityFee set",
- false,
+ "legacy",
&TransactionArgs{MaxPriorityFeePerGas: fortytwo},
nil,
errors.New("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active"),
},
{
"dynamic fee tx, maxFee < priorityFee",
- true,
+ "london",
&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: (*hexutil.Big)(big.NewInt(1000))},
nil,
errors.New("maxFeePerGas (0x3e) < maxPriorityFeePerGas (0x3e8)"),
},
{
"dynamic fee tx, maxFee < priorityFee while setting default",
- true,
+ "london",
&TransactionArgs{MaxFeePerGas: (*hexutil.Big)(big.NewInt(7))},
nil,
errors.New("maxFeePerGas (0x7) < maxPriorityFeePerGas (0x2a)"),
},
+ {
+ "dynamic fee tx post-London, explicit gas price",
+ "london",
+ &TransactionArgs{MaxFeePerGas: zero, MaxPriorityFeePerGas: zero},
+ nil,
+ errors.New("maxFeePerGas must be non-zero"),
+ },
// Misc
{
"set all fee parameters",
- false,
+ "legacy",
&TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
},
{
"set gas price and maxPriorityFee",
- false,
+ "legacy",
&TransactionArgs{GasPrice: fortytwo, MaxPriorityFeePerGas: fortytwo},
nil,
errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
},
{
"set gas price and maxFee",
- true,
+ "london",
&TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee},
nil,
errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
},
+ // EIP-4844
+ {
+ "set gas price and maxFee for blob transaction",
+ "cancun",
+ &TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee, BlobHashes: []common.Hash{}},
+ nil,
+ errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
+ },
+ {
+ "fill maxFeePerBlobGas",
+ "cancun",
+ &TransactionArgs{BlobHashes: []common.Hash{}},
+ &TransactionArgs{BlobHashes: []common.Hash{}, BlobFeeCap: (*hexutil.Big)(big.NewInt(4)), MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
+ nil,
+ },
+ {
+ "fill maxFeePerBlobGas when dynamic fees are set",
+ "cancun",
+ &TransactionArgs{BlobHashes: []common.Hash{}, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
+ &TransactionArgs{BlobHashes: []common.Hash{}, BlobFeeCap: (*hexutil.Big)(big.NewInt(4)), MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
+ nil,
+ },
}
ctx := context.Background()
for i, test := range tests {
- if test.isLondon {
- b.activateLondon()
- } else {
- b.deactivateLondon()
+ if err := b.setFork(test.fork); err != nil {
+ t.Fatalf("failed to set fork: %v", err)
}
got := test.in
err := got.setFeeDefaults(ctx, b)
- if err != nil && err.Error() == test.err.Error() {
- // Test threw expected error.
+ if err != nil {
+ if test.err == nil {
+ t.Fatalf("test %d (%s): unexpected error: %s", i, test.name, err)
+ } else if err.Error() != test.err.Error() {
+ t.Fatalf("test %d (%s): unexpected error: (got: %s, want: %s)", i, test.name, err, test.err)
+ }
+ // Matching error.
continue
- } else if err != nil {
- t.Fatalf("test %d (%s): unexpected error: %s", i, test.name, err)
+ } else if test.err != nil {
+ t.Fatalf("test %d (%s): expected error: %s", i, test.name, test.err)
}
if !reflect.DeepEqual(got, test.want) {
@@ -250,23 +297,37 @@ func newBackendMock() *backendMock {
}
}
-func (b *backendMock) activateLondon() {
- b.current.Number = big.NewInt(1100)
+func (b *backendMock) setFork(fork string) error {
+ if fork == "legacy" {
+ b.current.Number = big.NewInt(900)
+ b.current.Time = 555
+ } else if fork == "london" {
+ b.current.Number = big.NewInt(1100)
+ b.current.Time = 555
+ } else if fork == "cancun" {
+ b.current.Number = big.NewInt(1100)
+ b.current.Time = 700
+ // Blob base fee will be 2
+ excess := uint64(2314058)
+ b.current.ExcessBlobGas = &excess
+ } else {
+ return errors.New("invalid fork")
+ }
+ return nil
}
-func (b *backendMock) deactivateLondon() {
- b.current.Number = big.NewInt(900)
-}
func (b *backendMock) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
return big.NewInt(42), nil
}
+func (b *backendMock) BlobBaseFee(ctx context.Context) *big.Int { return big.NewInt(42) }
+
func (b *backendMock) CurrentHeader() *types.Header { return b.current }
func (b *backendMock) ChainConfig() *params.ChainConfig { return b.config }
// Other methods needed to implement Backend interface.
func (b *backendMock) SyncProgress() ethereum.SyncProgress { return ethereum.SyncProgress{} }
-func (b *backendMock) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, error) {
- return nil, nil, nil, nil, nil
+func (b *backendMock) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, []*big.Int, []float64, error) {
+ return nil, nil, nil, nil, nil, nil, nil
}
func (b *backendMock) ChainDb() ethdb.Database { return nil }
func (b *backendMock) AccountManager() *accounts.Manager { return nil }
@@ -311,10 +372,7 @@ func (b *backendMock) StateAndHeaderByNumber(ctx context.Context, number rpc.Blo
func (b *backendMock) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {
return nil, nil, nil
}
-func (b *backendMock) PendingBlockAndReceipts() (*types.Block, types.Receipts) {
- //nolint:nilnil
- return nil, nil
-}
+func (b *backendMock) Pending() (*types.Block, types.Receipts, *state.StateDB) { return nil, nil, nil }
func (b *backendMock) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
//nolint:nilnil
return nil, nil
@@ -335,8 +393,8 @@ func (b *backendMock) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) eve
return nil
}
func (b *backendMock) SendTx(ctx context.Context, signedTx *types.Transaction) error { return nil }
-func (b *backendMock) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
- return nil, [32]byte{}, 0, 0, nil
+func (b *backendMock) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
+ return false, nil, [32]byte{}, 0, 0, nil
}
func (b *backendMock) GetPoolTransactions() (types.Transactions, error) { return nil, nil }
func (b *backendMock) GetPoolTransaction(txHash common.Hash) *types.Transaction { return nil }
diff --git a/internal/flags/categories.go b/internal/flags/categories.go
index 487684d98b..d426add55b 100644
--- a/internal/flags/categories.go
+++ b/internal/flags/categories.go
@@ -20,7 +20,7 @@ import "github.com/urfave/cli/v2"
const (
EthCategory = "ETHEREUM"
- LightCategory = "LIGHT CLIENT"
+ BeaconCategory = "BEACON CHAIN"
DevCategory = "DEVELOPER CHAIN"
StateCategory = "STATE HISTORY MANAGEMENT"
TxPoolCategory = "TRANSACTION POOL (EVM)"
@@ -35,6 +35,7 @@ const (
LoggingCategory = "LOGGING AND DEBUGGING"
MetricsCategory = "METRICS AND STATS"
MiscCategory = "MISC"
+ TestingCategory = "TESTING"
DeprecatedCategory = "ALIASED (deprecated)"
)
diff --git a/internal/flags/flags.go b/internal/flags/flags.go
index bff4a7ce64..56ba6447d1 100644
--- a/internal/flags/flags.go
+++ b/internal/flags/flags.go
@@ -265,7 +265,8 @@ type BigFlag struct {
Hidden bool
HasBeenSet bool
- Value *big.Int
+ Value *big.Int
+ defaultValue *big.Int
Aliases []string
EnvVars []string
@@ -278,6 +279,10 @@ func (f *BigFlag) IsSet() bool { return f.HasBeenSet }
func (f *BigFlag) String() string { return cli.FlagStringer(f) }
func (f *BigFlag) Apply(set *flag.FlagSet) error {
+ // Set default value so that environment wont be able to overwrite it
+ if f.Value != nil {
+ f.defaultValue = new(big.Int).Set(f.Value)
+ }
for _, envVar := range f.EnvVars {
envVar = strings.TrimSpace(envVar)
if value, found := syscall.Getenv(envVar); found {
@@ -292,7 +297,6 @@ func (f *BigFlag) Apply(set *flag.FlagSet) error {
f.Value = new(big.Int)
set.Var((*bigValue)(f.Value), f.Name, f.Usage)
})
-
return nil
}
@@ -319,8 +323,7 @@ func (f *BigFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
-
- return f.GetValue()
+ return f.defaultValue.String()
}
// bigValue turns *big.Int into a flag.Value
diff --git a/internal/flags/helpers.go b/internal/flags/helpers.go
index c9aa729041..e505c905ae 100644
--- a/internal/flags/helpers.go
+++ b/internal/flags/helpers.go
@@ -42,7 +42,7 @@ func NewApp(usage string) *cli.App {
app.EnableBashCompletion = true
app.Version = params.VersionWithCommit(git.Commit, git.Date)
app.Usage = usage
- app.Copyright = "Copyright 2013-2023 The go-ethereum Authors"
+ app.Copyright = "Copyright 2013-2024 The go-ethereum Authors"
app.Before = func(ctx *cli.Context) error {
MigrateGlobalFlags(ctx)
return nil
diff --git a/internal/jsre/deps/web3.js b/internal/jsre/deps/web3.js
index 7e6ae09d50..70f9f9d5b3 100644
--- a/internal/jsre/deps/web3.js
+++ b/internal/jsre/deps/web3.js
@@ -3734,7 +3734,7 @@ var inputCallFormatter = function (options){
options.to = inputAddressFormatter(options.to);
}
- ['maxFeePerGas', 'maxPriorityFeePerGas', 'gasPrice', 'gas', 'value', 'nonce'].filter(function (key) {
+ ['maxFeePerBlobGas', 'maxFeePerGas', 'maxPriorityFeePerGas', 'gasPrice', 'gas', 'value', 'nonce'].filter(function (key) {
return options[key] !== undefined;
}).forEach(function(key){
options[key] = utils.fromDecimal(options[key]);
@@ -3759,7 +3759,7 @@ var inputTransactionFormatter = function (options){
options.to = inputAddressFormatter(options.to);
}
- ['maxFeePerGas', 'maxPriorityFeePerGas', 'gasPrice', 'gas', 'value', 'nonce'].filter(function (key) {
+ ['maxFeePerBlobGas', 'maxFeePerGas', 'maxPriorityFeePerGas', 'gasPrice', 'gas', 'value', 'nonce'].filter(function (key) {
return options[key] !== undefined;
}).forEach(function(key){
options[key] = utils.fromDecimal(options[key]);
@@ -3789,6 +3789,9 @@ var outputTransactionFormatter = function (tx){
if(tx.maxPriorityFeePerGas !== undefined) {
tx.maxPriorityFeePerGas = utils.toBigNumber(tx.maxPriorityFeePerGas);
}
+ if(tx.maxFeePerBlobGas !== undefined) {
+ tx.maxFeePerBlobGas = utils.toBigNumber(tx.maxFeePerBlobGas);
+ }
tx.value = utils.toBigNumber(tx.value);
return tx;
};
@@ -3810,6 +3813,12 @@ var outputTransactionReceiptFormatter = function (receipt){
if(receipt.effectiveGasPrice !== undefined) {
receipt.effectiveGasPrice = utils.toBigNumber(receipt.effectiveGasPrice);
}
+ if(receipt.blobGasPrice !== undefined) {
+ receipt.blobGasPrice = utils.toBigNumber(receipt.blobGasPrice);
+ }
+ if(receipt.blobGasUsed !== undefined) {
+ receipt.blobGasUsed = utils.toBigNumber(receipt.blobGasUsed);
+ }
if(utils.isArray(receipt.logs)) {
receipt.logs = receipt.logs.map(function(log){
return outputLogFormatter(log);
@@ -3831,11 +3840,17 @@ var outputBlockFormatter = function(block) {
if (block.baseFeePerGas !== undefined) {
block.baseFeePerGas = utils.toBigNumber(block.baseFeePerGas);
}
+ if (block.blobGasUsed !== undefined) {
+ block.blobGasUsed = utils.toBigNumber(block.blobGasUsed);
+ }
+ if (block.excessBlobGas !== undefined) {
+ block.excessBlobGas = utils.toBigNumber(block.excessBlobGas);
+ }
block.gasLimit = utils.toDecimal(block.gasLimit);
block.gasUsed = utils.toDecimal(block.gasUsed);
block.size = utils.toDecimal(block.size);
block.timestamp = utils.toDecimal(block.timestamp);
- if(block.number !== null)
+ if (block.number !== null)
block.number = utils.toDecimal(block.number);
block.difficulty = utils.toBigNumber(block.difficulty);
@@ -3961,6 +3976,8 @@ var outputSyncingFormatter = function(result) {
result.healedBytecodeBytes = utils.toDecimal(result.healedBytecodeBytes);
result.healingTrienodes = utils.toDecimal(result.healingTrienodes);
result.healingBytecode = utils.toDecimal(result.healingBytecode);
+ result.txIndexFinishedBlocks = utils.toDecimal(result.txIndexFinishedBlocks);
+ result.txIndexRemainingBlocks = utils.toDecimal(result.txIndexRemainingBlocks);
return result;
};
@@ -5517,6 +5534,11 @@ var properties = function () {
getter: 'eth_gasPrice',
outputFormatter: formatters.outputBigNumberFormatter
}),
+ new Property({
+ name: 'blobBaseFee',
+ getter: 'eth_blobBaseFee',
+ outputFormatter: formatters.outputBigNumberFormatter
+ }),
new Property({
name: 'accounts',
getter: 'eth_accounts'
diff --git a/internal/jsre/jsre_test.go b/internal/jsre/jsre_test.go
index d1d83d0975..f47de19ce0 100644
--- a/internal/jsre/jsre_test.go
+++ b/internal/jsre/jsre_test.go
@@ -18,7 +18,7 @@ package jsre
import (
"os"
- "path"
+ "path/filepath"
"reflect"
"testing"
"time"
@@ -44,7 +44,7 @@ func newWithTestJS(t *testing.T, testjs string) *JSRE {
dir := t.TempDir()
if testjs != "" {
- if err := os.WriteFile(path.Join(dir, "test.js"), []byte(testjs), os.ModePerm); err != nil {
+ if err := os.WriteFile(filepath.Join(dir, "test.js"), []byte(testjs), os.ModePerm); err != nil {
t.Fatal("cannot create test.js:", err)
}
}
diff --git a/internal/testlog/testlog.go b/internal/testlog/testlog.go
index 09fa90cd7d..e329f3c0e4 100644
--- a/internal/testlog/testlog.go
+++ b/internal/testlog/testlog.go
@@ -21,11 +21,11 @@ import (
"bytes"
"context"
"fmt"
+ "log/slog"
"sync"
"testing"
"github.com/ethereum/go-ethereum/log"
- "golang.org/x/exp/slog"
)
const (
@@ -47,9 +47,12 @@ type bufHandler struct {
buf []slog.Record
attrs []slog.Attr
level slog.Level
+ mu sync.Mutex
}
func (h *bufHandler) Handle(_ context.Context, r slog.Record) error {
+ h.mu.Lock()
+ defer h.mu.Unlock()
h.buf = append(h.buf, r)
return nil
}
@@ -59,12 +62,14 @@ func (h *bufHandler) Enabled(_ context.Context, lvl slog.Level) bool {
}
func (h *bufHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
+ h.mu.Lock()
+ defer h.mu.Unlock()
records := make([]slog.Record, len(h.buf))
copy(records[:], h.buf[:])
return &bufHandler{
- records,
- append(h.attrs, attrs...),
- h.level,
+ buf: records,
+ attrs: append(h.attrs, attrs...),
+ level: h.level,
}
}
@@ -75,9 +80,9 @@ func (h *bufHandler) WithGroup(_ string) slog.Handler {
// Logger returns a logger which logs to the unit test log of t.
func Logger(t *testing.T, level slog.Level) log.Logger {
handler := bufHandler{
- []slog.Record{},
- []slog.Attr{},
- level,
+ buf: []slog.Record{},
+ attrs: []slog.Attr{},
+ level: level,
}
return &logger{
t: t,
@@ -98,6 +103,10 @@ func LoggerWithHandler(t *testing.T, handler slog.Handler) log.Logger {
}
}
+func (l *logger) Handler() slog.Handler {
+ return l.l.Handler()
+}
+
func (l *logger) Write(level slog.Level, msg string, ctx ...interface{}) {}
func (l *logger) Enabled(ctx context.Context, level slog.Level) bool {
@@ -196,7 +205,8 @@ func (h *bufHandler) terminalFormat(r slog.Record) string {
// flush writes all buffered messages and clears the buffer.
func (l *logger) flush() {
l.t.Helper()
-
+ l.h.mu.Lock()
+ defer l.h.mu.Unlock()
for _, r := range l.h.buf {
l.t.Logf("%s", l.h.terminalFormat(r))
}
diff --git a/trie/testutil/utils.go b/internal/testrand/rand.go
similarity index 61%
rename from trie/testutil/utils.go
rename to internal/testrand/rand.go
index a75d0431b0..690993de05 100644
--- a/trie/testutil/utils.go
+++ b/internal/testrand/rand.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package testutil
+package testrand
import (
crand "crypto/rand"
@@ -22,11 +22,9 @@ import (
mrand "math/rand"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/trie/trienode"
)
-// Prng is a pseudo random number generator seeded by strong randomness.
+// prng is a pseudo random number generator seeded by strong randomness.
// The randomness is printed on startup in order to make failures reproducible.
var prng = initRand()
@@ -37,25 +35,19 @@ func initRand() *mrand.Rand {
return rnd
}
-// RandBytes generates a random byte slice with specified length.
-func RandBytes(n int) []byte {
+// Bytes generates a random byte slice with specified length.
+func Bytes(n int) []byte {
r := make([]byte, n)
prng.Read(r)
return r
}
-// RandomHash generates a random blob of data and returns it as a hash.
-func RandomHash() common.Hash {
- return common.BytesToHash(RandBytes(common.HashLength))
+// Hash generates a random hash.
+func Hash() common.Hash {
+ return common.BytesToHash(Bytes(common.HashLength))
}
-// RandomAddress generates a random blob of data and returns it as an address.
-func RandomAddress() common.Address {
- return common.BytesToAddress(RandBytes(common.AddressLength))
-}
-
-// RandomNode generates a random node.
-func RandomNode() *trienode.Node {
- val := RandBytes(100)
- return trienode.New(crypto.Keccak256Hash(val), val)
+// Address generates a random address.
+func Address() common.Address {
+ return common.BytesToAddress(Bytes(common.AddressLength))
}
diff --git a/internal/utesting/utesting.go b/internal/utesting/utesting.go
index 6520dfc564..83d79c45b2 100644
--- a/internal/utesting/utesting.go
+++ b/internal/utesting/utesting.go
@@ -35,6 +35,7 @@ import (
type Test struct {
Name string
Fn func(*T)
+ Slow bool
}
// Result is the result of a test execution.
diff --git a/internal/version/version.go b/internal/version/version.go
index 737d383f00..b144c4e953 100644
--- a/internal/version/version.go
+++ b/internal/version/version.go
@@ -70,6 +70,7 @@ func ClientName(clientIdentifier string) string {
}
// Info returns build and platform information about the current binary.
+//
// If the package that is currently executing is a prefixed by our go-ethereum
// module path, it will print out commit and date VCS information. Otherwise,
// it will assume it's imported by a third-party and will return the imported
diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go
index f1fcd9974d..8699e53763 100644
--- a/internal/web3ext/web3ext.go
+++ b/internal/web3ext/web3ext.go
@@ -302,7 +302,6 @@ web3._extend({
new web3._extend.Method({
name: 'chaindbProperty',
call: 'debug_chaindbProperty',
- params: 1,
outputFormatter: console.log
}),
new web3._extend.Method({
@@ -723,20 +722,6 @@ const MinerJs = `
web3._extend({
property: 'miner',
methods: [
- new web3._extend.Method({
- name: 'start',
- call: 'miner_start',
- }),
- new web3._extend.Method({
- name: 'stop',
- call: 'miner_stop'
- }),
- new web3._extend.Method({
- name: 'setEtherbase',
- call: 'miner_setEtherbase',
- params: 1,
- inputFormatter: [web3._extend.formatters.inputAddressFormatter]
- }),
new web3._extend.Method({
name: 'setExtra',
call: 'miner_setExtra',
@@ -754,15 +739,6 @@ web3._extend({
params: 1,
inputFormatter: [web3._extend.utils.fromDecimal]
}),
- new web3._extend.Method({
- name: 'setRecommitInterval',
- call: 'miner_setRecommitInterval',
- params: 1,
- }),
- new web3._extend.Method({
- name: 'getHashrate',
- call: 'miner_getHashrate'
- }),
],
properties: []
});
diff --git a/log/format.go b/log/format.go
index 6447f3c1f1..f50258e2cd 100644
--- a/log/format.go
+++ b/log/format.go
@@ -3,6 +3,7 @@ package log
import (
"bytes"
"fmt"
+ "log/slog"
"math/big"
"reflect"
"strconv"
@@ -10,7 +11,6 @@ import (
"unicode/utf8"
"github.com/holiman/uint256"
- "golang.org/x/exp/slog"
)
const (
@@ -79,24 +79,18 @@ func (h *TerminalHandler) format(buf []byte, r slog.Record, usecolor bool) []byt
}
func (h *TerminalHandler) formatAttributes(buf *bytes.Buffer, r slog.Record, color string) {
- // tmp is a temporary buffer we use, until bytes.Buffer.AvailableBuffer() (1.21)
- // can be used.
- var tmp = make([]byte, 40)
writeAttr := func(attr slog.Attr, first, last bool) {
buf.WriteByte(' ')
if color != "" {
buf.WriteString(color)
- //buf.Write(appendEscapeString(buf.AvailableBuffer(), attr.Key))
- buf.Write(appendEscapeString(tmp[:0], attr.Key))
+ buf.Write(appendEscapeString(buf.AvailableBuffer(), attr.Key))
buf.WriteString("\x1b[0m=")
} else {
- //buf.Write(appendEscapeString(buf.AvailableBuffer(), attr.Key))
- buf.Write(appendEscapeString(tmp[:0], attr.Key))
+ buf.Write(appendEscapeString(buf.AvailableBuffer(), attr.Key))
buf.WriteByte('=')
}
- //val := FormatSlogValue(attr.Value, true, buf.AvailableBuffer())
- val := FormatSlogValue(attr.Value, tmp[:0])
+ val := FormatSlogValue(attr.Value, buf.AvailableBuffer())
padding := h.fieldPadding[attr.Key]
@@ -237,6 +231,10 @@ func appendBigInt(dst []byte, n *big.Int) []byte {
return appendInt64(dst, n.Int64())
}
+ if len(n.String()) > 64*1024*1024 {
+ _ = fmt.Errorf("%s value in appendBigInt is too large to format", n.String())
+ }
+
var (
text = n.String()
buf = make([]byte, len(text)+len(text)/3)
@@ -346,7 +344,7 @@ func writeTimeTermFormat(buf *bytes.Buffer, t time.Time) {
// writePosIntWidth writes non-negative integer i to the buffer, padded on the left
// by zeroes to the given width. Use a width of 0 to omit padding.
-// Adapted from golang.org/x/exp/slog/internal/buffer/buffer.go
+// Adapted from pkg.go.dev/log/slog/internal/buffer
func writePosIntWidth(b *bytes.Buffer, i, width int) {
// Cheap integer to fixed-width decimal ASCII.
// Copied from log/log.go.
diff --git a/log/handler.go b/log/handler.go
index 7459aad891..56eff6671f 100644
--- a/log/handler.go
+++ b/log/handler.go
@@ -4,13 +4,13 @@ import (
"context"
"fmt"
"io"
+ "log/slog"
"math/big"
"reflect"
"sync"
"time"
"github.com/holiman/uint256"
- "golang.org/x/exp/slog"
)
type discardHandler struct{}
@@ -101,10 +101,10 @@ func (h *TerminalHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
}
// ResetFieldPadding zeroes the field-padding for all attribute pairs.
-func (t *TerminalHandler) ResetFieldPadding() {
- t.mu.Lock()
- t.fieldPadding = make(map[string]int)
- t.mu.Unlock()
+func (h *TerminalHandler) ResetFieldPadding() {
+ h.mu.Lock()
+ h.fieldPadding = make(map[string]int)
+ h.mu.Unlock()
}
type leveler struct{ minLevel slog.Level }
@@ -115,8 +115,15 @@ func (l *leveler) Level() slog.Level {
// JSONHandler returns a handler which prints records in JSON format.
func JSONHandler(wr io.Writer) slog.Handler {
+ return JSONHandlerWithLevel(wr, levelMaxVerbosity)
+}
+
+// JSONHandlerWithLevel returns a handler which prints records in JSON format that are less than or equal to
+// the specified verbosity level.
+func JSONHandlerWithLevel(wr io.Writer, level slog.Level) slog.Handler {
return slog.NewJSONHandler(wr, &slog.HandlerOptions{
ReplaceAttr: builtinReplaceJSON,
+ Level: &leveler{level},
})
}
diff --git a/log/handler_glog.go b/log/handler_glog.go
index fb1e03c5b5..739f8c5b42 100644
--- a/log/handler_glog.go
+++ b/log/handler_glog.go
@@ -20,14 +20,14 @@ import (
"context"
"errors"
"fmt"
+ "log/slog"
+ "maps"
"regexp"
"runtime"
"strconv"
"strings"
"sync"
"sync/atomic"
-
- "golang.org/x/exp/slog"
)
// errVmoduleSyntax is returned when a user vmodule pattern is invalid.
@@ -139,17 +139,18 @@ func (h *GlogHandler) Vmodule(ruleset string) error {
return nil
}
+// Enabled implements slog.Handler, reporting whether the handler handles records
+// at the given level.
func (h *GlogHandler) Enabled(ctx context.Context, lvl slog.Level) bool {
// fast-track skipping logging if override not enabled and the provided verbosity is above configured
return h.override.Load() || slog.Level(h.level.Load()) <= lvl
}
+// WithAttrs implements slog.Handler, returning a new Handler whose attributes
+// consist of both the receiver's attributes and the arguments.
func (h *GlogHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
h.lock.RLock()
- siteCache := make(map[uintptr]slog.Level)
- for k, v := range h.siteCache {
- siteCache[k] = v
- }
+ siteCache := maps.Clone(h.siteCache)
h.lock.RUnlock()
patterns := []pattern{}
@@ -167,12 +168,16 @@ func (h *GlogHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
return &res
}
+// WithGroup implements slog.Handler, returning a new Handler with the given
+// group appended to the receiver's existing groups.
+//
+// Note, this function is not implemented.
func (h *GlogHandler) WithGroup(name string) slog.Handler {
panic("not implemented")
}
-// Log implements Handler.Log, filtering a log record through the global, local
-// and backtrace filters, finally emitting it if either allow it through.
+// Handle implements slog.Handler, filtering a log record through the global,
+// local and backtrace filters, finally emitting it if either allow it through.
func (h *GlogHandler) Handle(_ context.Context, r slog.Record) error {
// If the global log level allows, fast track logging
if slog.Level(h.level.Load()) <= r.Level {
@@ -192,7 +197,7 @@ func (h *GlogHandler) Handle(_ context.Context, r slog.Record) error {
frame, _ := fs.Next()
for _, rule := range h.patterns {
- if rule.pattern.MatchString(fmt.Sprintf("%+s", frame.File)) {
+ if rule.pattern.MatchString(fmt.Sprintf("+%s", frame.File)) {
h.siteCache[r.PC], lvl, ok = rule.level, rule.level, true
}
}
diff --git a/log/logger.go b/log/logger.go
index 93d62f080b..016856c834 100644
--- a/log/logger.go
+++ b/log/logger.go
@@ -2,12 +2,11 @@ package log
import (
"context"
+ "log/slog"
"math"
"os"
"runtime"
"time"
-
- "golang.org/x/exp/slog"
)
const errorKey = "LOG_ERROR"
@@ -36,7 +35,7 @@ const (
LvlDebug = LevelDebug
)
-// convert from old Geth verbosity level constants
+// FromLegacyLevel converts from old Geth verbosity level constants
// to levels defined by slog
func FromLegacyLevel(lvl int) slog.Level {
switch lvl {
@@ -83,7 +82,7 @@ func LevelAlignedString(l slog.Level) string {
}
}
-// LevelString returns a 5-character string containing the name of a Lvl.
+// LevelString returns a string containing the name of a Lvl.
func LevelString(l slog.Level) string {
switch l {
case LevelTrace:
@@ -95,7 +94,7 @@ func LevelString(l slog.Level) string {
case slog.LevelWarn:
return "warn"
case slog.LevelError:
- return "eror"
+ return "error"
case LevelCrit:
return "crit"
default:
@@ -108,7 +107,7 @@ type Logger interface {
// With returns a new Logger that has this logger's attributes plus the given attributes
With(ctx ...interface{}) Logger
- // With returns a new Logger that has this logger's attributes plus the given attributes. Identical to 'With'.
+ // New returns a new Logger that has this logger's attributes plus the given attributes. Identical to 'With'.
New(ctx ...interface{}) Logger
// Log logs a message at the specified level with context key/value pairs
@@ -137,6 +136,9 @@ type Logger interface {
// Enabled reports whether l emits log records at the given context and level.
Enabled(ctx context.Context, level slog.Level) bool
+
+ // Handler returns the underlying handler of the inner logger.
+ Handler() slog.Handler
}
type logger struct {
@@ -150,7 +152,11 @@ func NewLogger(h slog.Handler) Logger {
}
}
-// write logs a message at the specified level:
+func (l *logger) Handler() slog.Handler {
+ return l.inner.Handler()
+}
+
+// Write logs a message at the specified level.
func (l *logger) Write(level slog.Level, msg string, attrs ...any) {
if !l.inner.Enabled(context.Background(), level) {
return
diff --git a/log/logger_test.go b/log/logger_test.go
index a633f5ad7a..f1a9a93bce 100644
--- a/log/logger_test.go
+++ b/log/logger_test.go
@@ -2,8 +2,10 @@ package log
import (
"bytes"
+ "errors"
"fmt"
"io"
+ "log/slog"
"math/big"
"os"
"strings"
@@ -11,7 +13,6 @@ import (
"time"
"github.com/holiman/uint256"
- "golang.org/x/exp/slog"
)
// TestLoggingWithVmodule checks that vmodule works.
@@ -25,7 +26,7 @@ func TestLoggingWithVmodule(t *testing.T) {
logger.Trace("a message", "foo", "bar")
have := out.String()
// The timestamp is locale-dependent, so we want to trim that off
- // "INFO [01-01|00:00:00.000] a messag ..." -> "a messag..."
+ // "INFO [01-01|00:00:00.000] a message ..." -> "a message..."
have = strings.Split(have, "]")[1]
want := " a message foo=bar\n"
if have != want {
@@ -41,7 +42,7 @@ func TestTerminalHandlerWithAttrs(t *testing.T) {
logger.Trace("a message", "foo", "bar")
have := out.String()
// The timestamp is locale-dependent, so we want to trim that off
- // "INFO [01-01|00:00:00.000] a messag ..." -> "a messag..."
+ // "INFO [01-01|00:00:00.000] a message ..." -> "a message..."
have = strings.Split(have, "]")[1]
want := " a message baz=bat foo=bar\n"
if have != want {
@@ -49,6 +50,25 @@ func TestTerminalHandlerWithAttrs(t *testing.T) {
}
}
+// Make sure the default json handler outputs debug log lines
+func TestJSONHandler(t *testing.T) {
+ out := new(bytes.Buffer)
+ handler := JSONHandler(out)
+ logger := slog.New(handler)
+ logger.Debug("hi there")
+ if len(out.String()) == 0 {
+ t.Error("expected non-empty debug log output from default JSON Handler")
+ }
+
+ out.Reset()
+ handler = JSONHandlerWithLevel(out, slog.LevelInfo)
+ logger = slog.New(handler)
+ logger.Debug("hi there")
+ if len(out.String()) != 0 {
+ t.Errorf("expected empty debug log output, but got: %v", out.String())
+ }
+}
+
func BenchmarkTraceLogging(b *testing.B) {
SetDefault(NewLogger(NewTerminalHandler(os.Stderr, true)))
b.ResetTimer()
@@ -77,7 +97,7 @@ func benchmarkLogger(b *testing.B, l Logger) {
tt = time.Now()
bigint = big.NewInt(100)
nilbig *big.Int
- err = fmt.Errorf("Oh nooes it's crap")
+ err = errors.New("oh nooes it's crap")
)
b.ReportAllocs()
b.ResetTimer()
@@ -106,7 +126,7 @@ func TestLoggerOutput(t *testing.T) {
tt = time.Time{}
bigint = big.NewInt(100)
nilbig *big.Int
- err = fmt.Errorf("Oh nooes it's crap")
+ err = errors.New("oh nooes it's crap")
smallUint = uint256.NewInt(500_000)
bigUint = &uint256.Int{0xff, 0xff, 0xff, 0xff}
)
@@ -130,7 +150,7 @@ func TestLoggerOutput(t *testing.T) {
have := out.String()
t.Logf("output %v", out.String())
- want := `INFO [11-07|19:14:33.821] This is a message foo=123 bytes="[0 0 0 0 0 0 0 0 0 0]" bonk="a string with text" time=0001-01-01T00:00:00+0000 bigint=100 nilbig= err="Oh nooes it's crap" struct="{A:Foo B:12}" struct="{A:Foo\nLinebreak B:122}" ptrstruct="&{A:Foo B:12}" smalluint=500,000 bigUint=1,600,660,942,523,603,594,864,898,306,482,794,244,293,965,082,972,225,630,372,095
+ want := `INFO [11-07|19:14:33.821] This is a message foo=123 bytes="[0 0 0 0 0 0 0 0 0 0]" bonk="a string with text" time=0001-01-01T00:00:00+0000 bigint=100 nilbig= err="oh nooes it's crap" struct="{A:Foo B:12}" struct="{A:Foo\nLinebreak B:122}" ptrstruct="&{A:Foo B:12}" smalluint=500,000 bigUint=1,600,660,942,523,603,594,864,898,306,482,794,244,293,965,082,972,225,630,372,095
`
if !bytes.Equal([]byte(have)[25:], []byte(want)[25:]) {
t.Errorf("Error\nhave: %q\nwant: %q", have, want)
diff --git a/log/root.go b/log/root.go
index 71040fff47..91209c46ad 100644
--- a/log/root.go
+++ b/log/root.go
@@ -1,17 +1,15 @@
package log
import (
+ "log/slog"
"os"
"sync/atomic"
-
- "golang.org/x/exp/slog"
)
var root atomic.Value
func init() {
- defaultLogger := &logger{slog.New(DiscardHandler())}
- SetDefault(defaultLogger)
+ root.Store(&logger{slog.New(DiscardHandler())})
}
// SetDefault sets the default global logger
diff --git a/metrics/README.md b/metrics/README.md
index e2d7945008..85b119470a 100644
--- a/metrics/README.md
+++ b/metrics/README.md
@@ -100,24 +100,6 @@ go influxdb.InfluxDB(metrics.DefaultRegistry,
)
```
-Periodically upload every metric to Librato using the [Librato client](https://github.com/mihasya/go-metrics-librato):
-
-**Note**: the client included with this repository under the `librato` package
-has been deprecated and moved to the repository linked above.
-
-```go
-import "github.com/mihasya/go-metrics-librato"
-
-go librato.Librato(metrics.DefaultRegistry,
- 10e9, // interval
- "example@example.com", // account owner email address
- "token", // Librato API token
- "hostname", // source
- []float64{0.95}, // percentiles to send
- time.Millisecond, // time unit
-)
-```
-
Periodically emit every metric to StatHat:
```go
@@ -157,7 +139,6 @@ Publishing Metrics
Clients are available for the following destinations:
-* Librato - https://github.com/mihasya/go-metrics-librato
* Graphite - https://github.com/cyberdelia/go-metrics-graphite
* InfluxDB - https://github.com/vrischmann/go-metrics-influxdb
* Ganglia - https://github.com/appscode/metlia
diff --git a/metrics/config.go b/metrics/config.go
index 2eb09fb48a..72f94dd194 100644
--- a/metrics/config.go
+++ b/metrics/config.go
@@ -19,7 +19,7 @@ package metrics
// Config contains the configuration for the metric collection.
type Config struct {
Enabled bool `toml:",omitempty"`
- EnabledExpensive bool `toml:",omitempty"`
+ EnabledExpensive bool `toml:"-"`
HTTP string `toml:",omitempty"`
Port int `toml:",omitempty"`
EnableInfluxDB bool `toml:",omitempty"`
diff --git a/metrics/counter.go b/metrics/counter.go
index 25e895f023..6ec60d25af 100644
--- a/metrics/counter.go
+++ b/metrics/counter.go
@@ -8,7 +8,7 @@ type CounterSnapshot interface {
Count() int64
}
-// Counters hold an int64 value that can be incremented and decremented.
+// Counter hold an int64 value that can be incremented and decremented.
type Counter interface {
Clear()
Dec(int64)
diff --git a/metrics/debug.go b/metrics/debug.go
index 0dd93d1349..7a305af66a 100644
--- a/metrics/debug.go
+++ b/metrics/debug.go
@@ -19,18 +19,18 @@ var (
gcStats debug.GCStats
)
-// Capture new values for the Go garbage collector statistics exported in
-// debug.GCStats. This is designed to be called as a goroutine.
+// CaptureDebugGCStats captures new values for the Go garbage collector statistics
+// exported in debug.GCStats. This is designed to be called as a goroutine.
func CaptureDebugGCStats(r Registry, d time.Duration) {
for range time.Tick(d) {
CaptureDebugGCStatsOnce(r)
}
}
-// Capture new values for the Go garbage collector statistics exported in
-// debug.GCStats. This is designed to be called in a background goroutine.
-// Giving a registry which has not been given to RegisterDebugGCStats will
-// panic.
+// CaptureDebugGCStatsOnce captures new values for the Go garbage collector
+// statistics exported in debug.GCStats. This is designed to be called in
+// a background goroutine. Giving a registry which has not been given to
+// RegisterDebugGCStats will panic.
//
// Be careful (but much less so) with this because debug.ReadGCStats calls
// the C function runtime·lock(runtime·mheap) which, while not a stop-the-world
@@ -52,9 +52,9 @@ func CaptureDebugGCStatsOnce(r Registry) {
debugMetrics.GCStats.PauseTotal.Update(int64(gcStats.PauseTotal))
}
-// Register metrics for the Go garbage collector statistics exported in
-// debug.GCStats. The metrics are named by their fully-qualified Go symbols,
-// i.e. debug.GCStats.PauseTotal.
+// RegisterDebugGCStats registers metrics for the Go garbage collector statistics
+// exported in debug.GCStats. The metrics are named by their fully-qualified Go
+// symbols, i.e. debug.GCStats.PauseTotal.
func RegisterDebugGCStats(r Registry) {
debugMetrics.GCStats.LastGC = NewGauge()
debugMetrics.GCStats.NumGC = NewGauge()
diff --git a/metrics/gauge.go b/metrics/gauge.go
index c480ec5a05..8c868b68aa 100644
--- a/metrics/gauge.go
+++ b/metrics/gauge.go
@@ -2,12 +2,12 @@ package metrics
import "sync/atomic"
-// gaugeSnapshot contains a readonly int64.
+// GaugeSnapshot contains a readonly int64.
type GaugeSnapshot interface {
Value() int64
}
-// Gauges hold an int64 value that can be set arbitrarily.
+// Gauge holds an int64 value that can be set arbitrarily.
type Gauge interface {
Snapshot() GaugeSnapshot
Update(int64)
@@ -79,7 +79,7 @@ func (g *StandardGauge) Update(v int64) {
g.value.Store(v)
}
-// Update updates the gauge's value if v is larger then the current valie.
+// UpdateIfGt updates the gauge's value if v is larger then the current value.
func (g *StandardGauge) UpdateIfGt(v int64) {
for {
exist := g.value.Load()
diff --git a/metrics/gauge_float64.go b/metrics/gauge_float64.go
index eef6d7673e..5a6e9c1f6b 100644
--- a/metrics/gauge_float64.go
+++ b/metrics/gauge_float64.go
@@ -53,7 +53,7 @@ type gaugeFloat64Snapshot float64
// Value returns the value at the time the snapshot was taken.
func (g gaugeFloat64Snapshot) Value() float64 { return float64(g) }
-// NilGauge is a no-op Gauge.
+// NilGaugeFloat64 is a no-op Gauge.
type NilGaugeFloat64 struct{}
func (NilGaugeFloat64) Snapshot() GaugeFloat64Snapshot { return NilGaugeFloat64{} }
diff --git a/metrics/gauge_info.go b/metrics/gauge_info.go
index c44b2d85f3..0010edc324 100644
--- a/metrics/gauge_info.go
+++ b/metrics/gauge_info.go
@@ -9,7 +9,7 @@ type GaugeInfoSnapshot interface {
Value() GaugeInfoValue
}
-// GaugeInfos hold a GaugeInfoValue value that can be set arbitrarily.
+// GaugeInfo holds a GaugeInfoValue value that can be set arbitrarily.
type GaugeInfo interface {
Update(GaugeInfoValue)
Snapshot() GaugeInfoSnapshot
diff --git a/metrics/healthcheck.go b/metrics/healthcheck.go
index 05b6ff01ab..67e0e25f20 100644
--- a/metrics/healthcheck.go
+++ b/metrics/healthcheck.go
@@ -1,6 +1,6 @@
package metrics
-// Healthchecks hold an error value describing an arbitrary up/down status.
+// Healthcheck holds an error value describing an arbitrary up/down status.
type Healthcheck interface {
Check()
Error() error
diff --git a/metrics/histogram.go b/metrics/histogram.go
index 395891f7e7..7badbfd097 100644
--- a/metrics/histogram.go
+++ b/metrics/histogram.go
@@ -4,7 +4,7 @@ type HistogramSnapshot interface {
SampleSnapshot
}
-// Histograms calculate distribution statistics from a series of int64 values.
+// Histogram calculates distribution statistics from a series of int64 values.
type Histogram interface {
Clear()
Update(int64)
diff --git a/metrics/influxdb/influxdb.go b/metrics/influxdb/influxdb.go
index 6c4a4cc3fd..115baecf18 100644
--- a/metrics/influxdb/influxdb.go
+++ b/metrics/influxdb/influxdb.go
@@ -106,20 +106,23 @@ func readMeter(namespace, name string, i interface{}) (string, map[string]interf
return measurement, fields
case metrics.ResettingTimer:
- t := metric.Snapshot()
- if t.Count() == 0 {
+ ms := metric.Snapshot()
+ if ms.Count() == 0 {
break
}
- ps := t.Percentiles([]float64{0.50, 0.95, 0.99})
- measurement := fmt.Sprintf("%s%s.span", namespace, name)
+ ps := ms.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999})
+ measurement := fmt.Sprintf("%s%s.timer", namespace, name)
fields := map[string]interface{}{
- "count": t.Count(),
- "max": t.Max(),
- "mean": t.Mean(),
- "min": t.Min(),
- "p50": int(ps[0]),
- "p95": int(ps[1]),
- "p99": int(ps[2]),
+ "count": ms.Count(),
+ "max": ms.Max(),
+ "mean": ms.Mean(),
+ "min": ms.Min(),
+ "p50": ps[0],
+ "p75": ps[1],
+ "p95": ps[2],
+ "p99": ps[3],
+ "p999": ps[4],
+ "p9999": ps[5],
}
return measurement, fields
diff --git a/metrics/influxdb/influxdb_test.go b/metrics/influxdb/influxdb_test.go
index c6f2eeac62..5879af7cf6 100644
--- a/metrics/influxdb/influxdb_test.go
+++ b/metrics/influxdb/influxdb_test.go
@@ -23,6 +23,7 @@ import (
"net/http/httptest"
"net/url"
"os"
+ "runtime"
"strings"
"testing"
@@ -37,6 +38,10 @@ func TestMain(m *testing.M) {
}
func TestExampleV1(t *testing.T) {
+ if runtime.GOARCH == "arm64" {
+ t.Skip("test skipped on ARM64 due to floating point precision differences")
+ }
+
r := internal.ExampleMetrics()
var have, want string
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -69,6 +74,10 @@ func TestExampleV1(t *testing.T) {
}
func TestExampleV2(t *testing.T) {
+ if runtime.GOARCH == "arm64" {
+ t.Skip("test skipped on ARM64 due to floating point precision differences")
+ }
+
r := internal.ExampleMetrics()
var have, want string
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
diff --git a/metrics/influxdb/influxdbv2.go b/metrics/influxdb/influxdbv2.go
index 49714b395f..1e8a8b8318 100644
--- a/metrics/influxdb/influxdbv2.go
+++ b/metrics/influxdb/influxdbv2.go
@@ -25,7 +25,7 @@ type v2Reporter struct {
write api.WriteAPI
}
-// InfluxDBWithTags starts a InfluxDB reporter which will post the from the given metrics.Registry at each d interval with the specified tags
+// InfluxDBV2WithTags starts a InfluxDB reporter which will post the from the given metrics.Registry at each d interval with the specified tags
func InfluxDBV2WithTags(r metrics.Registry, d time.Duration, endpoint string, token string, bucket string, organization string, namespace string, tags map[string]string) {
rep := &v2Reporter{
reg: r,
diff --git a/metrics/influxdb/testdata/influxdbv1.want b/metrics/influxdb/testdata/influxdbv1.want
index 9443faedc5..ded9434c73 100644
--- a/metrics/influxdb/testdata/influxdbv1.want
+++ b/metrics/influxdb/testdata/influxdbv1.want
@@ -7,5 +7,5 @@ goth.test/gauge_float64.gauge value=34567.89 978307200000000000
goth.test/gauge_info.gauge value="{\"arch\":\"amd64\",\"commit\":\"7caa2d8163ae3132c1c2d6978c76610caee2d949\",\"os\":\"linux\",\"protocol_versions\":\"64 65 66\",\"version\":\"1.10.18-unstable\"}" 978307200000000000
goth.test/histogram.histogram count=3i,max=3i,mean=2,min=1i,p25=1,p50=2,p75=3,p95=3,p99=3,p999=3,p9999=3,stddev=0.816496580927726,variance=0.6666666666666666 978307200000000000
goth.test/meter.meter count=0i,m1=0,m15=0,m5=0,mean=0 978307200000000000
-goth.test/resetting_timer.span count=6i,max=120000000i,mean=30000000,min=10000000i,p50=12500000i,p95=120000000i,p99=120000000i 978307200000000000
+goth.test/resetting_timer.timer count=6i,max=120000000i,mean=30000000,min=10000000i,p50=12500000,p75=40500000,p95=120000000,p99=120000000,p999=120000000,p9999=120000000 978307200000000000
goth.test/timer.timer count=6i,m1=0,m15=0,m5=0,max=120000000i,mean=38333333.333333336,meanrate=0,min=20000000i,p50=22500000,p75=48000000,p95=120000000,p99=120000000,p999=120000000,p9999=120000000,stddev=36545253.529775314,variance=1335555555555555.2 978307200000000000
diff --git a/metrics/influxdb/testdata/influxdbv2.want b/metrics/influxdb/testdata/influxdbv2.want
index 9443faedc5..ded9434c73 100644
--- a/metrics/influxdb/testdata/influxdbv2.want
+++ b/metrics/influxdb/testdata/influxdbv2.want
@@ -7,5 +7,5 @@ goth.test/gauge_float64.gauge value=34567.89 978307200000000000
goth.test/gauge_info.gauge value="{\"arch\":\"amd64\",\"commit\":\"7caa2d8163ae3132c1c2d6978c76610caee2d949\",\"os\":\"linux\",\"protocol_versions\":\"64 65 66\",\"version\":\"1.10.18-unstable\"}" 978307200000000000
goth.test/histogram.histogram count=3i,max=3i,mean=2,min=1i,p25=1,p50=2,p75=3,p95=3,p99=3,p999=3,p9999=3,stddev=0.816496580927726,variance=0.6666666666666666 978307200000000000
goth.test/meter.meter count=0i,m1=0,m15=0,m5=0,mean=0 978307200000000000
-goth.test/resetting_timer.span count=6i,max=120000000i,mean=30000000,min=10000000i,p50=12500000i,p95=120000000i,p99=120000000i 978307200000000000
+goth.test/resetting_timer.timer count=6i,max=120000000i,mean=30000000,min=10000000i,p50=12500000,p75=40500000,p95=120000000,p99=120000000,p999=120000000,p9999=120000000 978307200000000000
goth.test/timer.timer count=6i,m1=0,m15=0,m5=0,max=120000000i,mean=38333333.333333336,meanrate=0,min=20000000i,p50=22500000,p75=48000000,p95=120000000,p99=120000000,p999=120000000,p9999=120000000,stddev=36545253.529775314,variance=1335555555555555.2 978307200000000000
diff --git a/metrics/json.go b/metrics/json.go
index 2087d8211e..6b134d477b 100644
--- a/metrics/json.go
+++ b/metrics/json.go
@@ -26,6 +26,6 @@ func WriteJSONOnce(r Registry, w io.Writer) {
json.NewEncoder(w).Encode(r)
}
-func (p *PrefixedRegistry) MarshalJSON() ([]byte, error) {
- return json.Marshal(p.GetAll())
+func (r *PrefixedRegistry) MarshalJSON() ([]byte, error) {
+ return json.Marshal(r.GetAll())
}
diff --git a/metrics/librato/client.go b/metrics/librato/client.go
deleted file mode 100644
index 23df8623f7..0000000000
--- a/metrics/librato/client.go
+++ /dev/null
@@ -1,107 +0,0 @@
-package librato
-
-import (
- "bytes"
- "context"
- "encoding/json"
- "fmt"
- "io"
- "net/http"
-)
-
-const Operations = "operations"
-const OperationsShort = "ops"
-
-type LibratoClient struct {
- Email, Token string
-}
-
-// property strings
-const (
- // display attributes
- Color = "color"
- DisplayMax = "display_max"
- DisplayMin = "display_min"
- DisplayUnitsLong = "display_units_long"
- DisplayUnitsShort = "display_units_short"
- DisplayStacked = "display_stacked"
- DisplayTransform = "display_transform"
- // special gauge display attributes
- SummarizeFunction = "summarize_function"
- Aggregate = "aggregate"
-
- // metric keys
- Name = "name"
- Period = "period"
- Description = "description"
- DisplayName = "display_name"
- Attributes = "attributes"
-
- // measurement keys
- MeasureTime = "measure_time"
- Source = "source"
- Value = "value"
-
- // special gauge keys
- Count = "count"
- Sum = "sum"
- Max = "max"
- Min = "min"
- SumSquares = "sum_squares"
-
- // batch keys
- Counters = "counters"
- Gauges = "gauges"
-
- MetricsPostUrl = "https://metrics-api.librato.com/v1/metrics"
-)
-
-type Measurement map[string]interface{}
-type Metric map[string]interface{}
-
-type Batch struct {
- Gauges []Measurement `json:"gauges,omitempty"`
- Counters []Measurement `json:"counters,omitempty"`
- MeasureTime int64 `json:"measure_time"`
- Source string `json:"source"`
-}
-
-func (c *LibratoClient) PostMetrics(batch Batch) (err error) {
- var (
- js []byte
- req *http.Request
- resp *http.Response
- )
-
- if len(batch.Counters) == 0 && len(batch.Gauges) == 0 {
- return nil
- }
-
- if js, err = json.Marshal(batch); err != nil {
- return
- }
-
- if req, err = http.NewRequestWithContext(context.Background(), http.MethodPost, MetricsPostUrl, bytes.NewBuffer(js)); err != nil {
- return
- }
-
- req.Header.Set("Content-Type", "application/json")
- req.SetBasicAuth(c.Email, c.Token)
-
- resp, err = http.DefaultClient.Do(req)
- if err != nil {
- return
- }
- defer resp.Body.Close()
-
- if resp.StatusCode != http.StatusOK {
- var body []byte
- if body, err = io.ReadAll(resp.Body); err != nil {
- body = []byte(fmt.Sprintf("(could not fetch response body for error: %s)", err))
- }
-
- err = fmt.Errorf("unable to post to Librato: %d %s %s", resp.StatusCode, resp.Status, string(body))
- }
-
- return
-}
diff --git a/metrics/librato/librato.go b/metrics/librato/librato.go
deleted file mode 100644
index 1c8c43c9ca..0000000000
--- a/metrics/librato/librato.go
+++ /dev/null
@@ -1,271 +0,0 @@
-package librato
-
-import (
- "fmt"
- "log"
- "math"
- "regexp"
- "time"
-
- "github.com/ethereum/go-ethereum/metrics"
-)
-
-// a regexp for extracting the unit from time.Duration.String
-var unitRegexp = regexp.MustCompile(`[^\\d]+$`)
-
-// a helper that turns a time.Duration into librato display attributes for timer metrics
-func translateTimerAttributes(d time.Duration) (attrs map[string]interface{}) {
- attrs = make(map[string]interface{})
- attrs[DisplayTransform] = fmt.Sprintf("x/%d", int64(d))
- attrs[DisplayUnitsShort] = string(unitRegexp.Find([]byte(d.String())))
-
- return
-}
-
-type Reporter struct {
- Email, Token string
- Namespace string
- Source string
- Interval time.Duration
- Registry metrics.Registry
- Percentiles []float64 // percentiles to report on histogram metrics
- TimerAttributes map[string]interface{} // units in which timers will be displayed
- intervalSec int64
-}
-
-func NewReporter(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) *Reporter {
- return &Reporter{e, t, "", s, d, r, p, translateTimerAttributes(u), int64(d / time.Second)}
-}
-
-func Librato(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) {
- NewReporter(r, d, e, t, s, p, u).Run()
-}
-
-func (rep *Reporter) Run() {
- log.Printf("WARNING: This client has been DEPRECATED! It has been moved to https://github.com/mihasya/go-metrics-librato and will be removed from rcrowley/go-metrics on August 5th 2015")
-
- ticker := time.NewTicker(rep.Interval)
- defer ticker.Stop()
-
- metricsApi := &LibratoClient{rep.Email, rep.Token}
-
- for now := range ticker.C {
- var metrics Batch
-
- var err error
- if metrics, err = rep.BuildRequest(now, rep.Registry); err != nil {
- log.Printf("ERROR constructing librato request body %s", err)
- continue
- }
-
- if err := metricsApi.PostMetrics(metrics); err != nil {
- log.Printf("ERROR sending metrics to librato %s", err)
- continue
- }
- }
-}
-
-// calculate sum of squares from data provided by metrics.Histogram
-// see http://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methods
-func sumSquares(icount int64, mean, stDev float64) float64 {
- count := float64(icount)
- sumSquared := math.Pow(count*mean, 2)
- sumSquares := math.Pow(count*stDev, 2) + sumSquared/count
- if math.IsNaN(sumSquares) {
- return 0.0
- }
-
- return sumSquares
-}
-func sumSquaresTimer(t metrics.TimerSnapshot) float64 {
- count := float64(t.Count())
- sumSquared := math.Pow(count*t.Mean(), 2)
-
- sumSquares := math.Pow(count*t.StdDev(), 2) + sumSquared/count
- if math.IsNaN(sumSquares) {
- return 0.0
- }
-
- return sumSquares
-}
-
-func (rep *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot Batch, err error) {
- snapshot = Batch{
- // coerce timestamps to a stepping fn so that they line up in Librato graphs
- MeasureTime: (now.Unix() / rep.intervalSec) * rep.intervalSec,
- Source: rep.Source,
- }
- snapshot.Gauges = make([]Measurement, 0)
- snapshot.Counters = make([]Measurement, 0)
- histogramGaugeCount := 1 + len(rep.Percentiles)
-
- r.Each(func(name string, metric interface{}) {
- if rep.Namespace != "" {
- name = fmt.Sprintf("%s.%s", rep.Namespace, name)
- }
-
- measurement := Measurement{}
- measurement[Period] = rep.Interval.Seconds()
-
- switch m := metric.(type) {
- case metrics.Counter:
- ms := m.Snapshot()
- if ms.Count() > 0 {
- measurement[Name] = fmt.Sprintf("%s.%s", name, "count")
- measurement[Value] = float64(ms.Count())
- measurement[Attributes] = map[string]interface{}{
- DisplayUnitsLong: Operations,
- DisplayUnitsShort: OperationsShort,
- DisplayMin: "0",
- }
- snapshot.Counters = append(snapshot.Counters, measurement)
- }
- case metrics.CounterFloat64:
- if count := m.Snapshot().Count(); count > 0 {
- measurement[Name] = fmt.Sprintf("%s.%s", name, "count")
- measurement[Value] = count
- measurement[Attributes] = map[string]interface{}{
- DisplayUnitsLong: Operations,
- DisplayUnitsShort: OperationsShort,
- DisplayMin: "0",
- }
- snapshot.Counters = append(snapshot.Counters, measurement)
- }
- case metrics.Gauge:
- measurement[Name] = name
- measurement[Value] = float64(m.Snapshot().Value())
- snapshot.Gauges = append(snapshot.Gauges, measurement)
- case metrics.GaugeFloat64:
- measurement[Name] = name
- measurement[Value] = m.Snapshot().Value()
- snapshot.Gauges = append(snapshot.Gauges, measurement)
- case metrics.GaugeInfo:
- measurement[Name] = name
- measurement[Value] = m.Snapshot().Value()
- snapshot.Gauges = append(snapshot.Gauges, measurement)
- case metrics.Histogram:
- ms := m.Snapshot()
- if ms.Count() > 0 {
- gauges := make([]Measurement, histogramGaugeCount)
- measurement[Name] = fmt.Sprintf("%s.%s", name, "hist")
- measurement[Count] = uint64(ms.Count())
- measurement[Max] = float64(ms.Max())
- measurement[Min] = float64(ms.Min())
- measurement[Sum] = float64(ms.Sum())
- measurement[SumSquares] = sumSquares(ms.Count(), ms.Mean(), ms.StdDev())
- gauges[0] = measurement
-
- for i, p := range rep.Percentiles {
- gauges[i+1] = Measurement{
- Name: fmt.Sprintf("%s.%.2f", measurement[Name], p),
- Value: ms.Percentile(p),
- Period: measurement[Period],
- }
- }
-
- snapshot.Gauges = append(snapshot.Gauges, gauges...)
- }
- case metrics.Meter:
- ms := m.Snapshot()
- measurement[Name] = name
- measurement[Value] = float64(ms.Count())
- snapshot.Counters = append(snapshot.Counters, measurement)
- snapshot.Gauges = append(snapshot.Gauges,
- Measurement{
- Name: fmt.Sprintf("%s.%s", name, "1min"),
- Value: ms.Rate1(),
- Period: int64(rep.Interval.Seconds()),
- Attributes: map[string]interface{}{
- DisplayUnitsLong: Operations,
- DisplayUnitsShort: OperationsShort,
- DisplayMin: "0",
- },
- },
- Measurement{
- Name: fmt.Sprintf("%s.%s", name, "5min"),
- Value: ms.Rate5(),
- Period: int64(rep.Interval.Seconds()),
- Attributes: map[string]interface{}{
- DisplayUnitsLong: Operations,
- DisplayUnitsShort: OperationsShort,
- DisplayMin: "0",
- },
- },
- Measurement{
- Name: fmt.Sprintf("%s.%s", name, "15min"),
- Value: ms.Rate15(),
- Period: int64(rep.Interval.Seconds()),
- Attributes: map[string]interface{}{
- DisplayUnitsLong: Operations,
- DisplayUnitsShort: OperationsShort,
- DisplayMin: "0",
- },
- },
- )
- case metrics.Timer:
- ms := m.Snapshot()
- measurement[Name] = name
- measurement[Value] = float64(ms.Count())
- snapshot.Counters = append(snapshot.Counters, measurement)
- if ms.Count() > 0 {
- libratoName := fmt.Sprintf("%s.%s", name, "timer.mean")
- gauges := make([]Measurement, histogramGaugeCount)
- gauges[0] = Measurement{
- Name: libratoName,
- Count: uint64(ms.Count()),
- Sum: ms.Mean() * float64(ms.Count()),
- Max: float64(ms.Max()),
- Min: float64(ms.Min()),
- SumSquares: sumSquaresTimer(ms),
- Period: int64(rep.Interval.Seconds()),
- Attributes: rep.TimerAttributes,
- }
-
- for i, p := range rep.Percentiles {
- gauges[i+1] = Measurement{
- Name: fmt.Sprintf("%s.timer.%2.0f", name, p*100),
- Value: ms.Percentile(p),
- Period: int64(rep.Interval.Seconds()),
- Attributes: rep.TimerAttributes,
- }
- }
-
- snapshot.Gauges = append(snapshot.Gauges, gauges...)
- snapshot.Gauges = append(snapshot.Gauges,
- Measurement{
- Name: fmt.Sprintf("%s.%s", name, "rate.1min"),
- Value: ms.Rate1(),
- Period: int64(rep.Interval.Seconds()),
- Attributes: map[string]interface{}{
- DisplayUnitsLong: Operations,
- DisplayUnitsShort: OperationsShort,
- DisplayMin: "0",
- },
- },
- Measurement{
- Name: fmt.Sprintf("%s.%s", name, "rate.5min"),
- Value: ms.Rate5(),
- Period: int64(rep.Interval.Seconds()),
- Attributes: map[string]interface{}{
- DisplayUnitsLong: Operations,
- DisplayUnitsShort: OperationsShort,
- DisplayMin: "0",
- },
- },
- Measurement{
- Name: fmt.Sprintf("%s.%s", name, "rate.15min"),
- Value: ms.Rate15(),
- Period: int64(rep.Interval.Seconds()),
- Attributes: map[string]interface{}{
- DisplayUnitsLong: Operations,
- DisplayUnitsShort: OperationsShort,
- DisplayMin: "0",
- },
- },
- )
- }
- }
- })
-
- return
-}
diff --git a/metrics/meter.go b/metrics/meter.go
index 87a1a06bfb..d0e3a139dc 100644
--- a/metrics/meter.go
+++ b/metrics/meter.go
@@ -178,7 +178,7 @@ type meterArbiter struct {
var arbiter = meterArbiter{ticker: time.NewTicker(5 * time.Second), meters: make(map[*StandardMeter]struct{})}
-// Ticks meters on the scheduled interval
+// tick meters on the scheduled interval
func (ma *meterArbiter) tick() {
for range ma.ticker.C {
ma.tickMeters()
diff --git a/metrics/metrics.go b/metrics/metrics.go
index c76f3e7489..1496161d92 100644
--- a/metrics/metrics.go
+++ b/metrics/metrics.go
@@ -28,27 +28,16 @@ import (
// for less cluttered pprof profiles.
var Enabled = false
-// EnabledExpensive is a soft-flag meant for external packages to check if costly
-// metrics gathering is allowed or not. The goal is to separate standard metrics
-// for health monitoring and debug metrics that might impact runtime performance.
-var EnabledExpensive = false
-
// enablerFlags is the CLI flag names to use to enable metrics collections.
var enablerFlags = []string{"metrics"}
// enablerEnvVars is the env var names to use to enable metrics collections.
var enablerEnvVars = []string{"GETH_METRICS"}
-// expensiveEnablerFlags is the CLI flag names to use to enable metrics collections.
-var expensiveEnablerFlags = []string{"metrics.expensive"}
-
-// expensiveEnablerEnvVars is the env var names to use to enable metrics collections.
-var expensiveEnablerEnvVars = []string{"GETH_METRICS_EXPENSIVE"}
-
// configFlag is the CLI flag name to use to start node by providing a toml based config
var configFlag = "config"
-// Init enables or disables the metrics system. Since we need this to run before
+// init enables or disables the metrics system. Since we need this to run before
// any other code gets to create meters and timers, we'll actually do an ugly hack
// and peek into the command line args for the metrics flag.
func init() {
@@ -60,14 +49,6 @@ func init() {
}
}
}
- for _, enabler := range expensiveEnablerEnvVars {
- if val, found := syscall.Getenv(enabler); found && !EnabledExpensive {
- if enable, _ := strconv.ParseBool(val); enable { // ignore error, flag parser will choke on it later
- log.Info("Enabling expensive metrics collection")
- EnabledExpensive = true
- }
- }
- }
var configFile string
@@ -88,12 +69,6 @@ func init() {
Enabled = true
}
}
- for _, enabler := range expensiveEnablerFlags {
- if !EnabledExpensive && flag == enabler {
- log.Info("Enabling expensive metrics collection")
- EnabledExpensive = true
- }
- }
}
// Update the global metrics value, if they're provided in the config file
@@ -135,7 +110,6 @@ func updateMetricsFromConfig(path string) {
// We have the values now, update them
Enabled = conf.Telemetry.Enabled
- EnabledExpensive = conf.Telemetry.Expensive
}
var threadCreateProfile = pprof.Lookup("threadcreate")
diff --git a/metrics/prometheus/collector.go b/metrics/prometheus/collector.go
index 25b258d56a..353336763b 100644
--- a/metrics/prometheus/collector.go
+++ b/metrics/prometheus/collector.go
@@ -125,12 +125,13 @@ func (c *collector) addResettingTimer(name string, m metrics.ResettingTimerSnaps
if m.Count() <= 0 {
return
}
- ps := m.Percentiles([]float64{0.50, 0.95, 0.99})
+ pv := []float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999}
+ ps := m.Percentiles(pv)
c.writeSummaryCounter(name, m.Count())
c.buff.WriteString(fmt.Sprintf(typeSummaryTpl, mutateKey(name)))
- c.writeSummaryPercentile(name, "0.50", ps[0])
- c.writeSummaryPercentile(name, "0.95", ps[1])
- c.writeSummaryPercentile(name, "0.99", ps[2])
+ for i := range pv {
+ c.writeSummaryPercentile(name, strconv.FormatFloat(pv[i], 'f', -1, 64), ps[i])
+ }
c.buff.WriteRune('\n')
}
diff --git a/metrics/prometheus/testdata/prometheus.want b/metrics/prometheus/testdata/prometheus.want
index 861c5f5cf0..a999d83801 100644
--- a/metrics/prometheus/testdata/prometheus.want
+++ b/metrics/prometheus/testdata/prometheus.want
@@ -53,9 +53,12 @@ test_meter 0
test_resetting_timer_count 6
# TYPE test_resetting_timer summary
-test_resetting_timer {quantile="0.50"} 1.25e+07
+test_resetting_timer {quantile="0.5"} 1.25e+07
+test_resetting_timer {quantile="0.75"} 4.05e+07
test_resetting_timer {quantile="0.95"} 1.2e+08
test_resetting_timer {quantile="0.99"} 1.2e+08
+test_resetting_timer {quantile="0.999"} 1.2e+08
+test_resetting_timer {quantile="0.9999"} 1.2e+08
# TYPE test_timer_count counter
test_timer_count 6
diff --git a/metrics/registry.go b/metrics/registry.go
index 5226d2f613..a3216e32e8 100644
--- a/metrics/registry.go
+++ b/metrics/registry.go
@@ -8,8 +8,8 @@ import (
"sync"
)
-// DuplicateMetric is the error returned by Registry.Register when a metric
-// already exists. If you mean to Register that metric you must first
+// DuplicateMetric is the error returned by Registry. Register when a metric
+// already exists. If you mean to Register that metric you must first
// Unregister the existing metric.
type DuplicateMetric string
@@ -20,11 +20,11 @@ func (err DuplicateMetric) Error() string {
// A Registry holds references to a set of metrics by name and can iterate
// over them, calling callback functions provided by the user.
//
-// This is an interface so as to encourage other structs to implement
+// This is an interface to encourage other structs to implement
// the Registry API as appropriate.
type Registry interface {
- // Call the given function for each registered metric.
+ // Each call the given function for each registered metric.
Each(func(string, interface{}))
// Get the metric by the given name or nil if none is registered.
@@ -33,7 +33,7 @@ type Registry interface {
// GetAll metrics in the Registry.
GetAll() map[string]map[string]interface{}
- // Gets an existing metric or registers the given one.
+ // GetOrRegister gets an existing metric or registers the given one.
// The interface can be the metric to register if not found in registry,
// or a function returning the metric for lazy instantiation.
GetOrRegister(string, interface{}) interface{}
@@ -41,7 +41,7 @@ type Registry interface {
// Register the given metric under the given name.
Register(string, interface{}) error
- // Run all registered healthchecks.
+ // RunHealthchecks run all registered healthchecks.
RunHealthchecks()
// Unregister the metric with the given name.
@@ -52,7 +52,7 @@ type orderedRegistry struct {
StandardRegistry
}
-// Call the given function for each registered metric.
+// Each call the given function for each registered metric.
func (r *orderedRegistry) Each(f func(string, interface{})) {
var names []string
reg := r.registered()
@@ -75,13 +75,13 @@ func NewOrderedRegistry() Registry {
return new(orderedRegistry)
}
-// The standard implementation of a Registry uses sync.map
+// StandardRegistry the standard implementation of a Registry uses sync.map
// of names to metrics.
type StandardRegistry struct {
metrics sync.Map
}
-// Call the given function for each registered metric.
+// Each call the given function for each registered metric.
func (r *StandardRegistry) Each(f func(string, interface{})) {
for name, i := range r.registered() {
f(name, i)
@@ -94,7 +94,7 @@ func (r *StandardRegistry) Get(name string) interface{} {
return item
}
-// Gets an existing metric or creates and registers a new one. Threadsafe
+// GetOrRegister gets an existing metric or creates and registers a new one. Threadsafe
// alternative to calling Get and Register on failure.
// The interface can be the metric to register if not found in registry,
// or a function returning the metric for lazy instantiation.
@@ -115,7 +115,7 @@ func (r *StandardRegistry) GetOrRegister(name string, i interface{}) interface{}
return item
}
-// Register the given metric under the given name. Returns a DuplicateMetric
+// Register the given metric under the given name. Returns a DuplicateMetric
// if a metric by the given name is already registered.
func (r *StandardRegistry) Register(name string, i interface{}) error {
// fast path
@@ -134,7 +134,7 @@ func (r *StandardRegistry) Register(name string, i interface{}) error {
return nil
}
-// Run all registered healthchecks.
+// RunHealthchecks run all registered healthchecks.
func (r *StandardRegistry) RunHealthchecks() {
r.metrics.Range(func(key, value any) bool {
if h, ok := value.(Healthcheck); ok {
@@ -269,7 +269,7 @@ func NewPrefixedChildRegistry(parent Registry, prefix string) Registry {
}
}
-// Call the given function for each registered metric.
+// Each call the given function for each registered metric.
func (r *PrefixedRegistry) Each(fn func(string, interface{})) {
wrappedFn := func(prefix string) func(string, interface{}) {
return func(name string, iface interface{}) {
@@ -302,7 +302,7 @@ func (r *PrefixedRegistry) Get(name string) interface{} {
return r.underlying.Get(realName)
}
-// Gets an existing metric or registers the given one.
+// GetOrRegister gets an existing metric or registers the given one.
// The interface can be the metric to register if not found in registry,
// or a function returning the metric for lazy instantiation.
func (r *PrefixedRegistry) GetOrRegister(name string, metric interface{}) interface{} {
@@ -316,7 +316,7 @@ func (r *PrefixedRegistry) Register(name string, metric interface{}) error {
return r.underlying.Register(realName, metric)
}
-// Run all registered healthchecks.
+// RunHealthchecks run all registered healthchecks.
func (r *PrefixedRegistry) RunHealthchecks() {
r.underlying.RunHealthchecks()
}
@@ -338,7 +338,7 @@ var (
AccountingRegistry = NewRegistry() // registry used in swarm
)
-// Call the given function for each registered metric.
+// Each call the given function for each registered metric.
func Each(f func(string, interface{})) {
DefaultRegistry.Each(f)
}
@@ -348,7 +348,7 @@ func Get(name string) interface{} {
return DefaultRegistry.Get(name)
}
-// Gets an existing metric or creates and registers a new one. Threadsafe
+// GetOrRegister gets an existing metric or creates and registers a new one. Threadsafe
// alternative to calling Get and Register on failure.
func GetOrRegister(name string, i interface{}) interface{} {
return DefaultRegistry.GetOrRegister(name, i)
@@ -360,7 +360,7 @@ func Register(name string, i interface{}) error {
return DefaultRegistry.Register(name, i)
}
-// Register the given metric under the given name. Panics if a metric by the
+// MustRegister register the given metric under the given name. Panics if a metric by the
// given name is already registered.
func MustRegister(name string, i interface{}) {
if err := Register(name, i); err != nil {
@@ -368,7 +368,7 @@ func MustRegister(name string, i interface{}) {
}
}
-// Run all registered healthchecks.
+// RunHealthchecks run all registered healthchecks.
func RunHealthchecks() {
DefaultRegistry.RunHealthchecks()
}
diff --git a/metrics/sample.go b/metrics/sample.go
index 17e19c6555..26433c07c3 100644
--- a/metrics/sample.go
+++ b/metrics/sample.go
@@ -3,10 +3,9 @@ package metrics
import (
"math"
"math/rand"
+ "slices"
"sync"
"time"
-
- "golang.org/x/exp/slices"
)
const rescaleThreshold = time.Hour
@@ -156,13 +155,13 @@ func (NilSample) Clear() {}
func (NilSample) Snapshot() SampleSnapshot { return (*emptySnapshot)(nil) }
func (NilSample) Update(v int64) {}
-// SamplePercentiles returns an arbitrary percentile of the slice of int64.
+// SamplePercentile returns an arbitrary percentile of the slice of int64.
func SamplePercentile(values []int64, p float64) float64 {
return CalculatePercentiles(values, []float64{p})[0]
}
// CalculatePercentiles returns a slice of arbitrary percentiles of the slice of
-// int64. This method returns interpolated results, so e.g if there are only two
+// int64. This method returns interpolated results, so e.g. if there are only two
// values, [0, 10], a 50% percentile will land between them.
//
// Note: As a side-effect, this method will also sort the slice of values.
diff --git a/metrics/sample_test.go b/metrics/sample_test.go
index 56c31a40bb..4e76805be7 100644
--- a/metrics/sample_test.go
+++ b/metrics/sample_test.go
@@ -91,13 +91,6 @@ func BenchmarkUniformSample1028(b *testing.B) {
benchmarkSample(b, NewUniformSample(1028))
}
-func min(a, b int) int {
- if a < b {
- return a
- }
- return b
-}
-
func TestExpDecaySample(t *testing.T) {
for _, tc := range []struct {
reservoirSize int
@@ -114,18 +107,18 @@ func TestExpDecaySample(t *testing.T) {
}
snap := sample.Snapshot()
if have, want := int(snap.Count()), tc.updates; have != want {
- t.Errorf("have %d want %d", have, want)
+ t.Errorf("unexpected count: have %d want %d", have, want)
}
if have, want := snap.Size(), min(tc.updates, tc.reservoirSize); have != want {
- t.Errorf("have %d want %d", have, want)
+ t.Errorf("unexpected size: have %d want %d", have, want)
}
values := snap.(*sampleSnapshot).values
if have, want := len(values), min(tc.updates, tc.reservoirSize); have != want {
- t.Errorf("have %d want %d", have, want)
+ t.Errorf("unexpected values length: have %d want %d", have, want)
}
for _, v := range values {
if v > int64(tc.updates) || v < 0 {
- t.Errorf("out of range [0, %d): %v", tc.updates, v)
+ t.Errorf("out of range [0, %d]: %v", tc.updates, v)
}
}
}
@@ -214,7 +207,7 @@ func TestUniformSample(t *testing.T) {
}
for _, v := range values {
if v > 1000 || v < 0 {
- t.Errorf("out of range [0, 100): %v\n", v)
+ t.Errorf("out of range [0, 1000]: %v\n", v)
}
}
}
@@ -277,6 +270,9 @@ func benchmarkSample(b *testing.B, s Sample) {
}
func testExpDecaySampleStatistics(t *testing.T, s SampleSnapshot) {
+ if sum := s.Sum(); sum != 496598 {
+ t.Errorf("s.Sum(): 496598 != %v\n", sum)
+ }
if count := s.Count(); count != 10000 {
t.Errorf("s.Count(): 10000 != %v\n", count)
}
diff --git a/metrics/timer.go b/metrics/timer.go
index 2da24f8a7e..6ad2218a22 100644
--- a/metrics/timer.go
+++ b/metrics/timer.go
@@ -10,7 +10,7 @@ type TimerSnapshot interface {
MeterSnapshot
}
-// Timers capture the duration and rate of events.
+// Timer capture the duration and rate of events.
type Timer interface {
Snapshot() TimerSnapshot
Stop()
@@ -105,7 +105,7 @@ func (t *StandardTimer) Stop() {
t.meter.Stop()
}
-// Record the duration of the execution of the given function.
+// Time record the duration of the execution of the given function.
func (t *StandardTimer) Time(f func()) {
ts := time.Now()
@@ -113,7 +113,7 @@ func (t *StandardTimer) Time(f func()) {
t.Update(time.Since(ts))
}
-// Record the duration of an event, in nanoseconds.
+// Update the duration of an event, in nanoseconds.
func (t *StandardTimer) Update(d time.Duration) {
t.mutex.Lock()
defer t.mutex.Unlock()
@@ -121,7 +121,7 @@ func (t *StandardTimer) Update(d time.Duration) {
t.meter.Mark(1)
}
-// Record the duration of an event that started at a time and ends now.
+// UpdateSince update the duration of an event that started at a time and ends now.
// The record uses nanoseconds.
func (t *StandardTimer) UpdateSince(ts time.Time) {
t.Update(time.Since(ts))
diff --git a/metrics/writer.go b/metrics/writer.go
index b8f9128b0a..79abb4620a 100644
--- a/metrics/writer.go
+++ b/metrics/writer.go
@@ -3,10 +3,9 @@ package metrics
import (
"fmt"
"io"
+ "slices"
"strings"
"time"
-
- "golang.org/x/exp/slices"
)
// Write sorts writes each metric in the given registry periodically to the
diff --git a/metrics/writer_test.go b/metrics/writer_test.go
index 8376bf8975..edcfe955ab 100644
--- a/metrics/writer_test.go
+++ b/metrics/writer_test.go
@@ -1,9 +1,8 @@
package metrics
import (
+ "slices"
"testing"
-
- "golang.org/x/exp/slices"
)
func TestMetricsSorting(t *testing.T) {
diff --git a/miner/fake_miner.go b/miner/fake_miner.go
index 7c835ee2df..08d45e3f46 100644
--- a/miner/fake_miner.go
+++ b/miner/fake_miner.go
@@ -24,7 +24,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/tests/bor/mocks"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
type DefaultBorMiner struct {
@@ -93,7 +93,7 @@ func createBorMiner(t *testing.T, ethAPIMock api.Caller, spanner bor.Spanner, he
blockchain := &testBlockChainBor{chainConfig, statedb, 10000000, new(event.Feed)}
pool := legacypool.New(testTxPoolConfigBor, blockchain)
- txpool, _ := txpool.New(new(big.Int).SetUint64(testTxPoolConfigBor.PriceLimit), blockchain, []txpool.SubPool{pool})
+ txpool, _ := txpool.New(testTxPoolConfigBor.PriceLimit, blockchain, []txpool.SubPool{pool})
backend := NewMockBackendBor(bc, txpool)
@@ -132,7 +132,7 @@ func NewDBForFakes(t TensingObject) (ethdb.Database, *core.Genesis, *params.Chai
addr := common.HexToAddress("12345")
genesis := core.DeveloperGenesisBlock(11_500_000, &addr)
- chainConfig, _, err := core.SetupGenesisBlock(chainDB, trie.NewDatabase(chainDB, trie.HashDefaults), genesis)
+ chainConfig, _, err := core.SetupGenesisBlock(chainDB, triedb.NewDatabase(chainDB, triedb.HashDefaults), genesis)
if err != nil {
t.Fatalf("can't create new chain config: %v", err)
}
@@ -212,7 +212,7 @@ func (bc *testBlockChainBor) CurrentBlock() *types.Header {
}
func (bc *testBlockChainBor) GetBlock(hash common.Hash, number uint64) *types.Block {
- return types.NewBlock(bc.CurrentBlock(), nil, nil, nil, trie.NewStackTrie(nil))
+ return types.NewBlock(bc.CurrentBlock(), nil, nil, nil)
}
func (bc *testBlockChainBor) StateAt(common.Hash) (*state.StateDB, error) {
diff --git a/miner/miner.go b/miner/miner.go
index e3f11480b8..eba1d686f2 100644
--- a/miner/miner.go
+++ b/miner/miner.go
@@ -48,7 +48,6 @@ type Backend interface {
type Config struct {
Etherbase common.Address `toml:",omitempty"` // Public address for block mining rewards
ExtraData hexutil.Bytes `toml:",omitempty"` // Block extra data set by the miner
- GasFloor uint64 // Target gas floor for mined blocks.
GasCeil uint64 // Target gas ceiling for mined blocks.
GasPrice *big.Int // Minimum gas price for mining a transaction
Recommit time.Duration // The time interval for miner to re-create mining work.
@@ -59,8 +58,8 @@ type Config struct {
// DefaultConfig contains default settings for miner.
var DefaultConfig = Config{
- GasCeil: 30000000,
- GasPrice: big.NewInt(params.BorDefaultMinerGasPrice), // enforces minimum gas price of 30 gwei in bor
+ GasCeil: 30_000_000,
+ GasPrice: big.NewInt(params.BorDefaultMinerGasPrice), // enforces minimum gas price of 25 gwei in bor
// The default recommit time is chosen as two seconds since
// consensus-layer usually will wait a half slot of time(6s)
@@ -231,7 +230,7 @@ func (miner *Miner) SetRecommitInterval(interval time.Duration) {
// Pending returns the currently pending block and associated state. The returned
// values can be nil in case the pending block is not initialized
-func (miner *Miner) Pending() (*types.Block, *state.StateDB) {
+func (miner *Miner) Pending() (*types.Block, types.Receipts, *state.StateDB) {
return miner.worker.pending()
}
@@ -245,12 +244,6 @@ func (miner *Miner) PendingBlock() *types.Block {
return miner.worker.pendingBlock()
}
-// PendingBlockAndReceipts returns the currently pending block and corresponding receipts.
-// The returned values can be nil in case the pending block is not initialized.
-func (miner *Miner) PendingBlockAndReceipts() (*types.Block, types.Receipts) {
- return miner.worker.pendingBlockAndReceipts()
-}
-
func (miner *Miner) SetEtherbase(addr common.Address) {
miner.worker.setEtherbase(addr)
}
diff --git a/miner/miner_test.go b/miner/miner_test.go
index 0181c4bc88..1a3e8edc22 100644
--- a/miner/miner_test.go
+++ b/miner/miner_test.go
@@ -18,7 +18,6 @@
package miner
import (
- "errors"
"math/big"
"testing"
"time"
@@ -59,10 +58,6 @@ func (m *mockBackend) TxPool() *txpool.TxPool {
return m.txPool
}
-func (m *mockBackend) StateAtBlock(block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (statedb *state.StateDB, err error) {
- return nil, errors.New("not supported")
-}
-
// nolint : unused
type testBlockChain struct {
root common.Hash
@@ -87,7 +82,7 @@ func (bc *testBlockChain) CurrentBlock() *types.Header {
// nolint : unused
func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block {
- return types.NewBlock(bc.CurrentBlock(), nil, nil, nil, trie.NewStackTrie(nil))
+ return types.NewBlock(bc.CurrentBlock(), nil, nil, trie.NewStackTrie(nil))
}
// nolint : unused
@@ -345,6 +340,20 @@ func waitForMiningState(t *testing.T, m *Miner, mining bool) {
t.Fatalf("Mining() == %t, want %t", state, mining)
}
+// func TestBuildPendingBlocks(t *testing.T) {
+// miner := createMiner(t)
+// var wg sync.WaitGroup
+// wg.Add(1)
+// go func() {
+// defer wg.Done()
+// block, _, _ := miner.Pending()
+// if block == nil {
+// t.Error("Pending failed")
+// }
+// }()
+// wg.Wait()
+// }
+
// func minerTestGenesisBlock(period uint64, gasLimit uint64, faucet common.Address) *core.Genesis {
// config := *params.AllCliqueProtocolChanges
// config.Clique = ¶ms.CliqueConfig{
@@ -359,7 +368,7 @@ func waitForMiningState(t *testing.T, m *Miner, mining bool) {
// GasLimit: gasLimit,
// BaseFee: big.NewInt(params.InitialBaseFee),
// Difficulty: big.NewInt(1),
-// Alloc: map[common.Address]core.GenesisAccount{
+// Alloc: map[common.Address]types.Account{
// common.BytesToAddress([]byte{1}): {Balance: big.NewInt(1)}, // ECRecover
// common.BytesToAddress([]byte{2}): {Balance: big.NewInt(1)}, // SHA256
// common.BytesToAddress([]byte{3}): {Balance: big.NewInt(1)}, // RIPEMD
@@ -391,7 +400,7 @@ func waitForMiningState(t *testing.T, m *Miner, mining bool) {
// // Create consensus engine
// engine := clique.New(chainConfig.Clique, chainDB)
// // Create Ethereum backend
-// bc, err := core.NewBlockChain(chainDB, nil, genesis, nil, engine, vm.Config{}, nil, nil, nil)
+// bc, err := core.NewBlockChain(chainDB, nil, genesis, nil, engine, vm.Config{}, nil, nil)
// if err != nil {
// t.Fatalf("can't create new chain %v", err)
// }
diff --git a/miner/ordering.go b/miner/ordering.go
index 828d53d241..b5400be99a 100644
--- a/miner/ordering.go
+++ b/miner/ordering.go
@@ -21,28 +21,31 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/holiman/uint256"
)
// txWithMinerFee wraps a transaction with its gas price or effective miner gasTipCap
type txWithMinerFee struct {
tx *txpool.LazyTransaction
from common.Address
- fees *big.Int
+ fees *uint256.Int
}
// newTxWithMinerFee creates a wrapped transaction, calculating the effective
// miner gasTipCap if a base fee is provided.
// Returns error in case of a negative effective miner gasTipCap.
-func newTxWithMinerFee(tx *txpool.LazyTransaction, from common.Address, baseFee *big.Int) (*txWithMinerFee, error) {
- tip := new(big.Int).Set(tx.GasTipCap)
+func newTxWithMinerFee(tx *txpool.LazyTransaction, from common.Address, baseFee *uint256.Int) (*txWithMinerFee, error) {
+ tip := new(uint256.Int).Set(tx.GasTipCap)
if baseFee != nil {
if tx.GasFeeCap.Cmp(baseFee) < 0 {
return nil, types.ErrGasFeeCapTooLow
}
- tip = math.BigMin(tx.GasTipCap, new(big.Int).Sub(tx.GasFeeCap, baseFee))
+ tip = new(uint256.Int).Sub(tx.GasFeeCap, baseFee)
+ if tip.Gt(tx.GasTipCap) {
+ tip = tx.GasTipCap
+ }
}
return &txWithMinerFee{
tx: tx,
@@ -87,7 +90,7 @@ type transactionsByPriceAndNonce struct {
txs map[common.Address][]*txpool.LazyTransaction // Per account nonce-sorted list of transactions
heads txByPriceAndTime // Next transaction for each unique account (price heap)
signer types.Signer // Signer for the set of transactions
- baseFee *big.Int // Current base fee
+ baseFee *uint256.Int // Current base fee
}
// newTransactionsByPriceAndNonce creates a transaction set that can retrieve
@@ -96,10 +99,15 @@ type transactionsByPriceAndNonce struct {
// Note, the input map is reowned so the caller should not interact any more with
// if after providing it to the constructor.
func newTransactionsByPriceAndNonce(signer types.Signer, txs map[common.Address][]*txpool.LazyTransaction, baseFee *big.Int) *transactionsByPriceAndNonce {
+ // Convert the basefee from header format to uint256 format
+ var baseFeeUint *uint256.Int
+ if baseFee != nil {
+ baseFeeUint = uint256.MustFromBig(baseFee)
+ }
// Initialize a price and received time based heap with the head transactions
heads := make(txByPriceAndTime, 0, len(txs))
for from, accTxs := range txs {
- wrapped, err := newTxWithMinerFee(accTxs[0], from, baseFee)
+ wrapped, err := newTxWithMinerFee(accTxs[0], from, baseFeeUint)
if err != nil {
delete(txs, from)
continue
@@ -114,12 +122,12 @@ func newTransactionsByPriceAndNonce(signer types.Signer, txs map[common.Address]
txs: txs,
heads: heads,
signer: signer,
- baseFee: baseFee,
+ baseFee: baseFeeUint,
}
}
// Peek returns the next transaction by price.
-func (t *transactionsByPriceAndNonce) Peek() (*txpool.LazyTransaction, *big.Int) {
+func (t *transactionsByPriceAndNonce) Peek() (*txpool.LazyTransaction, *uint256.Int) {
if len(t.heads) == 0 {
return nil, nil
}
@@ -149,3 +157,14 @@ func (t *transactionsByPriceAndNonce) GetTxs() int {
func (t *transactionsByPriceAndNonce) Pop() {
heap.Pop(&t.heads)
}
+
+// Empty returns if the price heap is empty. It can be used to check it simpler
+// than calling peek and checking for nil return.
+func (t *transactionsByPriceAndNonce) Empty() bool {
+ return len(t.heads) == 0
+}
+
+// Clear removes the entire content of the heap.
+func (t *transactionsByPriceAndNonce) Clear() {
+ t.heads, t.txs = nil, nil
+}
diff --git a/miner/ordering_test.go b/miner/ordering_test.go
index d2de9b9f34..3587a835c8 100644
--- a/miner/ordering_test.go
+++ b/miner/ordering_test.go
@@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/holiman/uint256"
)
func TestTransactionPriceNonceSortLegacy(t *testing.T) {
@@ -92,8 +93,8 @@ func testTransactionPriceNonceSort(t *testing.T, baseFee *big.Int) {
Hash: tx.Hash(),
Tx: tx,
Time: tx.Time(),
- GasFeeCap: tx.GasFeeCap(),
- GasTipCap: tx.GasTipCap(),
+ GasFeeCap: uint256.MustFromBig(tx.GasFeeCap()),
+ GasTipCap: uint256.MustFromBig(tx.GasTipCap()),
Gas: tx.Gas(),
BlobGas: tx.BlobGas(),
})
@@ -160,8 +161,8 @@ func TestTransactionTimeSort(t *testing.T) {
Hash: tx.Hash(),
Tx: tx,
Time: tx.Time(),
- GasFeeCap: tx.GasFeeCap(),
- GasTipCap: tx.GasTipCap(),
+ GasFeeCap: uint256.MustFromBig(tx.GasFeeCap()),
+ GasTipCap: uint256.MustFromBig(tx.GasTipCap()),
Gas: tx.Gas(),
BlobGas: tx.BlobGas(),
})
diff --git a/miner/payload_building.go b/miner/payload_building.go
index 0b12728652..e085278a65 100644
--- a/miner/payload_building.go
+++ b/miner/payload_building.go
@@ -35,17 +35,17 @@ import (
// Check engine-api specification for more details.
// https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#payloadattributesv3
type BuildPayloadArgs struct {
- Parent common.Hash // The parent block to build payload on top
- Timestamp uint64 // The provided timestamp of generated payload
- FeeRecipient common.Address // The provided recipient address for collecting transaction fee
- Random common.Hash // The provided randomness value
- Withdrawals types.Withdrawals // The provided withdrawals
- BeaconRoot *common.Hash // The provided beaconRoot (Cancun)
+ Parent common.Hash // The parent block to build payload on top
+ Timestamp uint64 // The provided timestamp of generated payload
+ FeeRecipient common.Address // The provided recipient address for collecting transaction fee
+ Random common.Hash // The provided randomness value
+ Withdrawals types.Withdrawals // The provided withdrawals
+ BeaconRoot *common.Hash // The provided beaconRoot (Cancun)
+ Version engine.PayloadVersion // Versioning byte for payload id calculation.
}
// Id computes an 8-byte identifier by hashing the components of the payload arguments.
func (args *BuildPayloadArgs) Id() engine.PayloadID {
- // Hash
hasher := sha256.New()
hasher.Write(args.Parent[:])
_ = binary.Write(hasher, binary.BigEndian, args.Timestamp)
@@ -58,7 +58,7 @@ func (args *BuildPayloadArgs) Id() engine.PayloadID {
var out engine.PayloadID
copy(out[:], hasher.Sum(nil)[:8])
-
+ out[0] = byte(args.Version)
return out
}
@@ -194,6 +194,7 @@ func (w *worker) buildPayload(args *BuildPayloadArgs) (*Payload, error) {
beaconRoot: args.BeaconRoot,
noTxs: true,
}
+
empty := w.getSealingBlock(emptyParams)
if empty.err != nil {
return nil, empty.err
@@ -233,9 +234,10 @@ func (w *worker) buildPayload(args *BuildPayloadArgs) (*Payload, error) {
r := w.getSealingBlock(fullParams)
if r.err == nil {
payload.update(r, time.Since(start))
+ } else {
+ log.Info("Error while generating work", "id", payload.id, "err", r.err)
}
-
- timer.Reset(w.recommit)
+ timer.Reset(w.config.Recommit)
case <-payload.stop:
log.Info("Stopping work on payload", "id", payload.id, "reason", "delivery")
return
diff --git a/miner/payload_building_test.go b/miner/payload_building_test.go
index e263ff998b..e152f7bdc7 100644
--- a/miner/payload_building_test.go
+++ b/miner/payload_building_test.go
@@ -29,9 +29,7 @@ import (
"github.com/ethereum/go-ethereum/params"
)
-// nolint : paralleltest
func TestBuildPayload(t *testing.T) {
- t.Parallel()
var (
db = rawdb.NewMemoryDatabase()
recipient = common.HexToAddress("0xdeadbeef")
diff --git a/miner/pending.go b/miner/pending.go
new file mode 100644
index 0000000000..96f2065e40
--- /dev/null
+++ b/miner/pending.go
@@ -0,0 +1,72 @@
+// Copyright 2024 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 .
+
+//go:build ignore
+// +build ignore
+
+package miner
+
+// nolint : unused
+
+import (
+ "sync"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+// pendingTTL indicates the period of time a generated pending block should
+// exist to serve RPC requests before being discarded if the parent block
+// has not changed yet. The value is chosen to align with the recommit interval.
+const pendingTTL = 2 * time.Second
+
+// pending wraps a pending block with additional metadata.
+type pending struct {
+ created time.Time
+ parentHash common.Hash
+ result *newPayloadResult
+ lock sync.Mutex
+}
+
+// resolve retrieves the cached pending result if it's available. Nothing will be
+// returned if the parentHash is not matched or the result is already too old.
+//
+// Note, don't modify the returned payload result.
+func (p *pending) resolve(parentHash common.Hash) *newPayloadResult {
+ p.lock.Lock()
+ defer p.lock.Unlock()
+
+ if p.result == nil {
+ return nil
+ }
+ if parentHash != p.parentHash {
+ return nil
+ }
+ if time.Since(p.created) > pendingTTL {
+ return nil
+ }
+ return p.result
+}
+
+// update refreshes the cached pending block with newly created one.
+func (p *pending) update(parent common.Hash, result *newPayloadResult) {
+ p.lock.Lock()
+ defer p.lock.Unlock()
+
+ p.parentHash = parent
+ p.result = result
+ p.created = time.Now()
+}
diff --git a/miner/stress/clique/main.go b/miner/stress/clique/main.go
deleted file mode 100644
index 6fdde7745f..0000000000
--- a/miner/stress/clique/main.go
+++ /dev/null
@@ -1,235 +0,0 @@
-// Copyright 2018 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 .
-
-// This file contains a miner stress test based on the Clique consensus engine.
-package main
-
-import (
- "bytes"
- "crypto/ecdsa"
- "math/big"
- "math/rand"
- "os"
- "os/signal"
- "time"
-
- "github.com/ethereum/go-ethereum/accounts/keystore"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/fdlimit"
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/txpool/legacypool"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/eth"
- "github.com/ethereum/go-ethereum/eth/downloader"
- "github.com/ethereum/go-ethereum/eth/ethconfig"
- "github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/miner"
- "github.com/ethereum/go-ethereum/node"
- "github.com/ethereum/go-ethereum/p2p"
- "github.com/ethereum/go-ethereum/p2p/enode"
- "github.com/ethereum/go-ethereum/params"
-)
-
-func main() {
- log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
- fdlimit.Raise(2048)
-
- // Generate a batch of accounts to seal and fund with
- faucets := make([]*ecdsa.PrivateKey, 128)
- for i := 0; i < len(faucets); i++ {
- faucets[i], _ = crypto.GenerateKey()
- }
-
- sealers := make([]*ecdsa.PrivateKey, 4)
- for i := 0; i < len(sealers); i++ {
- sealers[i], _ = crypto.GenerateKey()
- }
- // Create a Clique network based off of the Sepolia config
- genesis := makeGenesis(faucets, sealers)
-
- // Handle interrupts.
- interruptCh := make(chan os.Signal, 5)
- signal.Notify(interruptCh, os.Interrupt)
-
- var (
- stacks []*node.Node
- nodes []*eth.Ethereum
- enodes []*enode.Node
- )
-
- for _, sealer := range sealers {
- // Start the node and wait until it's up
- stack, ethBackend, err := makeSealer(genesis)
- if err != nil {
- panic(err)
- }
- defer stack.Close()
-
- for stack.Server().NodeInfo().Ports.Listener == 0 {
- time.Sleep(250 * time.Millisecond)
- }
- // Connect the node to all the previous ones
- for _, n := range enodes {
- stack.Server().AddPeer(n)
- }
- // Start tracking the node and its enode
- stacks = append(stacks, stack)
- nodes = append(nodes, ethBackend)
- enodes = append(enodes, stack.Server().Self())
-
- // Inject the signer key and start sealing with it
- ks := keystore.NewKeyStore(stack.KeyStoreDir(), keystore.LightScryptN, keystore.LightScryptP)
-
- signer, err := ks.ImportECDSA(sealer, "")
- if err != nil {
- panic(err)
- }
- if err := ks.Unlock(signer, ""); err != nil {
- panic(err)
- }
-
- stack.AccountManager().AddBackend(ks)
- }
-
- // Iterate over all the nodes and start signing on them
- time.Sleep(3 * time.Second)
-
- for _, node := range nodes {
- if err := node.StartMining(); err != nil {
- panic(err)
- }
- }
-
- time.Sleep(3 * time.Second)
-
- // Start injecting transactions from the faucet like crazy
- nonces := make([]uint64, len(faucets))
-
- for {
- // Stop when interrupted.
- select {
- case <-interruptCh:
- for _, node := range stacks {
- node.Close()
- }
-
- return
- default:
- }
-
- // Pick a random signer node
- index := rand.Intn(len(faucets))
- backend := nodes[index%len(nodes)]
-
- // Create a self transaction and inject into the pool
- tx, err := types.SignTx(types.NewTransaction(nonces[index], crypto.PubkeyToAddress(faucets[index].PublicKey), new(big.Int), 21000, big.NewInt(100000000000), nil), types.HomesteadSigner{}, faucets[index])
- if err != nil {
- panic(err)
- }
- if err := backend.TxPool().Add([]*types.Transaction{tx}, true, false); err != nil {
- panic(err)
- }
-
- nonces[index]++
-
- // Wait if we're too saturated
- if pend, _ := backend.TxPool().Stats(); pend > 2048 {
- time.Sleep(100 * time.Millisecond)
- }
- }
-}
-
-// makeGenesis creates a custom Clique genesis block based on some pre-defined
-// signer and faucet accounts.
-func makeGenesis(faucets []*ecdsa.PrivateKey, sealers []*ecdsa.PrivateKey) *core.Genesis {
- // Create a Clique network based off of the Sepolia config
- genesis := core.DefaultSepoliaGenesisBlock()
- genesis.GasLimit = 25000000
-
- genesis.Config.ChainID = big.NewInt(18)
- genesis.Config.Clique.Period = 1
-
- genesis.Alloc = core.GenesisAlloc{}
- for _, faucet := range faucets {
- genesis.Alloc[crypto.PubkeyToAddress(faucet.PublicKey)] = core.GenesisAccount{
- Balance: new(big.Int).Exp(big.NewInt(2), big.NewInt(128), nil),
- }
- }
- // Sort the signers and embed into the extra-data section
- signers := make([]common.Address, len(sealers))
- for i, sealer := range sealers {
- signers[i] = crypto.PubkeyToAddress(sealer.PublicKey)
- }
-
- for i := 0; i < len(signers); i++ {
- for j := i + 1; j < len(signers); j++ {
- if bytes.Compare(signers[i][:], signers[j][:]) > 0 {
- signers[i], signers[j] = signers[j], signers[i]
- }
- }
- }
-
- genesis.ExtraData = make([]byte, 32+len(signers)*common.AddressLength+65)
- for i, signer := range signers {
- copy(genesis.ExtraData[32+i*common.AddressLength:], signer[:])
- }
- // Return the genesis block for initialization
- return genesis
-}
-
-func makeSealer(genesis *core.Genesis) (*node.Node, *eth.Ethereum, error) {
- // Define the basic configurations for the Ethereum node
- datadir, _ := os.MkdirTemp("", "")
-
- config := &node.Config{
- Name: "geth",
- Version: params.Version,
- DataDir: datadir,
- P2P: p2p.Config{
- ListenAddr: "0.0.0.0:0",
- NoDiscovery: true,
- MaxPeers: 25,
- },
- }
- // Start the node and configure a full Ethereum node on it
- stack, err := node.New(config)
- if err != nil {
- return nil, nil, err
- }
- // Create and register the backend
- ethBackend, err := eth.New(stack, ðconfig.Config{
- Genesis: genesis,
- NetworkId: genesis.Config.ChainID.Uint64(),
- SyncMode: downloader.FullSync,
- DatabaseCache: 256,
- DatabaseHandles: 256,
- TxPool: legacypool.DefaultConfig,
- GPO: ethconfig.Defaults.GPO,
- Miner: miner.Config{
- GasCeil: genesis.GasLimit * 11 / 10,
- GasPrice: big.NewInt(1),
- Recommit: time.Second,
- },
- })
- if err != nil {
- return nil, nil, err
- }
-
- err = stack.Start()
-
- return stack, ethBackend, err
-}
diff --git a/miner/test_backend.go b/miner/test_backend.go
index 035acce037..b18fc1c495 100644
--- a/miner/test_backend.go
+++ b/miner/test_backend.go
@@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"
- "math/big"
"os"
"sync"
"sync/atomic"
@@ -168,15 +167,15 @@ func (w *worker) mainLoopWithDelay(ctx context.Context, delay uint, opcodeDelay
Hash: tx.Hash(),
Tx: nil, // Do *not* set this! We need to resolve it later to pull blobs in
Time: tx.Time(),
- GasFeeCap: tx.GasFeeCap(),
- GasTipCap: tx.GasTipCap(),
+ GasFeeCap: uint256.NewInt(tx.GasFeeCap().Uint64()),
+ GasTipCap: uint256.NewInt(tx.GasTipCap().Uint64()),
Gas: tx.Gas(),
BlobGas: tx.BlobGas(),
})
}
txset := newTransactionsByPriceAndNonce(w.current.signer, txs, w.current.header.BaseFee)
tcount := w.current.tcount
- w.commitTransactions(w.current, txset, nil, new(big.Int), context.Background())
+ w.commitTransactions(w.current, txset, nil, nil, new(uint256.Int), context.Background())
// Only update the snapshot if any new transactons were added
// to the pending block
@@ -322,7 +321,7 @@ func (w *worker) fillTransactionsWithDelay(ctx context.Context, interrupt *atomi
// Split the pending transactions into locals and remotes
// Fill the block with all available pending transactions.
- pending := w.eth.TxPool().Pending(true)
+ pending := w.eth.TxPool().Pending(txpool.PendingFilter{})
localTxs, remoteTxs := make(map[common.Address][]*txpool.LazyTransaction), pending
var (
@@ -394,7 +393,7 @@ func (w *worker) fillTransactionsWithDelay(ctx context.Context, interrupt *atomi
tracing.Exec(ctx, "", "worker.SplittingTransactions", func(ctx context.Context, span trace.Span) {
prePendingTime := time.Now()
- pending := w.eth.TxPool().Pending(true)
+ pending := w.eth.TxPool().Pending(txpool.PendingFilter{})
remoteTxs = pending
postPendingTime := time.Now()
@@ -540,6 +539,8 @@ func (w *worker) commitTransactionsWithDelay(env *environment, txs *transactions
}(chDeps)
}
+ var lastTxHash common.Hash
+
mainloop:
for {
if interruptCtx != nil {
@@ -551,7 +552,7 @@ mainloop:
select {
case <-interruptCtx.Done():
txCommitInterruptCounter.Inc(1)
- log.Warn("Tx Level Interrupt")
+ log.Warn("Tx Level Interrupt", "hash", lastTxHash)
break mainloop
default:
}
@@ -573,6 +574,7 @@ mainloop:
if ltx == nil {
break
}
+ lastTxHash = ltx.Hash
// If we don't have enough space for the next transaction, skip the account.
if env.gasPool.Gas() < ltx.Gas {
log.Trace("Not enough gas left for transaction", "hash", ltx.Hash, "left", env.gasPool.Gas(), "needed", ltx.Gas)
@@ -598,14 +600,14 @@ mainloop:
// not prioritising conditional transaction, yet.
//nolint:nestif
if options := tx.GetOptions(); options != nil {
- if err := env.header.ValidateBlockNumberOptions4337(options.BlockNumberMin, options.BlockNumberMax); err != nil {
+ if err := env.header.ValidateBlockNumberOptionsPIP15(options.BlockNumberMin, options.BlockNumberMax); err != nil {
log.Trace("Dropping conditional transaction", "from", from, "hash", tx.Hash(), "reason", err)
txs.Pop()
continue
}
- if err := env.header.ValidateTimestampOptions4337(options.TimestampMin, options.TimestampMax); err != nil {
+ if err := env.header.ValidateTimestampOptionsPIP15(options.TimestampMin, options.TimestampMax); err != nil {
log.Trace("Dropping conditional transaction", "from", from, "hash", tx.Hash(), "reason", err)
txs.Pop()
diff --git a/miner/worker.go b/miner/worker.go
index 536ff80156..267f9ec309 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -37,11 +37,11 @@ import (
"go.opentelemetry.io/otel/trace"
"github.com/ethereum/go-ethereum/common"
- cmath "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/common/tracing"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/bor"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
+ "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/blockstm"
"github.com/ethereum/go-ethereum/core/state"
@@ -237,7 +237,7 @@ type worker struct {
mu sync.RWMutex // The lock used to protect the coinbase and extra fields
coinbase common.Address
extra []byte
- tip *big.Int // Minimum tip needed for non-local transaction to include them
+ tip *uint256.Int // Minimum tip needed for non-local transaction to include them
pendingMu sync.RWMutex
pendingTasks map[common.Hash]*task
@@ -296,7 +296,7 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus
isLocalBlock: isLocalBlock,
coinbase: config.Etherbase,
extra: config.ExtraData,
- tip: config.GasPrice,
+ tip: uint256.MustFromBig(config.GasPrice),
pendingTasks: make(map[common.Hash]*task),
txsCh: make(chan core.NewTxsEvent, txChanSize),
chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
@@ -401,7 +401,7 @@ func (w *worker) setExtra(extra []byte) {
func (w *worker) setGasTip(tip *big.Int) {
w.mu.Lock()
defer w.mu.Unlock()
- w.tip = tip
+ w.tip = uint256.MustFromBig(tip)
}
// setRecommitInterval updates the interval for miner sealing work recommitting.
@@ -414,15 +414,15 @@ func (w *worker) setRecommitInterval(interval time.Duration) {
// pending returns the pending state and corresponding block. The returned
// values can be nil in case the pending block is not initialized.
-func (w *worker) pending() (*types.Block, *state.StateDB) {
+func (w *worker) pending() (*types.Block, types.Receipts, *state.StateDB) {
w.snapshotMu.RLock()
defer w.snapshotMu.RUnlock()
if w.snapshotState == nil {
- return nil, nil
+ return nil, nil, nil
}
- return w.snapshotBlock, w.snapshotState.Copy()
+ return w.snapshotBlock, w.snapshotReceipts, w.snapshotState.Copy()
}
// pendingBlock returns pending block. The returned block can be nil in case the
@@ -434,15 +434,6 @@ func (w *worker) pendingBlock() *types.Block {
return w.snapshotBlock
}
-// pendingBlockAndReceipts returns pending block and corresponding receipts.
-// The returned values can be nil in case the pending block is not initialized.
-func (w *worker) pendingBlockAndReceipts() (*types.Block, types.Receipts) {
- w.snapshotMu.RLock()
- defer w.snapshotMu.RUnlock()
-
- return w.snapshotBlock, w.snapshotReceipts
-}
-
// start sets the running status as 1 and triggers new work submitting.
func (w *worker) start() {
w.running.Store(true)
@@ -649,15 +640,18 @@ func (w *worker) mainLoop(ctx context.Context) {
Hash: tx.Hash(),
Tx: nil, // Do *not* set this! We need to resolve it later to pull blobs in
Time: tx.Time(),
- GasFeeCap: tx.GasFeeCap(),
- GasTipCap: tx.GasTipCap(),
+ GasFeeCap: uint256.MustFromBig(tx.GasFeeCap()),
+ GasTipCap: uint256.MustFromBig(tx.GasTipCap()),
Gas: tx.Gas(),
BlobGas: tx.BlobGas(),
})
}
- txset := newTransactionsByPriceAndNonce(w.current.signer, txs, w.current.header.BaseFee)
+ plainTxs := newTransactionsByPriceAndNonce(w.current.signer, txs, w.current.header.BaseFee) // Mixed bag of everrything, yolo
+ blobTxs := newTransactionsByPriceAndNonce(w.current.signer, nil, w.current.header.BaseFee) // Empty bag, don't bother optimising
+
tcount := w.current.tcount
- w.commitTransactions(w.current, txset, nil, new(big.Int), context.Background())
+
+ w.commitTransactions(w.current, plainTxs, blobTxs, nil, new(uint256.Int), context.Background())
// Only update the snapshot if any new transactons were added
// to the pending block
@@ -861,7 +855,8 @@ func (w *worker) makeEnv(parent *types.Header, header *types.Header, coinbase co
return nil, err
}
- state.StartPrefetcher("miner")
+ // todo: @anshalshukla - check if witness is required
+ state.StartPrefetcher("miner", nil)
// Note the passed coinbase may be different with header.Coinbase.
env := &environment{
@@ -886,8 +881,9 @@ func (w *worker) updateSnapshot(env *environment) {
w.snapshotBlock = types.NewBlock(
env.header,
- env.txs,
- nil,
+ &types.Body{
+ Transactions: env.txs,
+ },
env.receipts,
trie.NewStackTrie(nil),
)
@@ -917,7 +913,7 @@ func (w *worker) commitTransaction(env *environment, tx *types.Transaction, inte
return receipt.Logs, nil
}
-func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAndNonce, interrupt *atomic.Int32, minTip *big.Int, interruptCtx context.Context) error {
+func (w *worker) commitTransactions(env *environment, plainTxs, blobTxs *transactionsByPriceAndNonce, interrupt *atomic.Int32, minTip *uint256.Int, interruptCtx context.Context) error {
gasLimit := env.header.GasLimit
if env.gasPool == nil {
env.gasPool = new(core.GasPool).AddGas(gasLimit)
@@ -956,6 +952,8 @@ func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAn
}(chDeps)
}
+ var lastTxHash common.Hash
+
mainloop:
for {
// Check interruption signal and abort building if it's fired.
@@ -974,7 +972,7 @@ mainloop:
select {
case <-interruptCtx.Done():
txCommitInterruptCounter.Inc(1)
- log.Warn("Tx Level Interrupt")
+ log.Warn("Tx Level Interrupt", "hash", lastTxHash)
break mainloop
default:
}
@@ -985,11 +983,38 @@ mainloop:
log.Trace("Not enough gas for further transactions", "have", env.gasPool, "want", params.TxGas)
break
}
+ // If we don't have enough blob space for any further blob transactions,
+ // skip that list altogether
+ if !blobTxs.Empty() && env.blobs*params.BlobTxBlobGasPerBlob >= params.MaxBlobGasPerBlock {
+ log.Trace("Not enough blob space for further blob transactions")
+ blobTxs.Clear()
+ // Fall though to pick up any plain txs
+ }
// Retrieve the next transaction and abort if all done.
- ltx, tip := txs.Peek()
+
+ var (
+ ltx *txpool.LazyTransaction
+ txs *transactionsByPriceAndNonce
+ )
+ pltx, ptip := plainTxs.Peek()
+ bltx, btip := blobTxs.Peek()
+
+ switch {
+ case pltx == nil:
+ txs, ltx = blobTxs, bltx
+ case bltx == nil:
+ txs, ltx = plainTxs, pltx
+ default:
+ if ptip.Lt(btip) {
+ txs, ltx = blobTxs, bltx
+ } else {
+ txs, ltx = plainTxs, pltx
+ }
+ }
if ltx == nil {
break
}
+ lastTxHash = ltx.Hash
// If we don't have enough space for the next transaction, skip the account.
if env.gasPool.Gas() < ltx.Gas {
log.Trace("Not enough gas left for transaction", "hash", ltx.Hash, "left", env.gasPool.Gas(), "needed", ltx.Gas)
@@ -1002,8 +1027,8 @@ mainloop:
continue
}
// If we don't receive enough tip for the next transaction, skip the account
- if tip.Cmp(minTip) < 0 {
- log.Trace("Not enough tip for transaction", "hash", ltx.Hash, "tip", tip, "needed", minTip)
+ if ptip.Cmp(minTip) < 0 {
+ log.Trace("Not enough tip for transaction", "hash", ltx.Hash, "tip", ptip, "needed", minTip)
break // If the next-best is too low, surely no better will be available
}
// Transaction seems to fit, pull it up from the pool
@@ -1014,20 +1039,20 @@ mainloop:
continue
}
// Error may be ignored here. The error has already been checked
- // during transaction acceptance is the transaction pool.
+ // during transaction acceptance in the transaction pool.
from, _ := types.Sender(env.signer, tx)
// not prioritising conditional transaction, yet.
//nolint:nestif
if options := tx.GetOptions(); options != nil {
- if err := env.header.ValidateBlockNumberOptions4337(options.BlockNumberMin, options.BlockNumberMax); err != nil {
+ if err := env.header.ValidateBlockNumberOptionsPIP15(options.BlockNumberMin, options.BlockNumberMax); err != nil {
log.Trace("Dropping conditional transaction", "from", from, "hash", tx.Hash(), "reason", err)
txs.Pop()
continue
}
- if err := env.header.ValidateTimestampOptions4337(options.TimestampMin, options.TimestampMax); err != nil {
+ if err := env.header.ValidateTimestampOptionsPIP15(options.TimestampMin, options.TimestampMax); err != nil {
log.Trace("Dropping conditional transaction", "from", from, "hash", tx.Hash(), "reason", err)
txs.Pop()
@@ -1343,20 +1368,33 @@ func startProfiler(profile string, filepath string, number uint64) (func() error
// fillTransactions retrieves the pending transactions from the txpool and fills them
// into the given sealing block. The transaction selection and ordering strategy can
// be customized with the plugin in the future.
+
//
//nolint:gocognit
func (w *worker) fillTransactions(ctx context.Context, interrupt *atomic.Int32, env *environment, interruptCtx context.Context) error {
ctx, span := tracing.StartSpan(ctx, "fillTransactions")
defer tracing.EndSpan(span)
- // Split the pending transactions into locals and remotes
- // Fill the block with all available pending transactions.
- pending := w.eth.TxPool().Pending(true)
- localTxs, remoteTxs := make(map[common.Address][]*txpool.LazyTransaction), pending
+ w.mu.RLock()
+ tip := w.tip
+ w.mu.RUnlock()
+
+ // Retrieve the pending transactions pre-filtered by the 1559/4844 dynamic fees
+ filter := txpool.PendingFilter{
+ MinTip: uint256.MustFromBig(tip.ToBig()),
+ }
+
+ if env.header.BaseFee != nil {
+ filter.BaseFee = uint256.MustFromBig(env.header.BaseFee)
+ }
+
+ if env.header.ExcessBlobGas != nil {
+ filter.BlobFee = uint256.MustFromBig(eip4844.CalcBlobFee(*env.header.ExcessBlobGas))
+ }
var (
- localTxsCount int
- remoteTxsCount int
+ localPlainTxsCount int
+ remotePlainTxsCount int
)
// TODO: move to config or RPC
@@ -1420,19 +1458,33 @@ func (w *worker) fillTransactions(ctx context.Context, interrupt *atomic.Int32,
}(env.header.Number.Uint64())
}
+ var (
+ localPlainTxs, remotePlainTxs, localBlobTxs, remoteBlobTxs map[common.Address][]*txpool.LazyTransaction
+ )
+
tracing.Exec(ctx, "", "worker.SplittingTransactions", func(ctx context.Context, span trace.Span) {
prePendingTime := time.Now()
- pending := w.eth.TxPool().Pending(true)
- remoteTxs = pending
+ filter.OnlyPlainTxs, filter.OnlyBlobTxs = true, false
+ pendingPlainTxs := w.eth.TxPool().Pending(filter)
+
+ filter.OnlyPlainTxs, filter.OnlyBlobTxs = false, true
+ pendingBlobTxs := w.eth.TxPool().Pending(filter)
+
+ // Split the pending transactions into locals and remotes.
+ localPlainTxs, remotePlainTxs = make(map[common.Address][]*txpool.LazyTransaction), pendingPlainTxs
+ localBlobTxs, remoteBlobTxs = make(map[common.Address][]*txpool.LazyTransaction), pendingBlobTxs
postPendingTime := time.Now()
for _, account := range w.eth.TxPool().Locals() {
- if txs := remoteTxs[account]; len(txs) > 0 {
- delete(remoteTxs, account)
-
- localTxs[account] = txs
+ if txs := remotePlainTxs[account]; len(txs) > 0 {
+ delete(remotePlainTxs, account)
+ localPlainTxs[account] = txs
+ }
+ if txs := remoteBlobTxs[account]; len(txs) > 0 {
+ delete(remoteBlobTxs, account)
+ localBlobTxs[account] = txs
}
}
@@ -1440,8 +1492,8 @@ func (w *worker) fillTransactions(ctx context.Context, interrupt *atomic.Int32,
tracing.SetAttributes(
span,
- attribute.Int("len of local txs", localTxsCount),
- attribute.Int("len of remote txs", remoteTxsCount),
+ attribute.Int("len of local txs", localPlainTxsCount),
+ attribute.Int("len of remote txs", remotePlainTxsCount),
attribute.String("time taken by Pending()", fmt.Sprintf("%v", postPendingTime.Sub(prePendingTime))),
attribute.String("time taken by Locals()", fmt.Sprintf("%v", postLocalsTime.Sub(postPendingTime))),
)
@@ -1453,29 +1505,22 @@ func (w *worker) fillTransactions(ctx context.Context, interrupt *atomic.Int32,
err error
)
- w.mu.RLock()
- tip := w.tip
- w.mu.RUnlock()
-
- if len(localTxs) > 0 {
- var txs *transactionsByPriceAndNonce
+ // Fill the block with all available pending transactions.
+ if len(localPlainTxs) > 0 || len(localBlobTxs) > 0 {
+ var plainTxs, blobTxs *transactionsByPriceAndNonce
tracing.Exec(ctx, "", "worker.LocalTransactionsByPriceAndNonce", func(ctx context.Context, span trace.Span) {
- var baseFee *uint256.Int
- if env.header.BaseFee != nil {
- baseFee = cmath.FromBig(env.header.BaseFee)
- }
-
- txs = newTransactionsByPriceAndNonce(env.signer, localTxs, baseFee.ToBig())
+ plainTxs = newTransactionsByPriceAndNonce(env.signer, localPlainTxs, env.header.BaseFee)
+ blobTxs = newTransactionsByPriceAndNonce(env.signer, localBlobTxs, env.header.BaseFee)
tracing.SetAttributes(
span,
- attribute.Int("len of tx local Heads", txs.GetTxs()),
+ attribute.Int("len of tx local Heads", plainTxs.GetTxs()),
)
})
tracing.Exec(ctx, "", "worker.LocalCommitTransactions", func(ctx context.Context, span trace.Span) {
- err = w.commitTransactions(env, txs, interrupt, new(big.Int), interruptCtx)
+ err = w.commitTransactions(env, plainTxs, blobTxs, interrupt, new(uint256.Int), interruptCtx)
})
if err != nil {
@@ -1485,25 +1530,21 @@ func (w *worker) fillTransactions(ctx context.Context, interrupt *atomic.Int32,
localEnvTCount = env.tcount
}
- if len(remoteTxs) > 0 {
- var txs *transactionsByPriceAndNonce
+ if len(remotePlainTxs) > 0 || len(remoteBlobTxs) > 0 {
+ var plainTxs, blobTxs *transactionsByPriceAndNonce
tracing.Exec(ctx, "", "worker.RemoteTransactionsByPriceAndNonce", func(ctx context.Context, span trace.Span) {
- var baseFee *uint256.Int
- if env.header.BaseFee != nil {
- baseFee = cmath.FromBig(env.header.BaseFee)
- }
-
- txs = newTransactionsByPriceAndNonce(env.signer, remoteTxs, baseFee.ToBig())
+ plainTxs = newTransactionsByPriceAndNonce(env.signer, remotePlainTxs, env.header.BaseFee)
+ blobTxs = newTransactionsByPriceAndNonce(env.signer, remoteBlobTxs, env.header.BaseFee)
tracing.SetAttributes(
span,
- attribute.Int("len of tx remote Heads", txs.GetTxs()),
+ attribute.Int("len of tx remote Heads", plainTxs.GetTxs()),
)
})
tracing.Exec(ctx, "", "worker.RemoteCommitTransactions", func(ctx context.Context, span trace.Span) {
- err = w.commitTransactions(env, txs, interrupt, tip, interruptCtx)
+ err = w.commitTransactions(env, plainTxs, blobTxs, interrupt, new(uint256.Int), interruptCtx)
})
if err != nil {
@@ -1546,7 +1587,12 @@ func (w *worker) generateWork(ctx context.Context, params *generateParams) *newP
log.Warn("Block building is interrupted", "allowance", common.PrettyDuration(w.newpayloadTimeout))
}
}
- block, err := w.engine.FinalizeAndAssemble(ctx, w.chain, work.header, work.state, work.txs, nil, work.receipts, params.withdrawals)
+ block, err := w.engine.FinalizeAndAssemble(w.chain, work.header, work.state, &types.Body{
+ Transactions: work.txs,
+ Uncles: nil,
+ Withdrawals: params.withdrawals,
+ }, work.receipts)
+
if err != nil {
return &newPayloadResult{err: err}
}
@@ -1700,7 +1746,9 @@ func (w *worker) commit(ctx context.Context, env *environment, interval func(),
// https://github.com/ethereum/go-ethereum/issues/24299
env := env.copy()
// Withdrawals are set to nil here, because this is only called in PoW.
- block, err := w.engine.FinalizeAndAssemble(ctx, w.chain, env.header, env.state, env.txs, nil, env.receipts, nil)
+ block, err := w.engine.FinalizeAndAssemble(w.chain, env.header, env.state, &types.Body{
+ Transactions: env.txs,
+ }, env.receipts)
tracing.SetAttributes(
span,
attribute.Int("number", int(env.header.Number.Uint64())),
@@ -1714,19 +1762,16 @@ func (w *worker) commit(ctx context.Context, env *environment, interval func(),
return err
}
- // If we're post merge, just ignore
- if !w.isTTDReached(block.Header()) {
- select {
- case w.taskCh <- &task{ctx: ctx, receipts: env.receipts, state: env.state, block: block, createdAt: time.Now()}:
- fees := totalFees(block, env.receipts)
- feesInEther := new(big.Float).Quo(new(big.Float).SetInt(fees), big.NewFloat(params.Ether))
- log.Info("Commit new sealing work", "number", block.Number(), "sealhash", w.engine.SealHash(block.Header()),
- "txs", env.tcount, "gas", block.GasUsed(), "fees", feesInEther,
- "elapsed", common.PrettyDuration(time.Since(start)))
-
- case <-w.exitCh:
- log.Info("Worker has exited")
- }
+ select {
+ case w.taskCh <- &task{ctx: ctx, receipts: env.receipts, state: env.state, block: block, createdAt: time.Now()}:
+ fees := totalFees(block, env.receipts)
+ feesInEther := new(big.Float).Quo(new(big.Float).SetInt(fees), big.NewFloat(params.Ether))
+ log.Info("Commit new sealing work", "number", block.Number(), "sealhash", w.engine.SealHash(block.Header()),
+ "txs", env.tcount, "gas", block.GasUsed(), "fees", feesInEther,
+ "elapsed", common.PrettyDuration(time.Since(start)))
+
+ case <-w.exitCh:
+ log.Info("Worker has exited")
}
}
@@ -1756,13 +1801,6 @@ func (w *worker) getSealingBlock(params *generateParams) *newPayloadResult {
}
}
-// isTTDReached returns the indicator if the given block has reached the total
-// terminal difficulty for The Merge transition.
-func (w *worker) isTTDReached(header *types.Header) bool {
- td, ttd := w.chain.GetTd(header.ParentHash, header.Number.Uint64()-1), w.chain.Config().TerminalTotalDifficulty
- return td != nil && ttd != nil && td.Cmp(ttd) >= 0
-}
-
// adjustResubmitInterval adjusts the resubmit interval.
func (w *worker) adjustResubmitInterval(message *intervalAdjust) {
select {
diff --git a/miner/worker_test.go b/miner/worker_test.go
index cac3e936df..1f90c79ec1 100644
--- a/miner/worker_test.go
+++ b/miner/worker_test.go
@@ -43,8 +43,9 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/tests/bor/mocks"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
"github.com/golang/mock/gomock"
+ "github.com/holiman/uint256"
"gotest.tools/assert"
)
@@ -226,7 +227,7 @@ type testWorkerBackend struct {
func newTestWorkerBackend(t TensingObject, chainConfig *params.ChainConfig, engine consensus.Engine, db ethdb.Database) *testWorkerBackend {
var gspec = &core.Genesis{
Config: chainConfig,
- Alloc: core.GenesisAlloc{testBankAddress: {Balance: testBankFunds}},
+ Alloc: types.GenesisAlloc{testBankAddress: {Balance: testBankFunds}},
}
switch e := engine.(type) {
case *bor.Bor:
@@ -251,7 +252,7 @@ func newTestWorkerBackend(t TensingObject, chainConfig *params.ChainConfig, engi
t.Fatalf("core.NewBlockChain failed: %v", err)
}
pool := legacypool.New(testTxPoolConfig, chain)
- txpool, _ := txpool.New(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), chain, []txpool.SubPool{pool})
+ txpool, _ := txpool.New(testTxPoolConfig.PriceLimit, chain, []txpool.SubPool{pool})
return &testWorkerBackend{
db: db,
@@ -269,7 +270,7 @@ func (b *testWorkerBackend) PeerCount() int {
func (b *testWorkerBackend) newRandomTx(creation bool) *types.Transaction {
var tx *types.Transaction
- gasPrice := big.NewInt(10 * params.InitialBaseFee)
+ gasPrice := big.NewInt(26 * params.InitialBaseFee)
if creation {
tx, _ = types.SignTx(types.NewContractCreation(b.txPool.Nonce(testBankAddress), big.NewInt(0), testGas, gasPrice, common.FromHex(testCode)), types.HomesteadSigner{}, testBankKey)
} else {
@@ -297,7 +298,7 @@ func (b *testWorkerBackend) newRandomTxWithNonce(creation bool, nonce uint64) *t
func (b *testWorkerBackend) newStorageCreateContractTx() (*types.Transaction, common.Address) {
var tx *types.Transaction
- gasPrice := big.NewInt(30 * params.InitialBaseFee)
+ gasPrice := big.NewInt(26 * params.InitialBaseFee)
tx, _ = types.SignTx(types.NewContractCreation(b.txPool.Nonce(TestBankAddress), big.NewInt(0), testGas, gasPrice, common.FromHex(storageContractByteCode)), types.HomesteadSigner{}, testBankKey)
contractAddr := crypto.CreateAddress(TestBankAddress, b.txPool.Nonce(TestBankAddress))
@@ -309,7 +310,7 @@ func (b *testWorkerBackend) newStorageCreateContractTx() (*types.Transaction, co
func (b *testWorkerBackend) newStorageContractCallTx(to common.Address, nonce uint64) *types.Transaction {
var tx *types.Transaction
- gasPrice := big.NewInt(10 * params.InitialBaseFee)
+ gasPrice := big.NewInt(26 * params.InitialBaseFee)
tx, _ = types.SignTx(types.NewTransaction(nonce, to, nil, storageCallTxGas, gasPrice, common.FromHex(storageContractTxCallData)), types.HomesteadSigner{}, testBankKey)
@@ -430,7 +431,7 @@ func testEmptyWork(t *testing.T, chainConfig *params.ChainConfig, engine consens
if len(task.receipts) != receiptLen {
t.Fatalf("receipt number mismatch: have %d, want %d", len(task.receipts), receiptLen)
}
- if task.state.GetBalance(testUserAddress).Cmp(balance) != 0 {
+ if task.state.GetBalance(testUserAddress).Cmp(uint256.NewInt(balance.Uint64())) != 0 {
t.Fatalf("account balance mismatch: have %d, want %d", task.state.GetBalance(testUserAddress), balance)
}
}
@@ -970,7 +971,7 @@ func BenchmarkBorMiningBlockSTMMetadata(b *testing.B) {
// This test chain imports the mined blocks.
db2 := rawdb.NewMemoryDatabase()
- back.genesis.MustCommit(db2, trie.NewDatabase(db2, trie.HashDefaults))
+ back.genesis.MustCommit(db2, triedb.NewDatabase(db2, triedb.HashDefaults))
chain, _ := core.NewParallelBlockChain(db2, nil, back.genesis, nil, engine, vm.Config{}, nil, nil, nil, 8)
defer chain.Stop()
diff --git a/node/api.go b/node/api.go
index c8817917a0..35396bc6c3 100644
--- a/node/api.go
+++ b/node/api.go
@@ -186,8 +186,6 @@ func (api *adminAPI) PeerEvents(ctx context.Context) (*rpc.Subscription, error)
return
case <-rpcSub.Err():
return
- case <-notifier.Closed():
- return
}
}
}()
diff --git a/node/defaults.go b/node/defaults.go
index d359522c30..b598372ffb 100644
--- a/node/defaults.go
+++ b/node/defaults.go
@@ -42,6 +42,7 @@ const (
// needs of all CLs.
engineAPIBatchItemLimit = 2000
engineAPIBatchResponseSizeLimit = 250 * 1000 * 1000
+ engineAPIBodyLimit = 128 * 1024 * 1024
)
var (
diff --git a/node/node.go b/node/node.go
index d63fe85d03..643f7615e9 100644
--- a/node/node.go
+++ b/node/node.go
@@ -26,6 +26,7 @@ import (
"os"
"path/filepath"
"reflect"
+ "slices"
"strings"
"sync"
@@ -36,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/ethdb/memorydb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p"
@@ -108,7 +110,7 @@ func New(conf *Config) (*Node, error) {
if strings.HasSuffix(conf.Name, ".ipc") {
return nil, errors.New(`Config.Name cannot end in ".ipc"`)
}
- server := rpc.NewServer("inproc", 0, 0)
+ server := rpc.NewServer("", 0, 0)
server.SetBatchLimits(conf.BatchRequestLimit, conf.BatchResponseMaxSize)
node := &Node{
config: conf,
@@ -300,17 +302,6 @@ func (n *Node) openEndpoints() error {
return err
}
-// containsLifecycle checks if 'lfs' contains 'l'.
-func containsLifecycle(lfs []Lifecycle, l Lifecycle) bool {
- for _, obj := range lfs {
- if obj == l {
- return true
- }
- }
-
- return false
-}
-
// stopServices terminates running services, RPC and p2p networking.
// It is the inverse of Start.
func (n *Node) stopServices(running []Lifecycle) error {
@@ -363,15 +354,9 @@ func (n *Node) closeDataDir() {
}
}
-// obtainJWTSecret loads the jwt-secret, either from the provided config,
-// or from the default location. If neither of those are present, it generates
-// a new secret and stores to the default location.
-func (n *Node) obtainJWTSecret(cliParam string) ([]byte, error) {
- fileName := cliParam
- if len(fileName) == 0 {
- // no path provided, use default
- fileName = n.ResolvePath(datadirJWTKey)
- }
+// ObtainJWTSecret loads the jwt-secret from the provided config. If the file is not
+// present, it generates a new secret and stores to the given location.
+func ObtainJWTSecret(fileName string) ([]byte, error) {
// try reading from file
if data, err := os.ReadFile(fileName); err == nil {
jwtSecret := common.FromHex(strings.TrimSpace(string(data)))
@@ -402,6 +387,18 @@ func (n *Node) obtainJWTSecret(cliParam string) ([]byte, error) {
return jwtSecret, nil
}
+// obtainJWTSecret loads the jwt-secret, either from the provided config,
+// or from the default location. If neither of those are present, it generates
+// a new secret and stores to the default location.
+func (n *Node) obtainJWTSecret(cliParam string) ([]byte, error) {
+ fileName := cliParam
+ if len(fileName) == 0 {
+ // no path provided, use default
+ fileName = n.ResolvePath(datadirJWTKey)
+ }
+ return ObtainJWTSecret(fileName)
+}
+
// startRPC is a helper method to configure all the various RPC endpoints during node
// startup. It's not meant to be called at any time afterwards as it makes certain
// assumptions about the state of the node.
@@ -469,12 +466,11 @@ func (n *Node) startRPC() error {
}
if err := server.enableWS(openAPIs, wsConfig{
- executionPoolSize: n.config.WSJsonRPCExecutionPoolSize,
- executionPoolRequestTimeout: n.config.WSJsonRPCExecutionPoolRequestTimeout,
- Modules: n.config.WSModules,
- Origins: n.config.WSOrigins,
- prefix: n.config.WSPathPrefix,
- rpcEndpointConfig: rpcConfig,
+ executionPoolSize: n.config.WSJsonRPCExecutionPoolSize,
+ Modules: n.config.WSModules,
+ Origins: n.config.WSOrigins,
+ prefix: n.config.WSPathPrefix,
+ rpcEndpointConfig: rpcConfig,
}); err != nil {
return err
}
@@ -494,14 +490,16 @@ func (n *Node) startRPC() error {
jwtSecret: secret,
batchItemLimit: engineAPIBatchItemLimit,
batchResponseSizeLimit: engineAPIBatchResponseSizeLimit,
+ httpBodyLimit: engineAPIBodyLimit,
}
- if err := server.enableRPC(allAPIs, httpConfig{
+ err := server.enableRPC(allAPIs, httpConfig{
CorsAllowedOrigins: DefaultAuthCors,
Vhosts: n.config.AuthVirtualHosts,
Modules: DefaultAuthModules,
prefix: DefaultAuthPrefix,
rpcEndpointConfig: sharedConfig,
- }); err != nil {
+ })
+ if err != nil {
return err
}
@@ -625,8 +623,7 @@ func (n *Node) RegisterLifecycle(lifecycle Lifecycle) {
if n.state != initializingState {
panic("can't register lifecycle on running/stopped node")
}
-
- if containsLifecycle(n.lifecycles, lifecycle) {
+ if slices.Contains(n.lifecycles, lifecycle) {
panic(fmt.Sprintf("attempt to register lifecycle %T more than once", lifecycle))
}
@@ -831,7 +828,7 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient,
var err error
if n.config.DataDir == "" {
- db = rawdb.NewMemoryDatabase()
+ db, err = rawdb.NewDatabaseWithFreezer(memorydb.New(), "", namespace, readonly, false, false)
} else {
db, err = rawdb.Open(rawdb.OpenOptions{
Type: n.config.DBEngine,
diff --git a/node/node_auth_test.go b/node/node_auth_test.go
index 597cd8531f..900f53440c 100644
--- a/node/node_auth_test.go
+++ b/node/node_auth_test.go
@@ -22,7 +22,7 @@ import (
"fmt"
"net/http"
"os"
- "path"
+ "path/filepath"
"testing"
"time"
@@ -98,7 +98,7 @@ func TestAuthEndpoints(t *testing.T) {
t.Fatalf("failed to create jwt secret: %v", err)
}
// Geth must read it from a file, and does not support in-memory JWT secrets, so we create a temporary file.
- jwtPath := path.Join(t.TempDir(), "jwt_secret")
+ jwtPath := filepath.Join(t.TempDir(), "jwt_secret")
if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(secret[:])), 0600); err != nil {
t.Fatalf("failed to prepare jwt secret file: %v", err)
}
diff --git a/node/node_test.go b/node/node_test.go
index dc291f5d91..a136a6393b 100644
--- a/node/node_test.go
+++ b/node/node_test.go
@@ -23,6 +23,7 @@ import (
"net"
"net/http"
"reflect"
+ "slices"
"strings"
"testing"
@@ -121,7 +122,7 @@ func TestLifecycleRegistry_Successful(t *testing.T) {
noop := NewNoop()
stack.RegisterLifecycle(noop)
- if !containsLifecycle(stack.lifecycles, noop) {
+ if !slices.Contains(stack.lifecycles, Lifecycle(noop)) {
t.Fatalf("lifecycle was not properly registered on the node, %v", err)
}
}
@@ -436,21 +437,6 @@ func TestRegisterHandler_Successful(t *testing.T) {
assert.Equal(t, "success", string(buf))
}
-// Tests that the given handler will not be successfully mounted since no HTTP server
-// is enabled for RPC
-func TestRegisterHandler_Unsuccessful(t *testing.T) {
- node, err := New(&DefaultConfig)
- if err != nil {
- t.Fatalf("could not create new node: %v", err)
- }
-
- // create and mount handler
- handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Write([]byte("success"))
- })
- node.RegisterHandler("test", "/test", handler)
-}
-
// Tests whether websocket requests can be handled on the same port as a regular http server.
func TestWebsocketHTTPOnSamePort_WebsocketRequest(t *testing.T) {
node := startHTTP(t, 0, 0)
diff --git a/node/rpcstack.go b/node/rpcstack.go
index b8e6df4774..7b4d723eeb 100644
--- a/node/rpcstack.go
+++ b/node/rpcstack.go
@@ -19,6 +19,7 @@ package node
import (
"compress/gzip"
"context"
+ "errors"
"fmt"
"io"
"net"
@@ -44,19 +45,17 @@ type httpConfig struct {
prefix string // path prefix on which to mount http handler
// Execution pool config
- executionPoolSize uint64
- executionPoolRequestTimeout time.Duration
+ executionPoolSize uint64
rpcEndpointConfig
}
// wsConfig is the JSON-RPC/Websocket configuration
type wsConfig struct {
// Execution pool config
- executionPoolSize uint64
- executionPoolRequestTimeout time.Duration
- Origins []string
- Modules []string
- prefix string // path prefix on which to mount ws handler
+ executionPoolSize uint64
+ Origins []string
+ Modules []string
+ prefix string // path prefix on which to mount ws handler
rpcEndpointConfig
}
@@ -64,6 +63,7 @@ type rpcEndpointConfig struct {
jwtSecret []byte // optional JWT secret
batchItemLimit int
batchResponseSizeLimit int
+ httpBodyLimit int
}
type rpcHandler struct {
@@ -325,14 +325,17 @@ func (h *httpServer) enableRPC(apis []rpc.API, config httpConfig) error {
defer h.mu.Unlock()
if h.rpcAllowed() {
- return fmt.Errorf("JSON-RPC over HTTP is already enabled")
+ return errors.New("JSON-RPC over HTTP is already enabled")
}
// Create RPC server and handler.
- srv := rpc.NewServer("http", config.executionPoolSize, config.executionPoolRequestTimeout)
+ srv := rpc.NewServer("", 0, 0)
srv.SetRPCBatchLimit(h.RPCBatchLimit)
srv.SetBatchLimits(config.batchItemLimit, config.batchResponseSizeLimit)
+ if config.httpBodyLimit > 0 {
+ srv.SetHTTPBodyLimit(config.httpBodyLimit)
+ }
if err := RegisterApis(apis, config.Modules, srv); err != nil {
return err
}
@@ -363,13 +366,16 @@ func (h *httpServer) enableWS(apis []rpc.API, config wsConfig) error {
defer h.mu.Unlock()
if h.wsAllowed() {
- return fmt.Errorf("JSON-RPC over WebSocket is already enabled")
+ return errors.New("JSON-RPC over WebSocket is already enabled")
}
// Create RPC server and handler.
- srv := rpc.NewServer("ws", config.executionPoolSize, config.executionPoolRequestTimeout)
+ srv := rpc.NewServer("", 0, 0)
srv.SetRPCBatchLimit(h.RPCBatchLimit)
srv.SetBatchLimits(config.batchItemLimit, config.batchResponseSizeLimit)
+ if config.httpBodyLimit > 0 {
+ srv.SetHTTPBodyLimit(config.httpBodyLimit)
+ }
if err := RegisterApis(apis, config.Modules, srv); err != nil {
return err
}
@@ -642,7 +648,7 @@ func newIPCServer(log log.Logger, endpoint string) *ipcServer {
return &ipcServer{log: log, endpoint: endpoint}
}
-// Start starts the httpServer's http.Server
+// start starts the httpServer's http.Server
func (is *ipcServer) start(apis []rpc.API) error {
is.mu.Lock()
defer is.mu.Unlock()
diff --git a/oss-fuzz.sh b/oss-fuzz.sh
index 8978de70dd..7993dc9c64 100644
--- a/oss-fuzz.sh
+++ b/oss-fuzz.sh
@@ -208,6 +208,14 @@ compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \
FuzzCrossPairing fuzz_cross_pairing\
$repo/tests/fuzzers/bls12381/bls12381_test.go
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \
+ FuzzG1SubgroupChecks fuzz_g1_subgroup_checks\
+ $repo/tests/fuzzers/bls12381/bls12381_test.go
+
+compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/bls12381 \
+ FuzzG2SubgroupChecks fuzz_g2_subgroup_checks\
+ $repo/tests/fuzzers/bls12381/bls12381_test.go
+
compile_fuzzer github.com/ethereum/go-ethereum/tests/fuzzers/secp256k1 \
Fuzz fuzzSecp256k1\
$repo/tests/fuzzers/secp256k1/secp_test.go
diff --git a/p2p/dial.go b/p2p/dial.go
index 59cc77c3c0..a8aee18073 100644
--- a/p2p/dial.go
+++ b/p2p/dial.go
@@ -65,11 +65,8 @@ type tcpDialer struct {
}
func (t tcpDialer) Dial(ctx context.Context, dest *enode.Node) (net.Conn, error) {
- return t.d.DialContext(ctx, "tcp", nodeAddr(dest).String())
-}
-
-func nodeAddr(n *enode.Node) net.Addr {
- return &net.TCPAddr{IP: n.IP(), Port: n.TCP()}
+ addr, _ := dest.TCPEndpoint()
+ return t.d.DialContext(ctx, "tcp", addr.String())
}
// checkDial errors:
@@ -249,7 +246,7 @@ loop:
select {
case node := <-nodesCh:
if err := d.checkDial(node); err != nil {
- d.log.Trace("Discarding dial candidate", "id", node.ID(), "ip", node.IP(), "reason", err)
+ d.log.Trace("Discarding dial candidate", "id", node.ID(), "ip", node.IPAddr(), "reason", err)
} else {
d.startDial(newDialTask(node, dynDialedConn))
}
@@ -283,7 +280,7 @@ loop:
case node := <-d.addStaticCh:
id := node.ID()
_, exists := d.static[id]
- d.log.Trace("Adding static node", "id", id, "ip", node.IP(), "added", !exists)
+ d.log.Trace("Adding static node", "id", id, "ip", node.IPAddr(), "added", !exists)
if exists {
continue loop
}
@@ -390,8 +387,7 @@ func (d *dialScheduler) checkDial(n *enode.Node) error {
if n.ID() == d.self {
return errSelf
}
-
- if n.IP() != nil && n.TCP() == 0 {
+ if n.IPAddr().IsValid() && n.TCP() == 0 {
// This check can trigger if a non-TCP node is found
// by discovery. If there is no IP, the node is a static
// node and the actual endpoint will be resolved later in dialTask.
@@ -405,8 +401,7 @@ func (d *dialScheduler) checkDial(n *enode.Node) error {
if _, ok := d.peers[n.ID()]; ok {
return errAlreadyConnected
}
-
- if d.netRestrict != nil && !d.netRestrict.Contains(n.IP()) {
+ if d.netRestrict != nil && !d.netRestrict.ContainsAddr(n.IPAddr()) {
return errNetRestrict
}
@@ -461,7 +456,7 @@ func (d *dialScheduler) removeFromStaticPool(idx int) {
// startDial runs the given dial task in a separate goroutine.
func (d *dialScheduler) startDial(task *dialTask) {
node := task.dest()
- d.log.Trace("Starting p2p dial", "id", node.ID(), "ip", node.IP(), "flag", task.flags)
+ d.log.Trace("Starting p2p dial", "id", node.ID(), "ip", node.IPAddr(), "flag", task.flags)
hkey := string(node.ID().Bytes())
d.history.add(hkey, d.clock.Now().Add(dialHistoryExpiration))
d.dialing[node.ID()] = task
@@ -514,7 +509,7 @@ func (t *dialTask) run(d *dialScheduler) {
}
func (t *dialTask) needResolve() bool {
- return t.flags&staticDialedConn != 0 && t.dest().IP() == nil
+ return t.flags&staticDialedConn != 0 && !t.dest().IPAddr().IsValid()
}
// resolve attempts to find the current endpoint for the destination
@@ -551,7 +546,8 @@ func (t *dialTask) resolve(d *dialScheduler) bool {
// The node was found.
t.resolveDelay = initialResolveDelay
t.destPtr.Store(resolved)
- d.log.Debug("Resolved node", "id", resolved.ID(), "addr", &net.TCPAddr{IP: resolved.IP(), Port: resolved.TCP()})
+ resAddr, _ := resolved.TCPEndpoint()
+ d.log.Debug("Resolved node", "id", resolved.ID(), "addr", resAddr)
return true
}
@@ -560,7 +556,8 @@ func (t *dialTask) dial(d *dialScheduler, dest *enode.Node) error {
dialMeter.Mark(1)
fd, err := d.dialer.Dial(d.ctx, dest)
if err != nil {
- d.log.Trace("Dial error", "id", dest.ID(), "addr", nodeAddr(dest), "conn", t.flags, "err", cleanupDialErr(err))
+ addr, _ := dest.TCPEndpoint()
+ d.log.Trace("Dial error", "id", dest.ID(), "addr", addr, "conn", t.flags, "err", cleanupDialErr(err))
dialConnectionError.Mark(1)
return &dialError{err}
}
@@ -570,7 +567,7 @@ func (t *dialTask) dial(d *dialScheduler, dest *enode.Node) error {
func (t *dialTask) String() string {
node := t.dest()
id := node.ID()
- return fmt.Sprintf("%v %x %v:%d", t.flags, id[:8], node.IP(), node.TCP())
+ return fmt.Sprintf("%v %x %v:%d", t.flags, id[:8], node.IPAddr(), node.TCP())
}
func cleanupDialErr(err error) error {
diff --git a/p2p/discover/metrics.go b/p2p/discover/metrics.go
index 24d2bb1706..8deafbbce4 100644
--- a/p2p/discover/metrics.go
+++ b/p2p/discover/metrics.go
@@ -44,7 +44,7 @@ func init() {
}
}
-// meteredConn is a wrapper around a net.UDPConn that meters both the
+// meteredUdpConn is a wrapper around a net.UDPConn that meters both the
// inbound and outbound network traffic.
type meteredUdpConn struct {
UDPConn
diff --git a/p2p/discover/ntp.go b/p2p/discover/ntp.go
index e687259341..2e82b99c7c 100644
--- a/p2p/discover/ntp.go
+++ b/p2p/discover/ntp.go
@@ -22,10 +22,10 @@ package discover
import (
"fmt"
"net"
+ "slices"
"time"
"github.com/ethereum/go-ethereum/log"
- "golang.org/x/exp/slices"
)
const (
diff --git a/p2p/discover/table.go b/p2p/discover/table.go
index 6a64935cce..6d9bbc2415 100644
--- a/p2p/discover/table.go
+++ b/p2p/discover/table.go
@@ -25,7 +25,7 @@ package discover
import (
"context"
"fmt"
- "net"
+ "net/netip"
"slices"
"sync"
"time"
@@ -209,8 +209,8 @@ func (tab *Table) setFallbackNodes(nodes []*enode.Node) error {
if err := n.ValidateComplete(); err != nil {
return fmt.Errorf("bad bootstrap node %q: %v", n, err)
}
- if tab.cfg.NetRestrict != nil && !tab.cfg.NetRestrict.Contains(n.IP()) {
- tab.log.Error("Bootstrap node filtered by netrestrict", "id", n.ID(), "ip", n.IP())
+ if tab.cfg.NetRestrict != nil && !tab.cfg.NetRestrict.ContainsAddr(n.IPAddr()) {
+ tab.log.Error("Bootstrap node filtered by netrestrict", "id", n.ID(), "ip", n.IPAddr())
continue
}
nursery = append(nursery, n)
@@ -454,11 +454,13 @@ func (tab *Table) loadSeedNodes() {
for i := range seeds {
seed := seeds[i]
if tab.log.Enabled(context.Background(), log.LevelTrace) {
- age := time.Since(tab.db.LastPongReceived(seed.ID(), seed.IP()))
+ age := time.Since(tab.db.LastPongReceived(seed.ID(), seed.IPAddr()))
addr, _ := seed.UDPEndpoint()
tab.log.Trace("Found seed node in database", "id", seed.ID(), "addr", addr, "age", age)
}
+ tab.mutex.Lock()
tab.handleAddNode(addNodeOp{node: seed, isInbound: false})
+ tab.mutex.Unlock()
}
}
@@ -481,37 +483,32 @@ func (tab *Table) bucketAtDistance(d int) *bucket {
return tab.buckets[d-bucketMinDistance-1]
}
-func (tab *Table) addIP(b *bucket, ip net.IP) bool {
- if len(ip) == 0 {
+func (tab *Table) addIP(b *bucket, ip netip.Addr) bool {
+ if !ip.IsValid() || ip.IsUnspecified() {
return false // Nodes without IP cannot be added.
}
-
- if netutil.IsLAN(ip) {
+ if netutil.AddrIsLAN(ip) {
return true
}
-
- if !tab.ips.Add(ip) {
+ if !tab.ips.AddAddr(ip) {
tab.log.Debug("IP exceeds table limit", "ip", ip)
return false
}
-
- if !b.ips.Add(ip) {
+ if !b.ips.AddAddr(ip) {
tab.log.Debug("IP exceeds bucket limit", "ip", ip)
- tab.ips.Remove(ip)
-
+ tab.ips.RemoveAddr(ip)
return false
}
return true
}
-func (tab *Table) removeIP(b *bucket, ip net.IP) {
- if netutil.IsLAN(ip) {
+func (tab *Table) removeIP(b *bucket, ip netip.Addr) {
+ if netutil.AddrIsLAN(ip) {
return
}
-
- tab.ips.Remove(ip)
- b.ips.Remove(ip)
+ tab.ips.RemoveAddr(ip)
+ b.ips.RemoveAddr(ip)
}
// handleAddNode adds the node in the request to the table, if there is space.
@@ -537,7 +534,7 @@ func (tab *Table) handleAddNode(req addNodeOp) bool {
tab.addReplacement(b, req.node)
return false
}
- if !tab.addIP(b, req.node.IP()) {
+ if !tab.addIP(b, req.node.IPAddr()) {
// Can't add: IP limit reached.
return false
}
@@ -560,8 +557,7 @@ func (tab *Table) addReplacement(b *bucket, n *enode.Node) {
// TODO: update ENR
return
}
-
- if !tab.addIP(b, n.IP()) {
+ if !tab.addIP(b, n.IPAddr()) {
return
}
@@ -569,7 +565,7 @@ func (tab *Table) addReplacement(b *bucket, n *enode.Node) {
var removed *tableNode
b.replacements, removed = pushNode(b.replacements, wn, maxReplacements)
if removed != nil {
- tab.removeIP(b, removed.IP())
+ tab.removeIP(b, removed.IPAddr())
}
}
@@ -609,12 +605,12 @@ func (tab *Table) deleteInBucket(b *bucket, id enode.ID) *tableNode {
// Remove the node.
n := b.entries[index]
b.entries = slices.Delete(b.entries, index, index+1)
- tab.removeIP(b, n.IP())
+ tab.removeIP(b, n.IPAddr())
tab.nodeRemoved(b, n)
// Add replacement.
if len(b.replacements) == 0 {
- tab.log.Debug("Removed dead node", "b", b.index, "id", n.ID(), "ip", n.IP())
+ tab.log.Debug("Removed dead node", "b", b.index, "id", n.ID(), "ip", n.IPAddr())
return nil
}
rindex := tab.rand.Intn(len(b.replacements))
@@ -622,7 +618,7 @@ func (tab *Table) deleteInBucket(b *bucket, id enode.ID) *tableNode {
b.replacements = slices.Delete(b.replacements, rindex, rindex+1)
b.entries = append(b.entries, rep)
tab.nodeAdded(b, rep)
- tab.log.Debug("Replaced dead node", "b", b.index, "id", n.ID(), "ip", n.IP(), "r", rep.ID(), "rip", rep.IP())
+ tab.log.Debug("Replaced dead node", "b", b.index, "id", n.ID(), "ip", n.IPAddr(), "r", rep.ID(), "rip", rep.IPAddr())
return rep
}
@@ -649,10 +645,10 @@ func (tab *Table) bumpInBucket(b *bucket, newRecord *enode.Node, isInbound bool)
ipchanged := newRecord.IPAddr() != n.IPAddr()
portchanged := newRecord.UDP() != n.UDP()
if ipchanged {
- tab.removeIP(b, n.IP())
- if !tab.addIP(b, newRecord.IP()) {
+ tab.removeIP(b, n.IPAddr())
+ if !tab.addIP(b, newRecord.IPAddr()) {
// It doesn't fit with the limit, put the previous record back.
- tab.addIP(b, n.IP())
+ tab.addIP(b, n.IPAddr())
return n, false
}
}
@@ -671,11 +667,11 @@ func (tab *Table) handleTrackRequest(op trackRequestOp) {
var fails int
if op.success {
// Reset failure counter because it counts _consecutive_ failures.
- tab.db.UpdateFindFails(op.node.ID(), op.node.IP(), 0)
+ tab.db.UpdateFindFails(op.node.ID(), op.node.IPAddr(), 0)
} else {
- fails = tab.db.FindFails(op.node.ID(), op.node.IP())
+ fails = tab.db.FindFails(op.node.ID(), op.node.IPAddr())
fails++
- tab.db.UpdateFindFails(op.node.ID(), op.node.IP(), fails)
+ tab.db.UpdateFindFails(op.node.ID(), op.node.IPAddr(), fails)
}
tab.mutex.Lock()
diff --git a/p2p/discover/table_test.go b/p2p/discover/table_test.go
index 013af5034d..fc9ecd83b1 100644
--- a/p2p/discover/table_test.go
+++ b/p2p/discover/table_test.go
@@ -137,7 +137,7 @@ func waitForRevalidationPing(t *testing.T, transport *pingRecorder, tab *Table,
simclock.Run(tab.cfg.PingInterval * slowRevalidationFactor)
p := transport.waitPing(2 * time.Second)
if p == nil {
- t.Fatal("Table did not send revalidation ping")
+ continue
}
if id == (enode.ID{}) || p.ID() == id {
return p
@@ -195,7 +195,7 @@ func checkIPLimitInvariant(t *testing.T, tab *Table) {
for _, b := range tab.buckets {
for _, n := range b.entries {
- tabset.Add(n.IP())
+ tabset.AddAddr(n.IPAddr())
}
}
@@ -282,7 +282,7 @@ func (*closeTest) Generate(rand *rand.Rand, size int) reflect.Value {
for _, id := range gen([]enode.ID{}, rand).([]enode.ID) {
r := new(enr.Record)
- r.Set(enr.IP(genIP(rand)))
+ r.Set(enr.IPv4Addr(netutil.RandomAddr(rand, true)))
n := enode.SignNull(r, id)
t.All = append(t.All, n)
}
@@ -402,11 +402,11 @@ func checkBucketContent(t *testing.T, tab *Table, nodes []*enode.Node) {
}
t.Log("wrong bucket content. have nodes:")
for _, n := range b.entries {
- t.Logf(" %v (seq=%v, ip=%v)", n.ID(), n.Seq(), n.IP())
+ t.Logf(" %v (seq=%v, ip=%v)", n.ID(), n.Seq(), n.IPAddr())
}
t.Log("want nodes:")
for _, n := range nodes {
- t.Logf(" %v (seq=%v, ip=%v)", n.ID(), n.Seq(), n.IP())
+ t.Logf(" %v (seq=%v, ip=%v)", n.ID(), n.Seq(), n.IPAddr())
}
t.FailNow()
@@ -442,7 +442,7 @@ func TestTable_revalidateSyncRecord(t *testing.T) {
transport.updateRecord(n2)
// Wait for revalidation. We wait for the node to be revalidated two times
- // in order to synchronize with the update in the able.
+ // in order to synchronize with the update in the table.
waitForRevalidationPing(t, transport, tab, n2.ID())
waitForRevalidationPing(t, transport, tab, n2.ID())
@@ -506,13 +506,6 @@ func gen(typ interface{}, rand *rand.Rand) interface{} {
return v.Interface()
}
-func genIP(rand *rand.Rand) net.IP {
- ip := make(net.IP, 4)
- rand.Read(ip)
-
- return ip
-}
-
func quickcfg() *quick.Config {
return &quick.Config{
MaxCount: 5000,
diff --git a/p2p/discover/table_util_test.go b/p2p/discover/table_util_test.go
index 720164d6d0..b256dfca47 100644
--- a/p2p/discover/table_util_test.go
+++ b/p2p/discover/table_util_test.go
@@ -24,6 +24,7 @@ import (
"fmt"
"math/rand"
"net"
+ "slices"
"sync"
"sync/atomic"
"time"
@@ -31,7 +32,6 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/enr"
- "golang.org/x/exp/slices"
)
var nullNode *enode.Node
@@ -107,8 +107,9 @@ func idAtDistance(a enode.ID, n int) (b enode.ID) {
return b
}
+// intIP returns a LAN IP address based on i.
func intIP(i int) net.IP {
- return net.IP{byte(i), 0, 2, byte(i)}
+ return net.IP{10, 0, byte(i >> 8), byte(i & 0xFF)}
}
// fillBucket inserts nodes into the given bucket until it is full.
@@ -274,7 +275,7 @@ NotEqual:
}
func nodeEqual(n1 *enode.Node, n2 *enode.Node) bool {
- return n1.ID() == n2.ID() && n1.IP().Equal(n2.IP())
+ return n1.ID() == n2.ID() && n1.IPAddr() == n2.IPAddr()
}
func sortByID[N nodeType](nodes []N) {
diff --git a/p2p/discover/v4_lookup_test.go b/p2p/discover/v4_lookup_test.go
index 8997031d27..4956475ee3 100644
--- a/p2p/discover/v4_lookup_test.go
+++ b/p2p/discover/v4_lookup_test.go
@@ -308,8 +308,7 @@ func (tn *preminedTestnet) neighborsAtDistances(base *enode.Node, distances []ui
for i := range lookupTestnet.dists[d] {
n := lookupTestnet.node(d, i)
d := enode.LogDist(base.ID(), n.ID())
-
- if containsUint(uint(d), distances) {
+ if slices.Contains(distances, uint(d)) {
result = append(result, n)
if len(result) >= elems {
return result
diff --git a/p2p/discover/v4_udp.go b/p2p/discover/v4_udp.go
index 8ddc4b1c2a..4ca977e6c3 100644
--- a/p2p/discover/v4_udp.go
+++ b/p2p/discover/v4_udp.go
@@ -25,7 +25,6 @@ import (
"errors"
"fmt"
"io"
- "net"
"net/netip"
"sync"
"time"
@@ -259,8 +258,7 @@ func (t *UDPv4) sendPing(toid enode.ID, toaddr netip.AddrPort, callback func())
return matched, matched
})
// Send the packet.
- toUDPAddr := &net.UDPAddr{IP: toaddr.Addr().AsSlice()}
- t.localNode.UDPContact(toUDPAddr)
+ t.localNode.UDPContact(toaddr)
t.write(toaddr, toid, req.Name(), packet)
return rm
@@ -398,13 +396,13 @@ func (t *UDPv4) RequestENR(n *enode.Node) (*enode.Node, error) {
}
if respN.ID() != n.ID() {
- return nil, fmt.Errorf("invalid ID in response record")
+ return nil, errors.New("invalid ID in response record")
}
if respN.Seq() < n.Seq() {
return n, nil // response record is older
}
- if err := netutil.CheckRelayIP(addr.Addr().AsSlice(), respN.IP()); err != nil {
+ if err := netutil.CheckRelayAddr(addr.Addr(), respN.IPAddr()); err != nil {
return nil, fmt.Errorf("invalid IP in response record: %v", err)
}
@@ -600,6 +598,11 @@ func (t *UDPv4) readLoop(unhandled chan<- ReadPacket) {
}
func (t *UDPv4) handlePacket(from netip.AddrPort, buf []byte) error {
+ // Unwrap IPv4-in-6 source address.
+ if from.Addr().Is4In6() {
+ from = netip.AddrPortFrom(netip.AddrFrom4(from.Addr().As4()), from.Port())
+ }
+
rawpacket, fromKey, hash, err := v4wire.Decode(buf)
if err != nil {
t.log.Debug("Bad discv4 packet", "addr", from, "err", err)
@@ -608,8 +611,7 @@ func (t *UDPv4) handlePacket(from netip.AddrPort, buf []byte) error {
packet := t.wrapPacket(rawpacket)
fromID := fromKey.ID()
-
- if err == nil && packet.preverify != nil {
+ if packet.preverify != nil {
err = packet.preverify(packet, from, fromID, fromKey)
}
@@ -624,15 +626,14 @@ func (t *UDPv4) handlePacket(from netip.AddrPort, buf []byte) error {
// checkBond checks if the given node has a recent enough endpoint proof.
func (t *UDPv4) checkBond(id enode.ID, ip netip.AddrPort) bool {
- return time.Since(t.db.LastPongReceived(id, ip.Addr().AsSlice())) < bondExpiration
+ return time.Since(t.db.LastPongReceived(id, ip.Addr())) < bondExpiration
}
// ensureBond solicits a ping from a node if we haven't seen a ping from it for a while.
// This ensures there is a valid endpoint proof on the remote end.
func (t *UDPv4) ensureBond(toid enode.ID, toaddr netip.AddrPort) {
- ip := toaddr.Addr().AsSlice()
- tooOld := time.Since(t.db.LastPingReceived(toid, ip)) > bondExpiration
- if tooOld || t.db.FindFails(toid, ip) > maxFindnodeFailures {
+ tooOld := time.Since(t.db.LastPingReceived(toid, toaddr.Addr())) > bondExpiration
+ if tooOld || t.db.FindFails(toid, toaddr.Addr()) > maxFindnodeFailures {
rm := t.sendPing(toid, toaddr, nil)
<-rm.errc
// Wait for them to ping back and process our pong.
@@ -741,7 +742,7 @@ func (t *UDPv4) handlePing(h *packetHandlerV4, from netip.AddrPort, fromID enode
// Ping back if our last pong on file is too far in the past.
fromIP := from.Addr().AsSlice()
n := enode.NewV4(h.senderKey, fromIP, int(req.From.TCP), int(from.Port()))
- if time.Since(t.db.LastPongReceived(n.ID(), fromIP)) > bondExpiration {
+ if time.Since(t.db.LastPongReceived(n.ID(), from.Addr())) > bondExpiration {
t.sendPing(fromID, from, func() {
t.tab.addInboundNode(n)
})
@@ -750,10 +751,9 @@ func (t *UDPv4) handlePing(h *packetHandlerV4, from netip.AddrPort, fromID enode
}
// Update node database and endpoint predictor.
- t.db.UpdateLastPingReceived(n.ID(), fromIP, time.Now())
- fromUDPAddr := &net.UDPAddr{IP: fromIP, Port: int(from.Port())}
- toUDPAddr := &net.UDPAddr{IP: req.To.IP, Port: int(req.To.UDP)}
- t.localNode.UDPEndpointStatement(fromUDPAddr, toUDPAddr)
+ t.db.UpdateLastPingReceived(n.ID(), from.Addr(), time.Now())
+ toaddr := netip.AddrPortFrom(netutil.IPToAddr(req.To.IP), req.To.UDP)
+ t.localNode.UDPEndpointStatement(from, toaddr)
}
// PONG/v4
@@ -767,11 +767,9 @@ func (t *UDPv4) verifyPong(h *packetHandlerV4, from netip.AddrPort, fromID enode
if !t.handleReply(fromID, from.Addr(), req) {
return errUnsolicitedReply
}
- fromIP := from.Addr().AsSlice()
- fromUDPAddr := &net.UDPAddr{IP: fromIP, Port: int(from.Port())}
- toUDPAddr := &net.UDPAddr{IP: req.To.IP, Port: int(req.To.UDP)}
- t.localNode.UDPEndpointStatement(fromUDPAddr, toUDPAddr)
- t.db.UpdateLastPongReceived(fromID, fromIP, time.Now())
+ toaddr := netip.AddrPortFrom(netutil.IPToAddr(req.To.IP), req.To.UDP)
+ t.localNode.UDPEndpointStatement(from, toaddr)
+ t.db.UpdateLastPongReceived(fromID, from.Addr(), time.Now())
return nil
}
@@ -810,8 +808,7 @@ func (t *UDPv4) handleFindnode(h *packetHandlerV4, from netip.AddrPort, fromID e
var sent bool
for _, n := range closest {
- fromIP := from.Addr().AsSlice()
- if netutil.CheckRelayIP(fromIP, n.IP()) == nil {
+ if netutil.CheckRelayAddr(from.Addr(), n.IPAddr()) == nil {
p.Nodes = append(p.Nodes, nodeToRPC(n))
}
diff --git a/p2p/discover/v4_udp_test.go b/p2p/discover/v4_udp_test.go
index b88b6a6002..76429b5ed3 100644
--- a/p2p/discover/v4_udp_test.go
+++ b/p2p/discover/v4_udp_test.go
@@ -296,7 +296,7 @@ func TestUDPv4_findnode(t *testing.T) {
// ensure there's a bond with the test node,
// findnode won't be accepted otherwise.
remoteID := v4wire.EncodePubkey(&test.remotekey.PublicKey).ID()
- test.table.db.UpdateLastPongReceived(remoteID, test.remoteaddr.Addr().AsSlice(), time.Now())
+ test.table.db.UpdateLastPongReceived(remoteID, test.remoteaddr.Addr(), time.Now())
// check that closest neighbors are returned.
expected := test.table.findnodeByID(testTarget.ID(), bucketSize, true)
@@ -304,13 +304,13 @@ func TestUDPv4_findnode(t *testing.T) {
waitNeighbors := func(want []*enode.Node) {
test.waitPacketOut(func(p *v4wire.Neighbors, to netip.AddrPort, hash []byte) {
if len(p.Nodes) != len(want) {
- t.Errorf("wrong number of results: got %d, want %d", len(p.Nodes), bucketSize)
+ t.Errorf("wrong number of results: got %d, want %d", len(p.Nodes), len(want))
return
}
for i, n := range p.Nodes {
if n.ID.ID() != want[i].ID() {
- t.Errorf("result mismatch at %d:\n got: %v\n want: %v", i, n, expected.entries[i])
+ t.Errorf("result mismatch at %d:\n got: %v\n want: %v", i, n, expected.entries[i])
}
if !live[n.ID.ID()] {
@@ -334,7 +334,7 @@ func TestUDPv4_findnodeMultiReply(t *testing.T) {
defer test.close()
rid := enode.PubkeyToIDV4(&test.remotekey.PublicKey)
- test.table.db.UpdateLastPingReceived(rid, test.remoteaddr.Addr().AsSlice(), time.Now())
+ test.table.db.UpdateLastPingReceived(rid, test.remoteaddr.Addr(), time.Now())
// queue a pending findnode request
resultc, errc := make(chan []*enode.Node, 1), make(chan error, 1)
@@ -466,8 +466,8 @@ func TestUDPv4_successfulPing(t *testing.T) {
if n.ID() != rid {
t.Errorf("node has wrong ID: got %v, want %v", n.ID(), rid)
}
- if !n.IP().Equal(test.remoteaddr.Addr().AsSlice()) {
- t.Errorf("node has wrong IP: got %v, want: %v", n.IP(), test.remoteaddr.Addr())
+ if n.IPAddr() != test.remoteaddr.Addr() {
+ t.Errorf("node has wrong IP: got %v, want: %v", n.IPAddr(), test.remoteaddr.Addr())
}
if n.UDP() != int(test.remoteaddr.Port()) {
t.Errorf("node has wrong UDP port: got %v, want: %v", n.UDP(), test.remoteaddr.Port())
diff --git a/p2p/discover/v5_udp.go b/p2p/discover/v5_udp.go
index 240647ed5e..acb4b554a5 100644
--- a/p2p/discover/v5_udp.go
+++ b/p2p/discover/v5_udp.go
@@ -725,6 +725,10 @@ func (t *UDPv5) readLoop() {
// dispatchReadPacket sends a packet into the dispatch loop.
func (t *UDPv5) dispatchReadPacket(from netip.AddrPort, content []byte) bool {
+ // Unwrap IPv4-in-6 source address.
+ if from.Addr().Is4In6() {
+ from = netip.AddrPortFrom(netip.AddrFrom4(from.Addr().As4()), from.Port())
+ }
select {
case t.packetInCh <- ReadPacket{content, from}:
return true
@@ -818,9 +822,8 @@ func (t *UDPv5) handle(p v5wire.Packet, fromID enode.ID, fromAddr netip.AddrPort
t.handlePing(p, fromID, fromAddr)
case *v5wire.Pong:
if t.handleCallResponse(fromID, fromAddr, p) {
- fromUDPAddr := &net.UDPAddr{IP: fromAddr.Addr().AsSlice(), Port: int(fromAddr.Port())}
- toUDPAddr := &net.UDPAddr{IP: p.ToIP, Port: int(p.ToPort)}
- t.localNode.UDPEndpointStatement(fromUDPAddr, toUDPAddr)
+ toAddr := netip.AddrPortFrom(netutil.IPToAddr(p.ToIP), p.ToPort)
+ t.localNode.UDPEndpointStatement(fromAddr, toAddr)
}
case *v5wire.Findnode:
t.handleFindnode(p, fromID, fromAddr)
diff --git a/p2p/discover/v5_udp_test.go b/p2p/discover/v5_udp_test.go
index 7a7e1892f7..58d066c58c 100644
--- a/p2p/discover/v5_udp_test.go
+++ b/p2p/discover/v5_udp_test.go
@@ -25,6 +25,7 @@ import (
"net"
"net/netip"
"reflect"
+ "slices"
"testing"
"time"
@@ -35,7 +36,6 @@ import (
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/ethereum/go-ethereum/rlp"
"github.com/stretchr/testify/require"
- "golang.org/x/exp/slices"
)
// Real sockets, real crypto: this test checks end-to-end connectivity for UDPv5.
diff --git a/p2p/discover/v5wire/crypto.go b/p2p/discover/v5wire/crypto.go
index f478becf34..ead29db1d2 100644
--- a/p2p/discover/v5wire/crypto.go
+++ b/p2p/discover/v5wire/crypto.go
@@ -137,11 +137,7 @@ func deriveKeys(hash hashFn, priv *ecdsa.PrivateKey, pub *ecdsa.PublicKey, n1, n
sec := session{writeKey: make([]byte, aesKeySize), readKey: make([]byte, aesKeySize)}
kdf.Read(sec.writeKey)
kdf.Read(sec.readKey)
-
- for i := range eph {
- eph[i] = 0
- }
-
+ clear(eph)
return &sec
}
diff --git a/p2p/discover/v5wire/encoding.go b/p2p/discover/v5wire/encoding.go
index 816ff44153..44e710a987 100644
--- a/p2p/discover/v5wire/encoding.go
+++ b/p2p/discover/v5wire/encoding.go
@@ -383,12 +383,12 @@ func (c *Codec) makeHandshakeAuth(toID enode.ID, addr string, challenge *Whoarey
// key is part of the ID nonce signature.
var remotePubkey = new(ecdsa.PublicKey)
if err := challenge.Node.Load((*enode.Secp256k1)(remotePubkey)); err != nil {
- return nil, nil, fmt.Errorf("can't find secp256k1 key for recipient")
+ return nil, nil, errors.New("can't find secp256k1 key for recipient")
}
ephkey, err := c.sc.ephemeralKeyGen()
if err != nil {
- return nil, nil, fmt.Errorf("can't generate ephemeral key")
+ return nil, nil, errors.New("can't generate ephemeral key")
}
ephpubkey := EncodePubkey(&ephkey.PublicKey)
@@ -415,7 +415,7 @@ func (c *Codec) makeHandshakeAuth(toID enode.ID, addr string, challenge *Whoarey
// Create session keys.
sec := deriveKeys(sha256.New, ephkey, remotePubkey, c.localnode.ID(), challenge.Node.ID(), cdata)
if sec == nil {
- return nil, nil, fmt.Errorf("key derivation failed")
+ return nil, nil, errors.New("key derivation failed")
}
return auth, sec, err
diff --git a/p2p/discover/v5wire/encoding_test.go b/p2p/discover/v5wire/encoding_test.go
index 40f707e7f2..e31c680b6c 100644
--- a/p2p/discover/v5wire/encoding_test.go
+++ b/p2p/discover/v5wire/encoding_test.go
@@ -30,6 +30,7 @@ import (
"testing"
"github.com/davecgh/go-spew/spew"
+
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/crypto"
@@ -296,9 +297,39 @@ func TestDecodeErrorsV5(t *testing.T) {
b = make([]byte, 63)
net.nodeA.expectDecodeErr(t, errInvalidHeader, b)
- // TODO some more tests would be nice :)
- // - check invalid authdata sizes
- // - check invalid handshake data sizes
+
+ t.Run("invalid-handshake-datasize", func(t *testing.T) {
+ requiredNumber := 108
+
+ testDataFile := filepath.Join("testdata", "v5.1-ping-handshake"+".txt")
+ enc := hexFile(testDataFile)
+ //delete some byte from handshake to make it invalid
+ enc = enc[:len(enc)-requiredNumber]
+ net.nodeB.expectDecodeErr(t, errMsgTooShort, enc)
+ })
+
+ t.Run("invalid-auth-datasize", func(t *testing.T) {
+ testPacket := []byte{}
+ testDataFiles := []string{"v5.1-whoareyou", "v5.1-ping-handshake"}
+ for counter, name := range testDataFiles {
+ file := filepath.Join("testdata", name+".txt")
+ enc := hexFile(file)
+ if counter == 0 {
+ //make whoareyou header
+ testPacket = enc[:sizeofStaticPacketData-1]
+ testPacket = append(testPacket, 255)
+ }
+ if counter == 1 {
+ //append invalid auth size
+ testPacket = append(testPacket, enc[sizeofStaticPacketData:]...)
+ }
+ }
+
+ wantErr := "invalid auth size"
+ if _, err := net.nodeB.decode(testPacket); strings.HasSuffix(err.Error(), wantErr) {
+ t.Fatal(fmt.Errorf("(%s) got err %q, want %q", net.nodeB.ln.ID().TerminalString(), err, wantErr))
+ }
+ })
}
// This test checks that all test vectors can be decoded.
@@ -610,7 +641,7 @@ func (n *handshakeTestNode) n() *enode.Node {
}
func (n *handshakeTestNode) addr() string {
- return n.ln.Node().IP().String()
+ return n.ln.Node().IPAddr().String()
}
func (n *handshakeTestNode) id() enode.ID {
diff --git a/p2p/dnsdisc/client.go b/p2p/dnsdisc/client.go
index 0ba9bce3d1..41a44ababa 100644
--- a/p2p/dnsdisc/client.go
+++ b/p2p/dnsdisc/client.go
@@ -215,7 +215,7 @@ func (c *Client) resolveEntry(ctx context.Context, domain, hash string) (entry,
func (c *Client) doResolveEntry(ctx context.Context, domain, hash string) (entry, error) {
wantHash, err := b32format.DecodeString(hash)
if err != nil {
- return nil, fmt.Errorf("invalid base32 hash")
+ return nil, errors.New("invalid base32 hash")
}
name := hash + "." + domain
diff --git a/p2p/dnsdisc/client_test.go b/p2p/dnsdisc/client_test.go
index 9f8cf4d0b2..f46cb23503 100644
--- a/p2p/dnsdisc/client_test.go
+++ b/p2p/dnsdisc/client_test.go
@@ -20,6 +20,7 @@ import (
"context"
"crypto/ecdsa"
"errors"
+ "maps"
"reflect"
"testing"
"time"
@@ -226,8 +227,7 @@ func TestIteratorNodeUpdates(t *testing.T) {
// Ensure RandomNode returns the new nodes after the tree is updated.
updateSomeNodes(keys, nodes)
tree2, _ := makeTestTree("n", nodes, nil)
-
- resolver.clear()
+ clear(resolver)
resolver.add(tree2.ToTXT("n"))
t.Log("tree updated")
@@ -270,8 +270,7 @@ func TestIteratorRootRecheckOnFail(t *testing.T) {
// Ensure RandomNode returns the new nodes after the tree is updated.
updateSomeNodes(keys, nodes)
tree2, _ := makeTestTree("n", nodes, nil)
-
- resolver.clear()
+ clear(resolver)
resolver.add(tree2.ToTXT("n"))
t.Log("tree updated")
@@ -481,16 +480,8 @@ func newMapResolver(maps ...map[string]string) mapResolver {
return mr
}
-func (mr mapResolver) clear() {
- for k := range mr {
- delete(mr, k)
- }
-}
-
func (mr mapResolver) add(m map[string]string) {
- for k, v := range m {
- mr[k] = v
- }
+ maps.Copy(mr, m)
}
func (mr mapResolver) LookupTXT(ctx context.Context, name string) ([]string, error) {
diff --git a/p2p/dnsdisc/tree.go b/p2p/dnsdisc/tree.go
index 4d6686eda2..fc98b55a91 100644
--- a/p2p/dnsdisc/tree.go
+++ b/p2p/dnsdisc/tree.go
@@ -21,8 +21,10 @@ import (
"crypto/ecdsa"
"encoding/base32"
"encoding/base64"
+ "errors"
"fmt"
"io"
+ "slices"
"strings"
"github.com/ethereum/go-ethereum/crypto"
@@ -30,7 +32,6 @@ import (
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/ethereum/go-ethereum/rlp"
"golang.org/x/crypto/sha3"
- "golang.org/x/exp/slices"
)
// Tree is a merkle tree of node records.
@@ -377,18 +378,16 @@ func parseLinkEntry(e string) (entry, error) {
func parseLink(e string) (*linkEntry, error) {
if !strings.HasPrefix(e, linkPrefix) {
- return nil, fmt.Errorf("wrong/missing scheme 'enrtree' in URL")
+ return nil, errors.New("wrong/missing scheme 'enrtree' in URL")
}
e = e[len(linkPrefix):]
- pos := strings.IndexByte(e, '@')
- if pos == -1 {
+ keystring, domain, found := strings.Cut(e, "@")
+ if !found {
return nil, entryError{"link", errNoPubkey}
}
- keystring, domain := e[:pos], e[pos+1:]
-
keybytes, err := b32format.DecodeString(keystring)
if err != nil {
return nil, entryError{"link", errBadPubkey}
diff --git a/p2p/enode/idscheme.go b/p2p/enode/idscheme.go
index d07ea23a8c..35fa210658 100644
--- a/p2p/enode/idscheme.go
+++ b/p2p/enode/idscheme.go
@@ -18,7 +18,7 @@ package enode
import (
"crypto/ecdsa"
- "fmt"
+ "errors"
"io"
"github.com/ethereum/go-ethereum/common/math"
@@ -70,7 +70,7 @@ func (V4ID) Verify(r *enr.Record, sig []byte) error {
if err := r.Load(&entry); err != nil {
return err
} else if len(entry) != 33 {
- return fmt.Errorf("invalid public key")
+ return errors.New("invalid public key")
}
h := sha3.NewLegacyKeccak256()
diff --git a/p2p/enode/localnode.go b/p2p/enode/localnode.go
index 66a56ad4e9..34741144ae 100644
--- a/p2p/enode/localnode.go
+++ b/p2p/enode/localnode.go
@@ -21,8 +21,8 @@ import (
"fmt"
"math"
"net"
+ "net/netip"
"reflect"
- "strconv"
"sync"
"sync/atomic"
"time"
@@ -178,8 +178,8 @@ func (ln *LocalNode) delete(e enr.Entry) {
}
}
-func (ln *LocalNode) endpointForIP(ip net.IP) *lnEndpoint {
- if ip.To4() != nil {
+func (ln *LocalNode) endpointForIP(ip netip.Addr) *lnEndpoint {
+ if ip.Is4() {
return &ln.endpoint4
}
@@ -192,7 +192,7 @@ func (ln *LocalNode) SetStaticIP(ip net.IP) {
ln.mu.Lock()
defer ln.mu.Unlock()
- ln.endpointForIP(ip).staticIP = ip
+ ln.endpointForIP(netutil.IPToAddr(ip)).staticIP = ip
ln.updateEndpoints()
}
@@ -202,7 +202,7 @@ func (ln *LocalNode) SetFallbackIP(ip net.IP) {
ln.mu.Lock()
defer ln.mu.Unlock()
- ln.endpointForIP(ip).fallbackIP = ip
+ ln.endpointForIP(netutil.IPToAddr(ip)).fallbackIP = ip
ln.updateEndpoints()
}
@@ -222,21 +222,21 @@ func (ln *LocalNode) SetFallbackUDP(port int) {
// UDPEndpointStatement should be called whenever a statement about the local node's
// UDP endpoint is received. It feeds the local endpoint predictor.
-func (ln *LocalNode) UDPEndpointStatement(fromaddr, endpoint *net.UDPAddr) {
+func (ln *LocalNode) UDPEndpointStatement(fromaddr, endpoint netip.AddrPort) {
ln.mu.Lock()
defer ln.mu.Unlock()
- ln.endpointForIP(endpoint.IP).track.AddStatement(fromaddr.String(), endpoint.String())
+ ln.endpointForIP(endpoint.Addr()).track.AddStatement(fromaddr.Addr(), endpoint)
ln.updateEndpoints()
}
// UDPContact should be called whenever the local node has announced itself to another node
// via UDP. It feeds the local endpoint predictor.
-func (ln *LocalNode) UDPContact(toaddr *net.UDPAddr) {
+func (ln *LocalNode) UDPContact(toaddr netip.AddrPort) {
ln.mu.Lock()
defer ln.mu.Unlock()
- ln.endpointForIP(toaddr.IP).track.AddContact(toaddr.String())
+ ln.endpointForIP(toaddr.Addr()).track.AddContact(toaddr.Addr())
ln.updateEndpoints()
}
@@ -280,33 +280,14 @@ func (e *lnEndpoint) get() (newIP net.IP, newPort uint16) {
if e.staticIP != nil {
newIP = e.staticIP
- } else if ip, port := predictAddr(e.track); ip != nil {
- newIP = ip
- newPort = port
+ } else if ap := e.track.PredictEndpoint(); ap.IsValid() {
+ newIP = ap.Addr().AsSlice()
+ newPort = ap.Port()
}
return newIP, newPort
}
-// predictAddr wraps IPTracker.PredictEndpoint, converting from its string-based
-// endpoint representation to IP and port types.
-func predictAddr(t *netutil.IPTracker) (net.IP, uint16) {
- ep := t.PredictEndpoint()
- if ep == "" {
- return nil, 0
- }
-
- ipString, portString, _ := net.SplitHostPort(ep)
- ip := net.ParseIP(ipString)
-
- port, err := strconv.ParseUint(portString, 10, 16)
- if err != nil {
- return nil, 0
- }
-
- return ip, uint16(port)
-}
-
func (ln *LocalNode) invalidate() {
ln.cur.Store((*Node)(nil))
}
@@ -334,7 +315,7 @@ func (ln *LocalNode) sign() {
}
ln.cur.Store(n)
- log.Info("New local node record", "seq", ln.seq, "id", n.ID(), "ip", n.IP(), "udp", n.UDP(), "tcp", n.TCP())
+ log.Info("New local node record", "seq", ln.seq, "id", n.ID(), "ip", n.IPAddr(), "udp", n.UDP(), "tcp", n.TCP())
}
func (ln *LocalNode) bumpSeq() {
diff --git a/p2p/enode/localnode_test.go b/p2p/enode/localnode_test.go
index de5f0f6c93..c0887a12e5 100644
--- a/p2p/enode/localnode_test.go
+++ b/p2p/enode/localnode_test.go
@@ -17,12 +17,14 @@
package enode
import (
- "crypto/rand"
+ "math/rand"
"net"
+ "net/netip"
"testing"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p/enr"
+ "github.com/ethereum/go-ethereum/p2p/netutil"
"github.com/stretchr/testify/assert"
)
@@ -92,6 +94,7 @@ func TestLocalNodeSeqPersist(t *testing.T) {
// This test checks behavior of the endpoint predictor.
func TestLocalNodeEndpoint(t *testing.T) {
var (
+ rng = rand.New(rand.NewSource(4))
fallback = &net.UDPAddr{IP: net.IP{127, 0, 0, 1}, Port: 80}
predicted = &net.UDPAddr{IP: net.IP{127, 0, 1, 2}, Port: 81}
staticIP = net.IP{127, 0, 1, 2}
@@ -101,6 +104,7 @@ func TestLocalNodeEndpoint(t *testing.T) {
defer db.Close()
// Nothing is set initially.
+ assert.Equal(t, netip.Addr{}, ln.Node().IPAddr())
assert.Equal(t, net.IP(nil), ln.Node().IP())
assert.Equal(t, 0, ln.Node().UDP())
initialSeq := ln.Node().Seq()
@@ -108,26 +112,30 @@ func TestLocalNodeEndpoint(t *testing.T) {
// Set up fallback address.
ln.SetFallbackIP(fallback.IP)
ln.SetFallbackUDP(fallback.Port)
+ assert.Equal(t, netutil.IPToAddr(fallback.IP), ln.Node().IPAddr())
assert.Equal(t, fallback.IP, ln.Node().IP())
assert.Equal(t, fallback.Port, ln.Node().UDP())
assert.Equal(t, initialSeq+1, ln.Node().Seq())
// Add endpoint statements from random hosts.
for i := 0; i < iptrackMinStatements; i++ {
+ assert.Equal(t, netutil.IPToAddr(fallback.IP), ln.Node().IPAddr())
assert.Equal(t, fallback.IP, ln.Node().IP())
assert.Equal(t, fallback.Port, ln.Node().UDP())
assert.Equal(t, initialSeq+1, ln.Node().Seq())
- from := &net.UDPAddr{IP: make(net.IP, 4), Port: 90}
- rand.Read(from.IP)
- ln.UDPEndpointStatement(from, predicted)
+ from := netip.AddrPortFrom(netutil.RandomAddr(rng, true), 9000)
+ endpoint := netip.AddrPortFrom(netutil.IPToAddr(predicted.IP), uint16(predicted.Port))
+ ln.UDPEndpointStatement(from, endpoint)
}
+ assert.Equal(t, netutil.IPToAddr(predicted.IP), ln.Node().IPAddr())
assert.Equal(t, predicted.IP, ln.Node().IP())
assert.Equal(t, predicted.Port, ln.Node().UDP())
assert.Equal(t, initialSeq+2, ln.Node().Seq())
// Static IP overrides prediction.
ln.SetStaticIP(staticIP)
+ assert.Equal(t, netutil.IPToAddr(staticIP), ln.Node().IPAddr())
assert.Equal(t, staticIP, ln.Node().IP())
assert.Equal(t, fallback.Port, ln.Node().UDP())
assert.Equal(t, initialSeq+3, ln.Node().Seq())
diff --git a/p2p/enode/nodedb.go b/p2p/enode/nodedb.go
index a83c7a6733..e111d11f84 100644
--- a/p2p/enode/nodedb.go
+++ b/p2p/enode/nodedb.go
@@ -21,7 +21,7 @@ import (
"crypto/rand"
"encoding/binary"
"fmt"
- "net"
+ "net/netip"
"os"
"sync"
"time"
@@ -66,7 +66,7 @@ var (
errInvalidIP = errors.New("invalid IP")
)
-var zeroIP = make(net.IP, 16)
+var zeroIP = netip.IPv6Unspecified()
// DB is the node database, storing previously seen nodes and any collected metadata about
// them for QoS purposes.
@@ -86,7 +86,7 @@ func OpenDB(path string) (*DB, error) {
return newPersistentDB(path)
}
-// newMemoryNodeDB creates a new in-memory node database without a persistent backend.
+// newMemoryDB creates a new in-memory node database without a persistent backend.
func newMemoryDB() (*DB, error) {
db, err := leveldb.Open(storage.NewMemStorage(), nil)
if err != nil {
@@ -96,7 +96,7 @@ func newMemoryDB() (*DB, error) {
return &DB{lvl: db, quit: make(chan struct{})}, nil
}
-// newPersistentNodeDB creates/opens a leveldb backed persistent node database,
+// newPersistentDB creates/opens a leveldb backed persistent node database,
// also flushing its contents in case of a version mismatch.
func newPersistentDB(path string) (*DB, error) {
opts := &opt.Options{OpenFilesCacheCapacity: 5}
@@ -161,30 +161,25 @@ func splitNodeKey(key []byte) (id ID, rest []byte) {
}
// nodeItemKey returns the database key for a node metadata field.
-func nodeItemKey(id ID, ip net.IP, field string) []byte {
- ip16 := ip.To16()
- if ip16 == nil {
- panic(fmt.Errorf("invalid IP (length %d)", len(ip)))
+func nodeItemKey(id ID, ip netip.Addr, field string) []byte {
+ if !ip.IsValid() {
+ panic("invalid IP")
}
-
- return bytes.Join([][]byte{nodeKey(id), ip16, []byte(field)}, []byte{':'})
+ ip16 := ip.As16()
+ return bytes.Join([][]byte{nodeKey(id), ip16[:], []byte(field)}, []byte{':'})
}
// splitNodeItemKey returns the components of a key created by nodeItemKey.
-func splitNodeItemKey(key []byte) (id ID, ip net.IP, field string) {
+func splitNodeItemKey(key []byte) (id ID, ip netip.Addr, field string) {
id, key = splitNodeKey(key)
// Skip discover root.
if string(key) == dbDiscoverRoot {
- return id, nil, ""
+ return id, netip.Addr{}, ""
}
key = key[len(dbDiscoverRoot)+1:]
// Split out the IP.
- ip = key[:16]
- if ip4 := ip.To4(); ip4 != nil {
- ip = ip4
- }
-
+ ip, _ = netip.AddrFromSlice(key[:16])
key = key[16+1:]
// Field is the remainder of key.
field = string(key)
@@ -192,12 +187,13 @@ func splitNodeItemKey(key []byte) (id ID, ip net.IP, field string) {
return id, ip, field
}
-func v5Key(id ID, ip net.IP, field string) []byte {
+func v5Key(id ID, ip netip.Addr, field string) []byte {
+ ip16 := ip.As16()
return bytes.Join([][]byte{
[]byte(dbNodePrefix),
id[:],
[]byte(dbDiscv5Root),
- ip.To16(),
+ ip16[:],
[]byte(field),
}, []byte{':'})
}
@@ -398,8 +394,8 @@ func (db *DB) expireNodes() {
// LastPingReceived retrieves the time of the last ping packet received from
// a remote node.
-func (db *DB) LastPingReceived(id ID, ip net.IP) time.Time {
- if ip = ip.To16(); ip == nil {
+func (db *DB) LastPingReceived(id ID, ip netip.Addr) time.Time {
+ if !ip.IsValid() {
return time.Time{}
}
@@ -407,8 +403,8 @@ func (db *DB) LastPingReceived(id ID, ip net.IP) time.Time {
}
// UpdateLastPingReceived updates the last time we tried contacting a remote node.
-func (db *DB) UpdateLastPingReceived(id ID, ip net.IP, instance time.Time) error {
- if ip = ip.To16(); ip == nil {
+func (db *DB) UpdateLastPingReceived(id ID, ip netip.Addr, instance time.Time) error {
+ if !ip.IsValid() {
return errInvalidIP
}
@@ -416,8 +412,8 @@ func (db *DB) UpdateLastPingReceived(id ID, ip net.IP, instance time.Time) error
}
// LastPongReceived retrieves the time of the last successful pong from remote node.
-func (db *DB) LastPongReceived(id ID, ip net.IP) time.Time {
- if ip = ip.To16(); ip == nil {
+func (db *DB) LastPongReceived(id ID, ip netip.Addr) time.Time {
+ if !ip.IsValid() {
return time.Time{}
}
// Launch expirer
@@ -427,8 +423,8 @@ func (db *DB) LastPongReceived(id ID, ip net.IP) time.Time {
}
// UpdateLastPongReceived updates the last pong time of a node.
-func (db *DB) UpdateLastPongReceived(id ID, ip net.IP, instance time.Time) error {
- if ip = ip.To16(); ip == nil {
+func (db *DB) UpdateLastPongReceived(id ID, ip netip.Addr, instance time.Time) error {
+ if !ip.IsValid() {
return errInvalidIP
}
@@ -436,8 +432,8 @@ func (db *DB) UpdateLastPongReceived(id ID, ip net.IP, instance time.Time) error
}
// FindFails retrieves the number of findnode failures since bonding.
-func (db *DB) FindFails(id ID, ip net.IP) int {
- if ip = ip.To16(); ip == nil {
+func (db *DB) FindFails(id ID, ip netip.Addr) int {
+ if !ip.IsValid() {
return 0
}
@@ -445,8 +441,8 @@ func (db *DB) FindFails(id ID, ip net.IP) int {
}
// UpdateFindFails updates the number of findnode failures since bonding.
-func (db *DB) UpdateFindFails(id ID, ip net.IP, fails int) error {
- if ip = ip.To16(); ip == nil {
+func (db *DB) UpdateFindFails(id ID, ip netip.Addr, fails int) error {
+ if !ip.IsValid() {
return errInvalidIP
}
@@ -454,8 +450,8 @@ func (db *DB) UpdateFindFails(id ID, ip net.IP, fails int) error {
}
// FindFailsV5 retrieves the discv5 findnode failure counter.
-func (db *DB) FindFailsV5(id ID, ip net.IP) int {
- if ip = ip.To16(); ip == nil {
+func (db *DB) FindFailsV5(id ID, ip netip.Addr) int {
+ if !ip.IsValid() {
return 0
}
@@ -463,8 +459,8 @@ func (db *DB) FindFailsV5(id ID, ip net.IP) int {
}
// UpdateFindFailsV5 stores the discv5 findnode failure counter.
-func (db *DB) UpdateFindFailsV5(id ID, ip net.IP, fails int) error {
- if ip = ip.To16(); ip == nil {
+func (db *DB) UpdateFindFailsV5(id ID, ip netip.Addr, fails int) error {
+ if !ip.IsValid() {
return errInvalidIP
}
@@ -514,7 +510,7 @@ seek:
id[0] = 0
continue seek // iterator exhausted
}
- if now.Sub(db.LastPongReceived(n.ID(), n.IP())) > maxAge {
+ if now.Sub(db.LastPongReceived(n.ID(), n.IPAddr())) > maxAge {
continue seek
}
for i := range nodes {
diff --git a/p2p/enode/nodedb_test.go b/p2p/enode/nodedb_test.go
index f71e71e112..0c890bbd55 100644
--- a/p2p/enode/nodedb_test.go
+++ b/p2p/enode/nodedb_test.go
@@ -20,6 +20,7 @@ import (
"bytes"
"fmt"
"net"
+ "net/netip"
"path/filepath"
"reflect"
"testing"
@@ -50,8 +51,10 @@ func TestDBNodeKey(t *testing.T) {
}
func TestDBNodeItemKey(t *testing.T) {
- wantIP := net.IP{127, 0, 0, 3}
+ wantIP := netip.MustParseAddr("127.0.0.3")
+ wantIP4in6 := netip.AddrFrom16(wantIP.As16())
wantField := "foobar"
+
enc := nodeItemKey(keytestID, wantIP, wantField)
want := []byte{
'n', ':',
@@ -73,8 +76,7 @@ func TestDBNodeItemKey(t *testing.T) {
if id != keytestID {
t.Errorf("splitNodeItemKey returned wrong ID: %v", id)
}
-
- if !ip.Equal(wantIP) {
+ if ip != wantIP4in6 {
t.Errorf("splitNodeItemKey returned wrong IP: %v", ip)
}
@@ -130,39 +132,33 @@ func TestDBFetchStore(t *testing.T) {
defer db.Close()
// Check fetch/store operations on a node ping object
- if stored := db.LastPingReceived(node.ID(), node.IP()); stored.Unix() != 0 {
+ if stored := db.LastPingReceived(node.ID(), node.IPAddr()); stored.Unix() != 0 {
t.Errorf("ping: non-existing object: %v", stored)
}
-
- if err := db.UpdateLastPingReceived(node.ID(), node.IP(), inst); err != nil {
+ if err := db.UpdateLastPingReceived(node.ID(), node.IPAddr(), inst); err != nil {
t.Errorf("ping: failed to update: %v", err)
}
-
- if stored := db.LastPingReceived(node.ID(), node.IP()); stored.Unix() != inst.Unix() {
+ if stored := db.LastPingReceived(node.ID(), node.IPAddr()); stored.Unix() != inst.Unix() {
t.Errorf("ping: value mismatch: have %v, want %v", stored, inst)
}
// Check fetch/store operations on a node pong object
- if stored := db.LastPongReceived(node.ID(), node.IP()); stored.Unix() != 0 {
+ if stored := db.LastPongReceived(node.ID(), node.IPAddr()); stored.Unix() != 0 {
t.Errorf("pong: non-existing object: %v", stored)
}
-
- if err := db.UpdateLastPongReceived(node.ID(), node.IP(), inst); err != nil {
+ if err := db.UpdateLastPongReceived(node.ID(), node.IPAddr(), inst); err != nil {
t.Errorf("pong: failed to update: %v", err)
}
-
- if stored := db.LastPongReceived(node.ID(), node.IP()); stored.Unix() != inst.Unix() {
+ if stored := db.LastPongReceived(node.ID(), node.IPAddr()); stored.Unix() != inst.Unix() {
t.Errorf("pong: value mismatch: have %v, want %v", stored, inst)
}
// Check fetch/store operations on a node findnode-failure object
- if stored := db.FindFails(node.ID(), node.IP()); stored != 0 {
+ if stored := db.FindFails(node.ID(), node.IPAddr()); stored != 0 {
t.Errorf("find-node fails: non-existing object: %v", stored)
}
-
- if err := db.UpdateFindFails(node.ID(), node.IP(), num); err != nil {
+ if err := db.UpdateFindFails(node.ID(), node.IPAddr(), num); err != nil {
t.Errorf("find-node fails: failed to update: %v", err)
}
-
- if stored := db.FindFails(node.ID(), node.IP()); stored != num {
+ if stored := db.FindFails(node.ID(), node.IPAddr()); stored != num {
t.Errorf("find-node fails: value mismatch: have %v, want %v", stored, num)
}
// Check fetch/store operations on an actual node object
@@ -283,8 +279,7 @@ func testSeedQuery() error {
if err := db.UpdateNode(seed.node); err != nil {
return fmt.Errorf("node %d: failed to insert: %v", i, err)
}
-
- if err := db.UpdateLastPongReceived(seed.node.ID(), seed.node.IP(), seed.pong); err != nil {
+ if err := db.UpdateLastPongReceived(seed.node.ID(), seed.node.IPAddr(), seed.pong); err != nil {
return fmt.Errorf("node %d: failed to insert bondTime: %v", i, err)
}
}
@@ -453,8 +448,7 @@ func TestDBExpiration(t *testing.T) {
t.Fatalf("node %d: failed to insert: %v", i, err)
}
}
-
- if err := db.UpdateLastPongReceived(seed.node.ID(), seed.node.IP(), seed.pong); err != nil {
+ if err := db.UpdateLastPongReceived(seed.node.ID(), seed.node.IPAddr(), seed.pong); err != nil {
t.Fatalf("node %d: failed to update bondTime: %v", i, err)
}
}
@@ -466,15 +460,14 @@ func TestDBExpiration(t *testing.T) {
for i, seed := range nodeDBExpirationNodes {
node := db.Node(seed.node.ID())
- pong := db.LastPongReceived(seed.node.ID(), seed.node.IP())
-
+ pong := db.LastPongReceived(seed.node.ID(), seed.node.IPAddr())
if seed.exp {
if seed.storeNode && node != nil {
t.Errorf("node %d (%s) shouldn't be present after expiration", i, seed.node.ID().TerminalString())
}
if !pong.Equal(unixZeroTime) {
- t.Errorf("pong time %d (%s %v) shouldn't be present after expiration", i, seed.node.ID().TerminalString(), seed.node.IP())
+ t.Errorf("pong time %d (%s %v) shouldn't be present after expiration", i, seed.node.ID().TerminalString(), seed.node.IPAddr())
}
} else {
if seed.storeNode && node == nil {
@@ -494,7 +487,7 @@ func TestDBExpireV5(t *testing.T) {
db, _ := OpenDB("")
defer db.Close()
- ip := net.IP{127, 0, 0, 1}
+ ip := netip.MustParseAddr("127.0.0.1")
db.UpdateFindFailsV5(ID{}, ip, 4)
db.expireNodes()
}
diff --git a/p2p/enr/enr_test.go b/p2p/enr/enr_test.go
index 6ccb617bc0..4f779ef31d 100644
--- a/p2p/enr/enr_test.go
+++ b/p2p/enr/enr_test.go
@@ -52,7 +52,7 @@ func TestGetSetID(t *testing.T) {
assert.Equal(t, id, id2)
}
-// TestGetSetIP4 tests encoding/decoding and setting/getting of the IP key.
+// TestGetSetIPv4 tests encoding/decoding and setting/getting of the IP key.
func TestGetSetIPv4(t *testing.T) {
ip := IPv4{192, 168, 0, 3}
@@ -66,7 +66,7 @@ func TestGetSetIPv4(t *testing.T) {
assert.Equal(t, ip, ip2)
}
-// TestGetSetIP6 tests encoding/decoding and setting/getting of the IP6 key.
+// TestGetSetIPv6 tests encoding/decoding and setting/getting of the IP6 key.
func TestGetSetIPv6(t *testing.T) {
ip := IPv6{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x00, 0x68}
diff --git a/p2p/metrics.go b/p2p/metrics.go
index 9a38e2afdb..bd73f1b06e 100644
--- a/p2p/metrics.go
+++ b/p2p/metrics.go
@@ -37,7 +37,9 @@ const (
)
var (
- activePeerGauge metrics.Gauge = metrics.NilGauge{}
+ activePeerGauge metrics.Gauge = metrics.NilGauge{}
+ activeInboundPeerGauge metrics.Gauge = metrics.NilGauge{}
+ activeOutboundPeerGauge metrics.Gauge = metrics.NilGauge{}
ingressTrafficMeter = metrics.NewRegisteredMeter("p2p/ingress", nil)
egressTrafficMeter = metrics.NewRegisteredMeter("p2p/egress", nil)
@@ -65,6 +67,8 @@ func init() {
}
activePeerGauge = metrics.NewRegisteredGauge("p2p/peers", nil)
+ activeInboundPeerGauge = metrics.NewRegisteredGauge("p2p/peers/inbound", nil)
+ activeOutboundPeerGauge = metrics.NewRegisteredGauge("p2p/peers/outbound", nil)
serveMeter = metrics.NewRegisteredMeter("p2p/serves", nil)
serveSuccessMeter = metrics.NewRegisteredMeter("p2p/serves/success", nil)
dialMeter = metrics.NewRegisteredMeter("p2p/dials", nil)
diff --git a/p2p/nat/natpmp.go b/p2p/nat/natpmp.go
index 3194009d17..4ae511de72 100644
--- a/p2p/nat/natpmp.go
+++ b/p2p/nat/natpmp.go
@@ -17,6 +17,7 @@
package nat
import (
+ "errors"
"fmt"
"net"
"strings"
@@ -25,7 +26,7 @@ import (
natpmp "github.com/jackpal/go-nat-pmp"
)
-// natPMPClient adapts the NAT-PMP protocol implementation so it conforms to
+// pmp adapts the NAT-PMP protocol implementation so it conforms to
// the common interface.
type pmp struct {
gw net.IP
@@ -47,7 +48,7 @@ func (n *pmp) ExternalIP() (net.IP, error) {
func (n *pmp) AddMapping(protocol string, extport, intport int, name string, lifetime time.Duration) (uint16, error) {
if lifetime <= 0 {
- return 0, fmt.Errorf("lifetime must not be <= 0")
+ return 0, errors.New("lifetime must not be <= 0")
}
// Note order of port arguments is switched between our
// AddMapping and the client's AddPortMapping.
diff --git a/p2p/nat/natupnp.go b/p2p/nat/natupnp.go
index 0e2629809b..803adab4f3 100644
--- a/p2p/nat/natupnp.go
+++ b/p2p/nat/natupnp.go
@@ -223,8 +223,8 @@ func discoverUPnP() Interface {
return nil
}
-// finds devices matching the given target and calls matcher for all
-// advertised services of each device. The first non-nil service found
+// discover finds devices matching the given target and calls matcher for
+// all advertised services of each device. The first non-nil service found
// is sent into out. If no service matched, nil is sent.
func discover(out chan<- *upnp, target string, matcher func(goupnp.ServiceClient) *upnp) {
devs, err := goupnp.DiscoverDevices(target)
diff --git a/p2p/netutil/addrutil.go b/p2p/netutil/addrutil.go
index fb6d8d2731..b8b318571b 100644
--- a/p2p/netutil/addrutil.go
+++ b/p2p/netutil/addrutil.go
@@ -16,18 +16,53 @@
package netutil
-import "net"
+import (
+ "fmt"
+ "math/rand"
+ "net"
+ "net/netip"
+)
-// AddrIP gets the IP address contained in addr. It returns nil if no address is present.
-func AddrIP(addr net.Addr) net.IP {
+// AddrAddr gets the IP address contained in addr. The result will be invalid if the
+// address type is unsupported.
+func AddrAddr(addr net.Addr) netip.Addr {
switch a := addr.(type) {
case *net.IPAddr:
- return a.IP
+ return IPToAddr(a.IP)
case *net.TCPAddr:
- return a.IP
+ return IPToAddr(a.IP)
case *net.UDPAddr:
- return a.IP
+ return IPToAddr(a.IP)
default:
- return nil
+ return netip.Addr{}
}
}
+
+// IPToAddr converts net.IP to netip.Addr. Note that unlike netip.AddrFromSlice, this
+// function will always ensure that the resulting Addr is IPv4 when the input is.
+func IPToAddr(ip net.IP) netip.Addr {
+ if ip4 := ip.To4(); ip4 != nil {
+ addr, _ := netip.AddrFromSlice(ip4)
+ return addr
+ } else if ip6 := ip.To16(); ip6 != nil {
+ addr, _ := netip.AddrFromSlice(ip6)
+ return addr
+ }
+ return netip.Addr{}
+}
+
+// RandomAddr creates a random IP address.
+func RandomAddr(rng *rand.Rand, ipv4 bool) netip.Addr {
+ var bytes []byte
+ if ipv4 || rng.Intn(2) == 0 {
+ bytes = make([]byte, 4)
+ } else {
+ bytes = make([]byte, 16)
+ }
+ rng.Read(bytes)
+ addr, ok := netip.AddrFromSlice(bytes)
+ if !ok {
+ panic(fmt.Errorf("BUG! invalid IP %v", bytes))
+ }
+ return addr
+}
diff --git a/p2p/netutil/iptrack.go b/p2p/netutil/iptrack.go
index 2d776de5d2..d730aeb162 100644
--- a/p2p/netutil/iptrack.go
+++ b/p2p/netutil/iptrack.go
@@ -17,6 +17,7 @@
package netutil
import (
+ "net/netip"
"time"
"github.com/ethereum/go-ethereum/common/mclock"
@@ -29,14 +30,14 @@ type IPTracker struct {
contactWindow time.Duration
minStatements int
clock mclock.Clock
- statements map[string]ipStatement
- contact map[string]mclock.AbsTime
+ statements map[netip.Addr]ipStatement
+ contact map[netip.Addr]mclock.AbsTime
lastStatementGC mclock.AbsTime
lastContactGC mclock.AbsTime
}
type ipStatement struct {
- endpoint string
+ endpoint netip.AddrPort
time mclock.AbsTime
}
@@ -51,9 +52,9 @@ func NewIPTracker(window, contactWindow time.Duration, minStatements int) *IPTra
return &IPTracker{
window: window,
contactWindow: contactWindow,
- statements: make(map[string]ipStatement),
+ statements: make(map[netip.Addr]ipStatement),
minStatements: minStatements,
- contact: make(map[string]mclock.AbsTime),
+ contact: make(map[netip.Addr]mclock.AbsTime),
clock: mclock.System{},
}
}
@@ -76,13 +77,15 @@ func (it *IPTracker) PredictFullConeNAT() bool {
}
// PredictEndpoint returns the current prediction of the external endpoint.
-func (it *IPTracker) PredictEndpoint() string {
+func (it *IPTracker) PredictEndpoint() netip.AddrPort {
it.gcStatements(it.clock.Now())
// The current strategy is simple: find the endpoint with most statements.
- counts := make(map[string]int, len(it.statements))
- maxcount, max := 0, ""
-
+ var (
+ counts = make(map[netip.AddrPort]int, len(it.statements))
+ maxcount int
+ max netip.AddrPort
+ )
for _, s := range it.statements {
c := counts[s.endpoint] + 1
counts[s.endpoint] = c
@@ -96,7 +99,7 @@ func (it *IPTracker) PredictEndpoint() string {
}
// AddStatement records that a certain host thinks our external endpoint is the one given.
-func (it *IPTracker) AddStatement(host, endpoint string) {
+func (it *IPTracker) AddStatement(host netip.Addr, endpoint netip.AddrPort) {
now := it.clock.Now()
it.statements[host] = ipStatement{endpoint, now}
@@ -107,7 +110,7 @@ func (it *IPTracker) AddStatement(host, endpoint string) {
// AddContact records that a packet containing our endpoint information has been sent to a
// certain host.
-func (it *IPTracker) AddContact(host string) {
+func (it *IPTracker) AddContact(host netip.Addr) {
now := it.clock.Now()
it.contact[host] = now
diff --git a/p2p/netutil/iptrack_test.go b/p2p/netutil/iptrack_test.go
index bf0bf2e905..0f2e1efb4e 100644
--- a/p2p/netutil/iptrack_test.go
+++ b/p2p/netutil/iptrack_test.go
@@ -19,6 +19,7 @@ package netutil
import (
crand "crypto/rand"
"fmt"
+ "net/netip"
"testing"
"time"
@@ -42,37 +43,37 @@ func TestIPTracker(t *testing.T) {
tests := map[string][]iptrackTestEvent{
"minStatements": {
{opPredict, 0, "", ""},
- {opStatement, 0, "127.0.0.1", "127.0.0.2"},
+ {opStatement, 0, "127.0.0.1:8000", "127.0.0.2"},
{opPredict, 1000, "", ""},
- {opStatement, 1000, "127.0.0.1", "127.0.0.3"},
+ {opStatement, 1000, "127.0.0.1:8000", "127.0.0.3"},
{opPredict, 1000, "", ""},
- {opStatement, 1000, "127.0.0.1", "127.0.0.4"},
- {opPredict, 1000, "127.0.0.1", ""},
+ {opStatement, 1000, "127.0.0.1:8000", "127.0.0.4"},
+ {opPredict, 1000, "127.0.0.1:8000", ""},
},
"window": {
- {opStatement, 0, "127.0.0.1", "127.0.0.2"},
- {opStatement, 2000, "127.0.0.1", "127.0.0.3"},
- {opStatement, 3000, "127.0.0.1", "127.0.0.4"},
- {opPredict, 10000, "127.0.0.1", ""},
+ {opStatement, 0, "127.0.0.1:8000", "127.0.0.2"},
+ {opStatement, 2000, "127.0.0.1:8000", "127.0.0.3"},
+ {opStatement, 3000, "127.0.0.1:8000", "127.0.0.4"},
+ {opPredict, 10000, "127.0.0.1:8000", ""},
{opPredict, 10001, "", ""}, // first statement expired
- {opStatement, 10100, "127.0.0.1", "127.0.0.2"},
- {opPredict, 10200, "127.0.0.1", ""},
+ {opStatement, 10100, "127.0.0.1:8000", "127.0.0.2"},
+ {opPredict, 10200, "127.0.0.1:8000", ""},
},
"fullcone": {
{opContact, 0, "", "127.0.0.2"},
- {opStatement, 10, "127.0.0.1", "127.0.0.2"},
+ {opStatement, 10, "127.0.0.1:8000", "127.0.0.2"},
{opContact, 2000, "", "127.0.0.3"},
- {opStatement, 2010, "127.0.0.1", "127.0.0.3"},
+ {opStatement, 2010, "127.0.0.1:8000", "127.0.0.3"},
{opContact, 3000, "", "127.0.0.4"},
- {opStatement, 3010, "127.0.0.1", "127.0.0.4"},
+ {opStatement, 3010, "127.0.0.1:8000", "127.0.0.4"},
{opCheckFullCone, 3500, "false", ""},
},
"fullcone_2": {
{opContact, 0, "", "127.0.0.2"},
- {opStatement, 10, "127.0.0.1", "127.0.0.2"},
+ {opStatement, 10, "127.0.0.1:8000", "127.0.0.2"},
{opContact, 2000, "", "127.0.0.3"},
- {opStatement, 2010, "127.0.0.1", "127.0.0.3"},
- {opStatement, 3000, "127.0.0.1", "127.0.0.4"},
+ {opStatement, 2010, "127.0.0.1:8000", "127.0.0.3"},
+ {opStatement, 3000, "127.0.0.1:8000", "127.0.0.4"},
{opContact, 3010, "", "127.0.0.4"},
{opCheckFullCone, 3500, "true", ""},
},
@@ -96,12 +97,19 @@ func runIPTrackerTest(t *testing.T, evs []iptrackTestEvent) {
switch ev.op {
case opStatement:
- it.AddStatement(ev.from, ev.ip)
+ it.AddStatement(netip.MustParseAddr(ev.from), netip.MustParseAddrPort(ev.ip))
case opContact:
- it.AddContact(ev.from)
+ it.AddContact(netip.MustParseAddr(ev.from))
case opPredict:
- if pred := it.PredictEndpoint(); pred != ev.ip {
- t.Errorf("op %d: wrong prediction %q, want %q", i, pred, ev.ip)
+ pred := it.PredictEndpoint()
+ if ev.ip == "" {
+ if pred.IsValid() {
+ t.Errorf("op %d: wrong prediction %v, expected invalid", i, pred)
+ }
+ } else {
+ if pred != netip.MustParseAddrPort(ev.ip) {
+ t.Errorf("op %d: wrong prediction %v, want %q", i, pred, ev.ip)
+ }
}
case opCheckFullCone:
pred := fmt.Sprintf("%t", it.PredictFullConeNAT())
@@ -125,12 +133,11 @@ func TestIPTrackerForceGC(t *testing.T) {
it.clock = &clock
for i := 0; i < 5*max; i++ {
- e1 := make([]byte, 4)
- e2 := make([]byte, 4)
- _, _ = crand.Read(e1)
- _, _ = crand.Read(e2)
- it.AddStatement(string(e1), string(e2))
- it.AddContact(string(e1))
+ var e1, e2 [4]byte
+ crand.Read(e1[:])
+ crand.Read(e2[:])
+ it.AddStatement(netip.AddrFrom4(e1), netip.AddrPortFrom(netip.AddrFrom4(e2), 9000))
+ it.AddContact(netip.AddrFrom4(e1))
clock.Run(rate)
}
diff --git a/p2p/netutil/net.go b/p2p/netutil/net.go
index 7fc357b8fb..0cf88f9ede 100644
--- a/p2p/netutil/net.go
+++ b/p2p/netutil/net.go
@@ -22,21 +22,19 @@ import (
"errors"
"fmt"
"net"
- "sort"
+ "net/netip"
+ "slices"
"strings"
+
+ "golang.org/x/exp/maps"
)
-var lan4, lan6, special4, special6 Netlist
+var special4, special6 Netlist
func init() {
// Lists from RFC 5735, RFC 5156,
// https://www.iana.org/assignments/iana-ipv4-special-registry/
- lan4.Add("0.0.0.0/8") // "This" network
- lan4.Add("10.0.0.0/8") // Private Use
- lan4.Add("172.16.0.0/12") // Private Use
- lan4.Add("192.168.0.0/16") // Private Use
- lan6.Add("fe80::/10") // Link-Local
- lan6.Add("fc00::/7") // Unique-Local
+ special4.Add("0.0.0.0/8") // "This" network.
special4.Add("192.0.0.0/29") // IPv4 Service Continuity
special4.Add("192.0.0.9/32") // PCP Anycast
special4.Add("192.0.0.170/32") // NAT64/DNS64 Discovery
@@ -66,7 +64,7 @@ func init() {
}
// Netlist is a list of IP networks.
-type Netlist []net.IPNet
+type Netlist []netip.Prefix
// ParseNetlist parses a comma-separated list of CIDR masks.
// Whitespace and extra commas are ignored.
@@ -79,13 +77,11 @@ func ParseNetlist(s string) (*Netlist, error) {
if mask == "" {
continue
}
-
- _, n, err := net.ParseCIDR(mask)
+ prefix, err := netip.ParsePrefix(mask)
if err != nil {
return nil, err
}
-
- l = append(l, *n)
+ l = append(l, prefix)
}
return &l, nil
@@ -109,12 +105,11 @@ func (l *Netlist) UnmarshalTOML(fn func(interface{}) error) error {
}
for _, mask := range masks {
- _, n, err := net.ParseCIDR(mask)
+ prefix, err := netip.ParsePrefix(mask)
if err != nil {
return err
}
-
- *l = append(*l, *n)
+ *l = append(*l, prefix)
}
return nil
@@ -123,16 +118,20 @@ func (l *Netlist) UnmarshalTOML(fn func(interface{}) error) error {
// Add parses a CIDR mask and appends it to the list. It panics for invalid masks and is
// intended to be used for setting up static lists.
func (l *Netlist) Add(cidr string) {
- _, n, err := net.ParseCIDR(cidr)
+ prefix, err := netip.ParsePrefix(cidr)
if err != nil {
panic(err)
}
-
- *l = append(*l, *n)
+ *l = append(*l, prefix)
}
// Contains reports whether the given IP is contained in the list.
func (l *Netlist) Contains(ip net.IP) bool {
+ return l.ContainsAddr(IPToAddr(ip))
+}
+
+// ContainsAddr reports whether the given IP is contained in the list.
+func (l *Netlist) ContainsAddr(ip netip.Addr) bool {
if l == nil {
return false
}
@@ -148,29 +147,39 @@ func (l *Netlist) Contains(ip net.IP) bool {
// IsLAN reports whether an IP is a local network address.
func IsLAN(ip net.IP) bool {
+ return AddrIsLAN(IPToAddr(ip))
+}
+
+// AddrIsLAN reports whether an IP is a local network address.
+func AddrIsLAN(ip netip.Addr) bool {
+ if ip.Is4In6() {
+ ip = netip.AddrFrom4(ip.As4())
+ }
if ip.IsLoopback() {
return true
}
-
- if v4 := ip.To4(); v4 != nil {
- return lan4.Contains(v4)
- }
-
- return lan6.Contains(ip)
+ return ip.IsPrivate() || ip.IsLinkLocalUnicast()
}
// IsSpecialNetwork reports whether an IP is located in a special-use network range
// This includes broadcast, multicast and documentation addresses.
func IsSpecialNetwork(ip net.IP) bool {
+ return AddrIsSpecialNetwork(IPToAddr(ip))
+}
+
+// AddrIsSpecialNetwork reports whether an IP is located in a special-use network range
+// This includes broadcast, multicast and documentation addresses.
+func AddrIsSpecialNetwork(ip netip.Addr) bool {
+ if ip.Is4In6() {
+ ip = netip.AddrFrom4(ip.As4())
+ }
if ip.IsMulticast() {
return true
}
-
- if v4 := ip.To4(); v4 != nil {
- return special4.Contains(v4)
+ if ip.Is4() {
+ return special4.ContainsAddr(ip)
}
-
- return special6.Contains(ip)
+ return special6.ContainsAddr(ip)
}
var (
@@ -190,23 +199,33 @@ var (
// - LAN addresses are OK if relayed by a LAN host.
// - All other addresses are always acceptable.
func CheckRelayIP(sender, addr net.IP) error {
- if len(addr) != net.IPv4len && len(addr) != net.IPv6len {
+ return CheckRelayAddr(IPToAddr(sender), IPToAddr(addr))
+}
+
+// CheckRelayAddr reports whether an IP relayed from the given sender IP
+// is a valid connection target.
+//
+// There are four rules:
+// - Special network addresses are never valid.
+// - Loopback addresses are OK if relayed by a loopback host.
+// - LAN addresses are OK if relayed by a LAN host.
+// - All other addresses are always acceptable.
+func CheckRelayAddr(sender, addr netip.Addr) error {
+ if !addr.IsValid() {
return errInvalid
}
if addr.IsUnspecified() {
return errUnspecified
}
-
- if IsSpecialNetwork(addr) {
+ if AddrIsSpecialNetwork(addr) {
return errSpecial
}
if addr.IsLoopback() && !sender.IsLoopback() {
return errLoopback
}
-
- if IsLAN(addr) && !IsLAN(sender) {
+ if AddrIsLAN(addr) && !AddrIsLAN(sender) {
return errLAN
}
@@ -244,18 +263,22 @@ type DistinctNetSet struct {
Subnet uint // number of common prefix bits
Limit uint // maximum number of IPs in each subnet
- members map[string]uint
- buf net.IP
+ members map[netip.Prefix]uint
}
// Add adds an IP address to the set. It returns false (and doesn't add the IP) if the
// number of existing IPs in the defined range exceeds the limit.
func (s *DistinctNetSet) Add(ip net.IP) bool {
- key := s.key(ip)
+ return s.AddAddr(IPToAddr(ip))
+}
- n := s.members[string(key)]
+// AddAddr adds an IP address to the set. It returns false (and doesn't add the IP) if the
+// number of existing IPs in the defined range exceeds the limit.
+func (s *DistinctNetSet) AddAddr(ip netip.Addr) bool {
+ key := s.key(ip)
+ n := s.members[key]
if n < s.Limit {
- s.members[string(key)] = n + 1
+ s.members[key] = n + 1
return true
}
@@ -264,21 +287,30 @@ func (s *DistinctNetSet) Add(ip net.IP) bool {
// Remove removes an IP from the set.
func (s *DistinctNetSet) Remove(ip net.IP) {
+ s.RemoveAddr(IPToAddr(ip))
+}
+
+// RemoveAddr removes an IP from the set.
+func (s *DistinctNetSet) RemoveAddr(ip netip.Addr) {
key := s.key(ip)
- if n, ok := s.members[string(key)]; ok {
+ if n, ok := s.members[key]; ok {
if n == 1 {
- delete(s.members, string(key))
+ delete(s.members, key)
} else {
- s.members[string(key)] = n - 1
+ s.members[key] = n - 1
}
}
}
-// Contains whether the given IP is contained in the set.
+// Contains reports whether the given IP is contained in the set.
func (s DistinctNetSet) Contains(ip net.IP) bool {
- key := s.key(ip)
- _, ok := s.members[string(key)]
+ return s.ContainsAddr(IPToAddr(ip))
+}
+// ContainsAddr reports whether the given IP is contained in the set.
+func (s DistinctNetSet) ContainsAddr(ip netip.Addr) bool {
+ key := s.key(ip)
+ _, ok := s.members[key]
return ok
}
@@ -292,63 +324,31 @@ func (s DistinctNetSet) Len() int {
return int(n)
}
-// key encodes the map key for an address into a temporary buffer.
-//
-// The first byte of key is '4' or '6' to distinguish IPv4/IPv6 address types.
-// The remainder of the key is the IP, truncated to the number of bits.
-func (s *DistinctNetSet) key(ip net.IP) net.IP {
+// key returns the map key for ip.
+func (s *DistinctNetSet) key(ip netip.Addr) netip.Prefix {
// Lazily initialize storage.
if s.members == nil {
- s.members = make(map[string]uint)
- s.buf = make(net.IP, 17)
- }
- // Canonicalize ip and bits.
- typ := byte('6')
- if ip4 := ip.To4(); ip4 != nil {
- typ, ip = '4', ip4
+ s.members = make(map[netip.Prefix]uint)
}
-
- bits := s.Subnet
- if bits > uint(len(ip)*8) {
- bits = uint(len(ip) * 8)
- }
- // Encode the prefix into s.buf.
- nb := int(bits / 8)
- mask := ^byte(0xFF >> (bits % 8))
- s.buf[0] = typ
-
- buf := append(s.buf[:1], ip[:nb]...)
- if nb < len(ip) && mask != 0 {
- buf = append(buf, ip[nb]&mask)
+ p, err := ip.Prefix(int(s.Subnet))
+ if err != nil {
+ panic(err)
}
-
- return buf
+ return p
}
// String implements fmt.Stringer
func (s DistinctNetSet) String() string {
+ keys := maps.Keys(s.members)
+ slices.SortFunc(keys, func(a, b netip.Prefix) int {
+ return strings.Compare(a.String(), b.String())
+ })
+
var buf bytes.Buffer
buf.WriteString("{")
-
- keys := make([]string, 0, len(s.members))
- for k := range s.members {
- keys = append(keys, k)
- }
-
- sort.Strings(keys)
-
for i, k := range keys {
- var ip net.IP
- if k[0] == '4' {
- ip = make(net.IP, 4)
- } else {
- ip = make(net.IP, 16)
- }
-
- copy(ip, k[1:])
- fmt.Fprintf(&buf, "%v×%d", ip, s.members[k])
-
+ fmt.Fprintf(&buf, "%v×%d", k, s.members[k])
if i != len(keys)-1 {
buf.WriteString(" ")
}
diff --git a/p2p/netutil/net_test.go b/p2p/netutil/net_test.go
index 34493a226d..16baa7b017 100644
--- a/p2p/netutil/net_test.go
+++ b/p2p/netutil/net_test.go
@@ -18,7 +18,9 @@ package netutil
import (
"fmt"
+ "math/rand"
"net"
+ "net/netip"
"reflect"
"testing"
"testing/quick"
@@ -29,7 +31,7 @@ import (
func TestParseNetlist(t *testing.T) {
var tests = []struct {
input string
- wantErr error
+ wantErr string
wantList *Netlist
}{
{
@@ -38,25 +40,27 @@ func TestParseNetlist(t *testing.T) {
},
{
input: "127.0.0.0/8",
- wantErr: nil,
- wantList: &Netlist{{IP: net.IP{127, 0, 0, 0}, Mask: net.CIDRMask(8, 32)}},
+ wantList: &Netlist{netip.MustParsePrefix("127.0.0.0/8")},
},
{
input: "127.0.0.0/44",
- wantErr: &net.ParseError{Type: "CIDR address", Text: "127.0.0.0/44"},
+ wantErr: `netip.ParsePrefix("127.0.0.0/44"): prefix length out of range`,
},
{
input: "127.0.0.0/16, 23.23.23.23/24,",
wantList: &Netlist{
- {IP: net.IP{127, 0, 0, 0}, Mask: net.CIDRMask(16, 32)},
- {IP: net.IP{23, 23, 23, 0}, Mask: net.CIDRMask(24, 32)},
+ netip.MustParsePrefix("127.0.0.0/16"),
+ netip.MustParsePrefix("23.23.23.23/24"),
},
},
}
for _, test := range tests {
l, err := ParseNetlist(test.input)
- if !reflect.DeepEqual(err, test.wantErr) {
+ if err == nil && test.wantErr != "" {
+ t.Errorf("%q: got no error, expected %q", test.input, test.wantErr)
+ continue
+ } else if err != nil && err.Error() != test.wantErr {
t.Errorf("%q: got error %q, want %q", test.input, err, test.wantErr)
continue
}
@@ -71,15 +75,12 @@ func TestParseNetlist(t *testing.T) {
func TestNilNetListContains(t *testing.T) {
var list *Netlist
-
- checkContains(t, list.Contains, nil, []string{"1.2.3.4"})
+ checkContains(t, list.Contains, list.ContainsAddr, nil, []string{"1.2.3.4"})
}
func TestIsLAN(t *testing.T) {
- checkContains(t, IsLAN,
+ checkContains(t, IsLAN, AddrIsLAN,
[]string{ // included
- "0.0.0.0",
- "0.2.0.8",
"127.0.0.1",
"10.0.1.1",
"10.22.0.3",
@@ -88,25 +89,35 @@ func TestIsLAN(t *testing.T) {
"fe80::f4a1:8eff:fec5:9d9d",
"febf::ab32:2233",
"fc00::4",
+ // 4-in-6
+ "::ffff:127.0.0.1",
+ "::ffff:10.10.0.2",
},
[]string{ // excluded
"192.0.2.1",
"1.0.0.0",
"172.32.0.1",
"fec0::2233",
+ // 4-in-6
+ "::ffff:88.99.100.2",
},
)
}
func TestIsSpecialNetwork(t *testing.T) {
- checkContains(t, IsSpecialNetwork,
+ checkContains(t, IsSpecialNetwork, AddrIsSpecialNetwork,
[]string{ // included
+ "0.0.0.0",
+ "0.2.0.8",
"192.0.2.1",
"192.0.2.44",
"2001:db8:85a3:8d3:1319:8a2e:370:7348",
"255.255.255.255",
"224.0.0.22", // IPv4 multicast
"ff05::1:3", // IPv6 multicast
+ // 4-in-6
+ "::ffff:255.255.255.255",
+ "::ffff:192.0.2.1",
},
[]string{ // excluded
"192.0.3.1",
@@ -117,16 +128,22 @@ func TestIsSpecialNetwork(t *testing.T) {
)
}
-func checkContains(t *testing.T, fn func(net.IP) bool, inc, exc []string) {
+func checkContains(t *testing.T, fn func(net.IP) bool, fn2 func(netip.Addr) bool, inc, exc []string) {
for _, s := range inc {
if !fn(parseIP(s)) {
- t.Error("returned false for included address", s)
+ t.Error("returned false for included net.IP", s)
+ }
+ if !fn2(netip.MustParseAddr(s)) {
+ t.Error("returned false for included netip.Addr", s)
}
}
for _, s := range exc {
if fn(parseIP(s)) {
- t.Error("returned true for excluded address", s)
+ t.Error("returned true for excluded net.IP", s)
+ }
+ if fn2(netip.MustParseAddr(s)) {
+ t.Error("returned true for excluded netip.Addr", s)
}
}
}
@@ -251,15 +268,23 @@ func TestDistinctNetSet(t *testing.T) {
}
func TestDistinctNetSetAddRemove(t *testing.T) {
- cfg := &quick.Config{}
- fn := func(ips []net.IP) bool {
+ cfg := &quick.Config{
+ Values: func(s []reflect.Value, rng *rand.Rand) {
+ slice := make([]netip.Addr, rng.Intn(20)+1)
+ for i := range slice {
+ slice[i] = RandomAddr(rng, false)
+ }
+ s[0] = reflect.ValueOf(slice)
+ },
+ }
+ fn := func(ips []netip.Addr) bool {
s := DistinctNetSet{Limit: 3, Subnet: 2}
for _, ip := range ips {
- s.Add(ip)
+ s.AddAddr(ip)
}
for _, ip := range ips {
- s.Remove(ip)
+ s.RemoveAddr(ip)
}
return s.Len() == 0
diff --git a/p2p/nodestate/nodestate.go b/p2p/nodestate/nodestate.go
deleted file mode 100644
index 3fc5f21c72..0000000000
--- a/p2p/nodestate/nodestate.go
+++ /dev/null
@@ -1,1151 +0,0 @@
-// Copyright 2020 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 nodestate
-
-import (
- "errors"
- "reflect"
- "sync"
- "time"
- "unsafe"
-
- "github.com/ethereum/go-ethereum/common/mclock"
- "github.com/ethereum/go-ethereum/ethdb"
- "github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/metrics"
- "github.com/ethereum/go-ethereum/p2p/enode"
- "github.com/ethereum/go-ethereum/p2p/enr"
- "github.com/ethereum/go-ethereum/rlp"
-)
-
-var (
- ErrInvalidField = errors.New("invalid field type")
- ErrClosed = errors.New("already closed")
-)
-
-type (
- // NodeStateMachine implements a network node-related event subscription system.
- // It can assign binary state flags and fields of arbitrary type to each node and allows
- // subscriptions to flag/field changes which can also modify further flags and fields,
- // potentially triggering further subscriptions. An operation includes an initial change
- // and all resulting subsequent changes and always ends in a consistent global state.
- // It is initiated by a "top level" SetState/SetField call that blocks (also blocking other
- // top-level functions) until the operation is finished. Callbacks making further changes
- // should use the non-blocking SetStateSub/SetFieldSub functions. The tree of events
- // resulting from the initial changes is traversed in a breadth-first order, ensuring for
- // each subscription callback that all other callbacks caused by the same change triggering
- // the current callback are processed before anything is triggered by the changes made in the
- // current callback. In practice this logic ensures that all subscriptions "see" events in
- // the logical order, callbacks are never called concurrently and "back and forth" effects
- // are also possible. The state machine design should ensure that infinite event cycles
- // cannot happen.
- // The caller can also add timeouts assigned to a certain node and a subset of state flags.
- // If the timeout elapses, the flags are reset. If all relevant flags are reset then the timer
- // is dropped. State flags with no timeout are persisted in the database if the flag
- // descriptor enables saving. If a node has no state flags set at any moment then it is discarded.
- // Note: in order to avoid mutex deadlocks the callbacks should never lock a mutex that
- // might be locked when the top level SetState/SetField functions are called. If a function
- // potentially performs state/field changes then it is recommended to mention this fact in the
- // function description, along with whether it should run inside an operation callback.
- NodeStateMachine struct {
- started, closed bool
- lock sync.Mutex
- clock mclock.Clock
- db ethdb.KeyValueStore
- dbNodeKey []byte
- nodes map[enode.ID]*nodeInfo
- offlineCallbackList []offlineCallback
- opFlag bool // an operation has started
- opWait *sync.Cond // signaled when the operation ends
- opPending []func() // pending callback list of the current operation
-
- // Registered state flags or fields. Modifications are allowed
- // only when the node state machine has not been started.
- setup *Setup
- fields []*fieldInfo
- saveFlags bitMask
-
- // Installed callbacks. Modifications are allowed only when the
- // node state machine has not been started.
- stateSubs []stateSub
-
- // Testing hooks, only for testing purposes.
- saveNodeHook func(*nodeInfo)
- }
-
- // Flags represents a set of flags from a certain setup
- Flags struct {
- mask bitMask
- setup *Setup
- }
-
- // Field represents a field from a certain setup
- Field struct {
- index int
- setup *Setup
- }
-
- // flagDefinition describes a node state flag. Each registered instance is automatically
- // mapped to a bit of the 64 bit node states.
- // If persistent is true then the node is saved when state machine is shutdown.
- flagDefinition struct {
- name string
- persistent bool
- }
-
- // fieldDefinition describes an optional node field of the given type. The contents
- // of the field are only retained for each node as long as at least one of the
- // state flags is set.
- fieldDefinition struct {
- name string
- ftype reflect.Type
- encode func(interface{}) ([]byte, error)
- decode func([]byte) (interface{}, error)
- }
-
- // Setup contains the list of flags and fields used by the application
- Setup struct {
- Version uint
- flags []flagDefinition
- fields []fieldDefinition
- }
-
- // bitMask describes a node state or state mask. It represents a subset
- // of node flags with each bit assigned to a flag index (LSB represents flag 0).
- bitMask uint64
-
- // StateCallback is a subscription callback which is called when one of the
- // state flags that is included in the subscription state mask is changed.
- // Note: oldState and newState are also masked with the subscription mask so only
- // the relevant bits are included.
- StateCallback func(n *enode.Node, oldState, newState Flags)
-
- // FieldCallback is a subscription callback which is called when the value of
- // a specific field is changed.
- FieldCallback func(n *enode.Node, state Flags, oldValue, newValue interface{})
-
- // nodeInfo contains node state, fields and state timeouts
- nodeInfo struct {
- node *enode.Node
- state bitMask
- timeouts []*nodeStateTimeout
- fields []interface{}
- fieldCount int
- db, dirty bool
- }
-
- nodeInfoEnc struct {
- Enr enr.Record
- Version uint
- State bitMask
- Fields [][]byte
- }
-
- stateSub struct {
- mask bitMask
- callback StateCallback
- }
-
- nodeStateTimeout struct {
- mask bitMask
- timer mclock.Timer
- }
-
- fieldInfo struct {
- fieldDefinition
- subs []FieldCallback
- }
-
- offlineCallback struct {
- node *nodeInfo
- state bitMask
- fields []interface{}
- }
-)
-
-// offlineState is a special state that is assumed to be set before a node is loaded from
-// the database and after it is shut down.
-const offlineState = bitMask(1)
-
-// NewFlag creates a new node state flag
-func (s *Setup) NewFlag(name string) Flags {
- if s.flags == nil {
- s.flags = []flagDefinition{{name: "offline"}}
- }
-
- f := Flags{mask: bitMask(1) << uint(len(s.flags)), setup: s}
- s.flags = append(s.flags, flagDefinition{name: name})
-
- return f
-}
-
-// NewPersistentFlag creates a new persistent node state flag
-func (s *Setup) NewPersistentFlag(name string) Flags {
- if s.flags == nil {
- s.flags = []flagDefinition{{name: "offline"}}
- }
-
- f := Flags{mask: bitMask(1) << uint(len(s.flags)), setup: s}
- s.flags = append(s.flags, flagDefinition{name: name, persistent: true})
-
- return f
-}
-
-// OfflineFlag returns the system-defined offline flag belonging to the given setup
-func (s *Setup) OfflineFlag() Flags {
- return Flags{mask: offlineState, setup: s}
-}
-
-// NewField creates a new node state field
-func (s *Setup) NewField(name string, ftype reflect.Type) Field {
- f := Field{index: len(s.fields), setup: s}
- s.fields = append(s.fields, fieldDefinition{
- name: name,
- ftype: ftype,
- })
-
- return f
-}
-
-// NewPersistentField creates a new persistent node field
-func (s *Setup) NewPersistentField(name string, ftype reflect.Type, encode func(interface{}) ([]byte, error), decode func([]byte) (interface{}, error)) Field {
- f := Field{index: len(s.fields), setup: s}
- s.fields = append(s.fields, fieldDefinition{
- name: name,
- ftype: ftype,
- encode: encode,
- decode: decode,
- })
-
- return f
-}
-
-// flagOp implements binary flag operations and also checks whether the operands belong to the same setup
-func flagOp(a, b Flags, trueIfA, trueIfB, trueIfBoth bool) Flags {
- if a.setup == nil {
- if a.mask != 0 {
- panic("Node state flags have no setup reference")
- }
-
- a.setup = b.setup
- }
-
- if b.setup == nil {
- if b.mask != 0 {
- panic("Node state flags have no setup reference")
- }
-
- b.setup = a.setup
- }
-
- if a.setup != b.setup {
- panic("Node state flags belong to a different setup")
- }
-
- res := Flags{setup: a.setup}
- if trueIfA {
- res.mask |= a.mask & ^b.mask
- }
-
- if trueIfB {
- res.mask |= b.mask & ^a.mask
- }
-
- if trueIfBoth {
- res.mask |= a.mask & b.mask
- }
-
- return res
-}
-
-// And returns the set of flags present in both a and b
-func (a Flags) And(b Flags) Flags { return flagOp(a, b, false, false, true) }
-
-// AndNot returns the set of flags present in a but not in b
-func (a Flags) AndNot(b Flags) Flags { return flagOp(a, b, true, false, false) }
-
-// Or returns the set of flags present in either a or b
-func (a Flags) Or(b Flags) Flags { return flagOp(a, b, true, true, true) }
-
-// Xor returns the set of flags present in either a or b but not both
-func (a Flags) Xor(b Flags) Flags { return flagOp(a, b, true, true, false) }
-
-// HasAll returns true if b is a subset of a
-func (a Flags) HasAll(b Flags) bool { return flagOp(a, b, false, true, false).mask == 0 }
-
-// HasNone returns true if a and b have no shared flags
-func (a Flags) HasNone(b Flags) bool { return flagOp(a, b, false, false, true).mask == 0 }
-
-// Equals returns true if a and b have the same flags set
-func (a Flags) Equals(b Flags) bool { return flagOp(a, b, true, true, false).mask == 0 }
-
-// IsEmpty returns true if a has no flags set
-func (a Flags) IsEmpty() bool { return a.mask == 0 }
-
-// MergeFlags merges multiple sets of state flags
-func MergeFlags(list ...Flags) Flags {
- if len(list) == 0 {
- return Flags{}
- }
-
- res := list[0]
- for i := 1; i < len(list); i++ {
- res = res.Or(list[i])
- }
-
- return res
-}
-
-// String returns a list of the names of the flags specified in the bit mask
-func (f Flags) String() string {
- if f.mask == 0 {
- return "[]"
- }
-
- s := "["
- comma := false
-
- for index, flag := range f.setup.flags {
- if f.mask&(bitMask(1)< 8*int(unsafe.Sizeof(bitMask(0))) {
- panic("Too many node state flags")
- }
-
- ns := &NodeStateMachine{
- db: db,
- dbNodeKey: dbKey,
- clock: clock,
- setup: setup,
- nodes: make(map[enode.ID]*nodeInfo),
- fields: make([]*fieldInfo, len(setup.fields)),
- }
- ns.opWait = sync.NewCond(&ns.lock)
- stateNameMap := make(map[string]int, len(setup.flags))
- for index, flag := range setup.flags {
- if _, ok := stateNameMap[flag.name]; ok {
- panic("Node state flag name collision: " + flag.name)
- }
-
- stateNameMap[flag.name] = index
-
- if flag.persistent {
- ns.saveFlags |= bitMask(1) << uint(index)
- }
- }
- fieldNameMap := make(map[string]int, len(setup.fields))
- for index, field := range setup.fields {
- if _, ok := fieldNameMap[field.name]; ok {
- panic("Node field name collision: " + field.name)
- }
-
- ns.fields[index] = &fieldInfo{fieldDefinition: field}
- fieldNameMap[field.name] = index
- }
-
- return ns
-}
-
-// stateMask checks whether the set of flags belongs to the same setup and returns its internal bit mask
-func (ns *NodeStateMachine) stateMask(flags Flags) bitMask {
- if flags.setup != ns.setup && flags.mask != 0 {
- panic("Node state flags belong to a different setup")
- }
-
- return flags.mask
-}
-
-// fieldIndex checks whether the field belongs to the same setup and returns its internal index
-func (ns *NodeStateMachine) fieldIndex(field Field) int {
- if field.setup != ns.setup {
- panic("Node field belongs to a different setup")
- }
-
- return field.index
-}
-
-// SubscribeState adds a node state subscription. The callback is called while the state
-// machine mutex is not held and it is allowed to make further state updates using the
-// non-blocking SetStateSub/SetFieldSub functions. All callbacks of an operation are running
-// from the thread/goroutine of the initial caller and parallel operations are not permitted.
-// Therefore the callback is never called concurrently. It is the responsibility of the
-// implemented state logic to avoid deadlocks and to reach a stable state in a finite amount
-// of steps.
-// State subscriptions should be installed before loading the node database or making the
-// first state update.
-func (ns *NodeStateMachine) SubscribeState(flags Flags, callback StateCallback) {
- ns.lock.Lock()
- defer ns.lock.Unlock()
-
- if ns.started {
- panic("state machine already started")
- }
-
- ns.stateSubs = append(ns.stateSubs, stateSub{ns.stateMask(flags), callback})
-}
-
-// SubscribeField adds a node field subscription. Same rules apply as for SubscribeState.
-func (ns *NodeStateMachine) SubscribeField(field Field, callback FieldCallback) {
- ns.lock.Lock()
- defer ns.lock.Unlock()
-
- if ns.started {
- panic("state machine already started")
- }
-
- f := ns.fields[ns.fieldIndex(field)]
- f.subs = append(f.subs, callback)
-}
-
-// newNode creates a new nodeInfo
-func (ns *NodeStateMachine) newNode(n *enode.Node) *nodeInfo {
- return &nodeInfo{node: n, fields: make([]interface{}, len(ns.fields))}
-}
-
-// checkStarted checks whether the state machine has already been started and panics otherwise.
-func (ns *NodeStateMachine) checkStarted() {
- if !ns.started {
- panic("state machine not started yet")
- }
-}
-
-// Start starts the state machine, enabling state and field operations and disabling
-// further subscriptions.
-func (ns *NodeStateMachine) Start() {
- ns.lock.Lock()
- if ns.started {
- panic("state machine already started")
- }
-
- ns.started = true
- if ns.db != nil {
- ns.loadFromDb()
- }
-
- ns.opStart()
- ns.offlineCallbacks(true)
- ns.opFinish()
- ns.lock.Unlock()
-}
-
-// Stop stops the state machine and saves its state if a database was supplied
-func (ns *NodeStateMachine) Stop() {
- ns.lock.Lock()
- defer ns.lock.Unlock()
-
- ns.checkStarted()
-
- if !ns.opStart() {
- panic("already closed")
- }
-
- for _, node := range ns.nodes {
- fields := make([]interface{}, len(node.fields))
- copy(fields, node.fields)
- ns.offlineCallbackList = append(ns.offlineCallbackList, offlineCallback{node, node.state, fields})
- }
-
- if ns.db != nil {
- ns.saveToDb()
- }
-
- ns.offlineCallbacks(false)
- ns.closed = true
- ns.opFinish()
-}
-
-// loadFromDb loads persisted node states from the database
-func (ns *NodeStateMachine) loadFromDb() {
- it := ns.db.NewIterator(ns.dbNodeKey, nil)
- for it.Next() {
- var id enode.ID
- if len(it.Key()) != len(ns.dbNodeKey)+len(id) {
- log.Error("Node state db entry with invalid length", "found", len(it.Key()), "expected", len(ns.dbNodeKey)+len(id))
- continue
- }
-
- copy(id[:], it.Key()[len(ns.dbNodeKey):])
- ns.decodeNode(id, it.Value())
- }
-}
-
-type dummyIdentity enode.ID
-
-func (id dummyIdentity) Verify(r *enr.Record, sig []byte) error { return nil }
-func (id dummyIdentity) NodeAddr(r *enr.Record) []byte { return id[:] }
-
-// decodeNode decodes a node database entry and adds it to the node set if successful
-func (ns *NodeStateMachine) decodeNode(id enode.ID, data []byte) {
- var enc nodeInfoEnc
- if err := rlp.DecodeBytes(data, &enc); err != nil {
- log.Error("Failed to decode node info", "id", id, "error", err)
- return
- }
-
- n, _ := enode.New(dummyIdentity(id), &enc.Enr)
- node := ns.newNode(n)
- node.db = true
-
- if enc.Version != ns.setup.Version {
- log.Debug("Removing stored node with unknown version", "current", ns.setup.Version, "stored", enc.Version)
- ns.deleteNode(id)
-
- return
- }
-
- if len(enc.Fields) > len(ns.setup.fields) {
- log.Error("Invalid node field count", "id", id, "stored", len(enc.Fields))
- return
- }
- // Resolve persisted node fields
- for i, encField := range enc.Fields {
- if len(encField) == 0 {
- continue
- }
-
- if decode := ns.fields[i].decode; decode != nil {
- if field, err := decode(encField); err == nil {
- node.fields[i] = field
- node.fieldCount++
- } else {
- log.Error("Failed to decode node field", "id", id, "field name", ns.fields[i].name, "error", err)
- return
- }
- } else {
- log.Error("Cannot decode node field", "id", id, "field name", ns.fields[i].name)
- return
- }
- }
- // It's a compatible node record, add it to set.
- ns.nodes[id] = node
- node.state = enc.State
- fields := make([]interface{}, len(node.fields))
- copy(fields, node.fields)
- ns.offlineCallbackList = append(ns.offlineCallbackList, offlineCallback{node, node.state, fields})
- log.Debug("Loaded node state", "id", id, "state", Flags{mask: enc.State, setup: ns.setup})
-}
-
-// saveNode saves the given node info to the database
-func (ns *NodeStateMachine) saveNode(id enode.ID, node *nodeInfo) error {
- if ns.db == nil {
- return nil
- }
-
- storedState := node.state & ns.saveFlags
- for _, t := range node.timeouts {
- storedState &= ^t.mask
- }
-
- enc := nodeInfoEnc{
- Enr: *node.node.Record(),
- Version: ns.setup.Version,
- State: storedState,
- Fields: make([][]byte, len(ns.fields)),
- }
- log.Debug("Saved node state", "id", id, "state", Flags{mask: enc.State, setup: ns.setup})
-
- lastIndex := -1
-
- for i, f := range node.fields {
- if f == nil {
- continue
- }
-
- encode := ns.fields[i].encode
- if encode == nil {
- continue
- }
-
- blob, err := encode(f)
- if err != nil {
- return err
- }
-
- enc.Fields[i] = blob
- lastIndex = i
- }
-
- if storedState == 0 && lastIndex == -1 {
- if node.db {
- node.db = false
-
- ns.deleteNode(id)
- }
-
- node.dirty = false
-
- return nil
- }
-
- enc.Fields = enc.Fields[:lastIndex+1]
-
- data, err := rlp.EncodeToBytes(&enc)
- if err != nil {
- return err
- }
-
- if err := ns.db.Put(append(ns.dbNodeKey, id[:]...), data); err != nil {
- return err
- }
-
- node.dirty, node.db = false, true
-
- if ns.saveNodeHook != nil {
- ns.saveNodeHook(node)
- }
-
- return nil
-}
-
-// deleteNode removes a node info from the database
-func (ns *NodeStateMachine) deleteNode(id enode.ID) {
- ns.db.Delete(append(ns.dbNodeKey, id[:]...))
-}
-
-// saveToDb saves the persistent flags and fields of all nodes that have been changed
-func (ns *NodeStateMachine) saveToDb() {
- for id, node := range ns.nodes {
- if node.dirty {
- err := ns.saveNode(id, node)
- if err != nil {
- log.Error("Failed to save node", "id", id, "error", err)
- }
- }
- }
-}
-
-// updateEnode updates the enode entry belonging to the given node if it already exists
-func (ns *NodeStateMachine) updateEnode(n *enode.Node) (enode.ID, *nodeInfo) {
- id := n.ID()
-
- node := ns.nodes[id]
- if node != nil && n.Seq() > node.node.Seq() {
- node.node = n
- node.dirty = true
- }
-
- return id, node
-}
-
-// Persist saves the persistent state and fields of the given node immediately
-func (ns *NodeStateMachine) Persist(n *enode.Node) error {
- ns.lock.Lock()
- defer ns.lock.Unlock()
-
- ns.checkStarted()
-
- if id, node := ns.updateEnode(n); node != nil && node.dirty {
- err := ns.saveNode(id, node)
- if err != nil {
- log.Error("Failed to save node", "id", id, "error", err)
- }
-
- return err
- }
-
- return nil
-}
-
-// SetState updates the given node state flags and blocks until the operation is finished.
-// If a flag with a timeout is set again, the operation removes or replaces the existing timeout.
-func (ns *NodeStateMachine) SetState(n *enode.Node, setFlags, resetFlags Flags, timeout time.Duration) error {
- ns.lock.Lock()
- defer ns.lock.Unlock()
-
- if !ns.opStart() {
- return ErrClosed
- }
-
- ns.setState(n, setFlags, resetFlags, timeout)
- ns.opFinish()
-
- return nil
-}
-
-// SetStateSub updates the given node state flags without blocking (should be called
-// from a subscription/operation callback).
-func (ns *NodeStateMachine) SetStateSub(n *enode.Node, setFlags, resetFlags Flags, timeout time.Duration) {
- ns.lock.Lock()
- defer ns.lock.Unlock()
-
- ns.opCheck()
- ns.setState(n, setFlags, resetFlags, timeout)
-}
-
-func (ns *NodeStateMachine) setState(n *enode.Node, setFlags, resetFlags Flags, timeout time.Duration) {
- ns.checkStarted()
- set, reset := ns.stateMask(setFlags), ns.stateMask(resetFlags)
- id, node := ns.updateEnode(n)
-
- if node == nil {
- if set == 0 {
- return
- }
-
- node = ns.newNode(n)
- ns.nodes[id] = node
- }
-
- oldState := node.state
- newState := (node.state & (^reset)) | set
- changed := oldState ^ newState
- node.state = newState
-
- // Remove the timeout callbacks for all reset and set flags,
- // even they are not existent(it's noop).
- ns.removeTimeouts(node, set|reset)
-
- // Register the timeout callback if required
- if timeout != 0 && set != 0 {
- ns.addTimeout(n, set, timeout)
- }
-
- if newState == oldState {
- return
- }
-
- if newState == 0 && node.fieldCount == 0 {
- delete(ns.nodes, id)
-
- if node.db {
- ns.deleteNode(id)
- }
- } else {
- if changed&ns.saveFlags != 0 {
- node.dirty = true
- }
- }
-
- callback := func() {
- for _, sub := range ns.stateSubs {
- if changed&sub.mask != 0 {
- sub.callback(n, Flags{mask: oldState & sub.mask, setup: ns.setup}, Flags{mask: newState & sub.mask, setup: ns.setup})
- }
- }
- }
- ns.opPending = append(ns.opPending, callback)
-}
-
-// opCheck checks whether an operation is active
-func (ns *NodeStateMachine) opCheck() {
- if !ns.opFlag {
- panic("Operation has not started")
- }
-}
-
-// opStart waits until other operations are finished and starts a new one
-func (ns *NodeStateMachine) opStart() bool {
- for ns.opFlag {
- ns.opWait.Wait()
- }
-
- if ns.closed {
- return false
- }
-
- ns.opFlag = true
-
- return true
-}
-
-// opFinish finishes the current operation by running all pending callbacks.
-// Callbacks resulting from a state/field change performed in a previous callback are always
-// put at the end of the pending list and therefore processed after all callbacks resulting
-// from the previous state/field change.
-func (ns *NodeStateMachine) opFinish() {
- for len(ns.opPending) != 0 {
- list := ns.opPending
- ns.lock.Unlock()
-
- for _, cb := range list {
- cb()
- }
-
- ns.lock.Lock()
- ns.opPending = ns.opPending[len(list):]
- }
-
- ns.opPending = nil
- ns.opFlag = false
- ns.opWait.Broadcast()
-}
-
-// Operation calls the given function as an operation callback. This allows the caller
-// to start an operation with multiple initial changes. The same rules apply as for
-// subscription callbacks.
-func (ns *NodeStateMachine) Operation(fn func()) error {
- ns.lock.Lock()
- started := ns.opStart()
- ns.lock.Unlock()
-
- if !started {
- return ErrClosed
- }
-
- fn()
- ns.lock.Lock()
- ns.opFinish()
- ns.lock.Unlock()
-
- return nil
-}
-
-// offlineCallbacks calls state update callbacks at startup or shutdown
-func (ns *NodeStateMachine) offlineCallbacks(start bool) {
- for _, cb := range ns.offlineCallbackList {
- cb := cb
- callback := func() {
- for _, sub := range ns.stateSubs {
- offState := offlineState & sub.mask
- onState := cb.state & sub.mask
-
- if offState == onState {
- continue
- }
-
- if start {
- sub.callback(cb.node.node, Flags{mask: offState, setup: ns.setup}, Flags{mask: onState, setup: ns.setup})
- } else {
- sub.callback(cb.node.node, Flags{mask: onState, setup: ns.setup}, Flags{mask: offState, setup: ns.setup})
- }
- }
-
- for i, f := range cb.fields {
- if f == nil || ns.fields[i].subs == nil {
- continue
- }
-
- for _, fsub := range ns.fields[i].subs {
- if start {
- fsub(cb.node.node, Flags{mask: offlineState, setup: ns.setup}, nil, f)
- } else {
- fsub(cb.node.node, Flags{mask: offlineState, setup: ns.setup}, f, nil)
- }
- }
- }
- }
- ns.opPending = append(ns.opPending, callback)
- }
-
- ns.offlineCallbackList = nil
-}
-
-// AddTimeout adds a node state timeout associated to the given state flag(s).
-// After the specified time interval, the relevant states will be reset.
-func (ns *NodeStateMachine) AddTimeout(n *enode.Node, flags Flags, timeout time.Duration) error {
- ns.lock.Lock()
- defer ns.lock.Unlock()
-
- ns.checkStarted()
-
- if ns.closed {
- return ErrClosed
- }
-
- ns.addTimeout(n, ns.stateMask(flags), timeout)
-
- return nil
-}
-
-// addTimeout adds a node state timeout associated to the given state flag(s).
-func (ns *NodeStateMachine) addTimeout(n *enode.Node, mask bitMask, timeout time.Duration) {
- _, node := ns.updateEnode(n)
- if node == nil {
- return
- }
-
- mask &= node.state
- if mask == 0 {
- return
- }
-
- ns.removeTimeouts(node, mask)
- t := &nodeStateTimeout{mask: mask}
- t.timer = ns.clock.AfterFunc(timeout, func() {
- ns.lock.Lock()
- defer ns.lock.Unlock()
-
- if !ns.opStart() {
- return
- }
-
- ns.setState(n, Flags{}, Flags{mask: t.mask, setup: ns.setup}, 0)
- ns.opFinish()
- })
-
- node.timeouts = append(node.timeouts, t)
- if mask&ns.saveFlags != 0 {
- node.dirty = true
- }
-}
-
-// removeTimeout removes node state timeouts associated to the given state flag(s).
-// If a timeout was associated to multiple flags which are not all included in the
-// specified remove mask then only the included flags are de-associated and the timer
-// stays active.
-func (ns *NodeStateMachine) removeTimeouts(node *nodeInfo, mask bitMask) {
- for i := 0; i < len(node.timeouts); i++ {
- t := node.timeouts[i]
-
- match := t.mask & mask
- if match == 0 {
- continue
- }
-
- t.mask -= match
- if t.mask != 0 {
- continue
- }
-
- t.timer.Stop()
-
- node.timeouts[i] = node.timeouts[len(node.timeouts)-1]
- node.timeouts = node.timeouts[:len(node.timeouts)-1]
- i--
-
- if match&ns.saveFlags != 0 {
- node.dirty = true
- }
- }
-}
-
-// GetField retrieves the given field of the given node. Note that when used in a
-// subscription callback the result can be out of sync with the state change represented
-// by the callback parameters so extra safety checks might be necessary.
-func (ns *NodeStateMachine) GetField(n *enode.Node, field Field) interface{} {
- ns.lock.Lock()
- defer ns.lock.Unlock()
-
- ns.checkStarted()
-
- if ns.closed {
- return nil
- }
-
- if _, node := ns.updateEnode(n); node != nil {
- return node.fields[ns.fieldIndex(field)]
- }
-
- return nil
-}
-
-// GetState retrieves the current state of the given node. Note that when used in a
-// subscription callback the result can be out of sync with the state change represented
-// by the callback parameters so extra safety checks might be necessary.
-func (ns *NodeStateMachine) GetState(n *enode.Node) Flags {
- ns.lock.Lock()
- defer ns.lock.Unlock()
-
- ns.checkStarted()
-
- if ns.closed {
- return Flags{}
- }
-
- if _, node := ns.updateEnode(n); node != nil {
- return Flags{mask: node.state, setup: ns.setup}
- }
-
- return Flags{}
-}
-
-// SetField sets the given field of the given node and blocks until the operation is finished
-func (ns *NodeStateMachine) SetField(n *enode.Node, field Field, value interface{}) error {
- ns.lock.Lock()
- defer ns.lock.Unlock()
-
- if !ns.opStart() {
- return ErrClosed
- }
-
- err := ns.setField(n, field, value)
- ns.opFinish()
-
- return err
-}
-
-// SetFieldSub sets the given field of the given node without blocking (should be called
-// from a subscription/operation callback).
-func (ns *NodeStateMachine) SetFieldSub(n *enode.Node, field Field, value interface{}) error {
- ns.lock.Lock()
- defer ns.lock.Unlock()
-
- ns.opCheck()
-
- return ns.setField(n, field, value)
-}
-
-func (ns *NodeStateMachine) setField(n *enode.Node, field Field, value interface{}) error {
- ns.checkStarted()
-
- id, node := ns.updateEnode(n)
- if node == nil {
- if value == nil {
- return nil
- }
-
- node = ns.newNode(n)
- ns.nodes[id] = node
- }
-
- fieldIndex := ns.fieldIndex(field)
-
- f := ns.fields[fieldIndex]
- if value != nil && reflect.TypeOf(value) != f.ftype {
- log.Error("Invalid field type", "type", reflect.TypeOf(value), "required", f.ftype)
- return ErrInvalidField
- }
-
- oldValue := node.fields[fieldIndex]
- if value == oldValue {
- return nil
- }
-
- if oldValue != nil {
- node.fieldCount--
- }
-
- if value != nil {
- node.fieldCount++
- }
-
- node.fields[fieldIndex] = value
- if node.state == 0 && node.fieldCount == 0 {
- delete(ns.nodes, id)
-
- if node.db {
- ns.deleteNode(id)
- }
- } else {
- if f.encode != nil {
- node.dirty = true
- }
- }
-
- state := node.state
- callback := func() {
- for _, cb := range f.subs {
- cb(n, Flags{mask: state, setup: ns.setup}, oldValue, value)
- }
- }
- ns.opPending = append(ns.opPending, callback)
-
- return nil
-}
-
-// ForEach calls the callback for each node having all of the required and none of the
-// disabled flags set.
-// Note that this callback is not an operation callback but ForEach can be called from an
-// Operation callback or Operation can also be called from a ForEach callback if necessary.
-func (ns *NodeStateMachine) ForEach(requireFlags, disableFlags Flags, cb func(n *enode.Node, state Flags)) {
- ns.lock.Lock()
- ns.checkStarted()
-
- type callback struct {
- node *enode.Node
- state bitMask
- }
-
- require, disable := ns.stateMask(requireFlags), ns.stateMask(disableFlags)
-
- var callbacks []callback
-
- for _, node := range ns.nodes {
- if node.state&require == require && node.state&disable == 0 {
- callbacks = append(callbacks, callback{node.node, node.state & (require | disable)})
- }
- }
- ns.lock.Unlock()
-
- for _, c := range callbacks {
- cb(c.node, Flags{mask: c.state, setup: ns.setup})
- }
-}
-
-// GetNode returns the enode currently associated with the given ID
-func (ns *NodeStateMachine) GetNode(id enode.ID) *enode.Node {
- ns.lock.Lock()
- defer ns.lock.Unlock()
-
- ns.checkStarted()
-
- if node := ns.nodes[id]; node != nil {
- return node.node
- }
-
- return nil
-}
-
-// AddLogMetrics adds logging and/or metrics for nodes entering, exiting and currently
-// being in a given set specified by required and disabled state flags
-func (ns *NodeStateMachine) AddLogMetrics(requireFlags, disableFlags Flags, name string, inMeter, outMeter metrics.Meter, gauge metrics.Gauge) {
- var count int64
-
- ns.SubscribeState(requireFlags.Or(disableFlags), func(n *enode.Node, oldState, newState Flags) {
- oldMatch := oldState.HasAll(requireFlags) && oldState.HasNone(disableFlags)
- newMatch := newState.HasAll(requireFlags) && newState.HasNone(disableFlags)
-
- if newMatch == oldMatch {
- return
- }
-
- if newMatch {
- count++
- if name != "" {
- log.Debug("Node entered", "set", name, "id", n.ID(), "count", count)
- }
-
- if inMeter != nil {
- inMeter.Mark(1)
- }
- } else {
- count--
- if name != "" {
- log.Debug("Node left", "set", name, "id", n.ID(), "count", count)
- }
-
- if outMeter != nil {
- outMeter.Mark(1)
- }
- }
-
- if gauge != nil {
- gauge.Update(count)
- }
- })
-}
diff --git a/p2p/nodestate/nodestate_test.go b/p2p/nodestate/nodestate_test.go
deleted file mode 100644
index 5286cfd8a2..0000000000
--- a/p2p/nodestate/nodestate_test.go
+++ /dev/null
@@ -1,440 +0,0 @@
-// Copyright 2020 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 nodestate
-
-import (
- "errors"
- "fmt"
- "reflect"
- "testing"
- "time"
-
- "github.com/ethereum/go-ethereum/common/mclock"
- "github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/p2p/enode"
- "github.com/ethereum/go-ethereum/p2p/enr"
- "github.com/ethereum/go-ethereum/rlp"
-)
-
-func testSetup(flagPersist []bool, fieldType []reflect.Type) (*Setup, []Flags, []Field) {
- setup := &Setup{}
- flags := make([]Flags, len(flagPersist))
-
- for i, persist := range flagPersist {
- if persist {
- flags[i] = setup.NewPersistentFlag(fmt.Sprintf("flag-%d", i))
- } else {
- flags[i] = setup.NewFlag(fmt.Sprintf("flag-%d", i))
- }
- }
-
- fields := make([]Field, len(fieldType))
-
- for i, ftype := range fieldType {
- switch ftype {
- case reflect.TypeOf(uint64(0)):
- fields[i] = setup.NewPersistentField(fmt.Sprintf("field-%d", i), ftype, uint64FieldEnc, uint64FieldDec)
- case reflect.TypeOf(""):
- fields[i] = setup.NewPersistentField(fmt.Sprintf("field-%d", i), ftype, stringFieldEnc, stringFieldDec)
- default:
- fields[i] = setup.NewField(fmt.Sprintf("field-%d", i), ftype)
- }
- }
-
- return setup, flags, fields
-}
-
-func testNode(b byte) *enode.Node {
- r := &enr.Record{}
- r.SetSig(dummyIdentity{b}, []byte{42})
- n, _ := enode.New(dummyIdentity{b}, r)
-
- return n
-}
-
-func TestCallback(t *testing.T) {
- mdb, clock := rawdb.NewMemoryDatabase(), &mclock.Simulated{}
-
- s, flags, _ := testSetup([]bool{false, false, false}, nil)
- ns := NewNodeStateMachine(mdb, []byte("-ns"), clock, s)
-
- set0 := make(chan struct{}, 1)
- set1 := make(chan struct{}, 1)
- set2 := make(chan struct{}, 1)
-
- ns.SubscribeState(flags[0], func(n *enode.Node, oldState, newState Flags) { set0 <- struct{}{} })
- ns.SubscribeState(flags[1], func(n *enode.Node, oldState, newState Flags) { set1 <- struct{}{} })
- ns.SubscribeState(flags[2], func(n *enode.Node, oldState, newState Flags) { set2 <- struct{}{} })
-
- ns.Start()
-
- ns.SetState(testNode(1), flags[0], Flags{}, 0)
- ns.SetState(testNode(1), flags[1], Flags{}, time.Second)
- ns.SetState(testNode(1), flags[2], Flags{}, 2*time.Second)
-
- for i := 0; i < 3; i++ {
- select {
- case <-set0:
- case <-set1:
- case <-set2:
- case <-time.After(time.Second):
- t.Fatalf("failed to invoke callback")
- }
- }
-}
-
-func TestPersistentFlags(t *testing.T) {
- mdb, clock := rawdb.NewMemoryDatabase(), &mclock.Simulated{}
-
- s, flags, _ := testSetup([]bool{true, true, true, false}, nil)
- ns := NewNodeStateMachine(mdb, []byte("-ns"), clock, s)
-
- saveNode := make(chan *nodeInfo, 5)
- ns.saveNodeHook = func(node *nodeInfo) {
- saveNode <- node
- }
-
- ns.Start()
-
- ns.SetState(testNode(1), flags[0], Flags{}, time.Second) // state with timeout should not be saved
- ns.SetState(testNode(2), flags[1], Flags{}, 0)
- ns.SetState(testNode(3), flags[2], Flags{}, 0)
- ns.SetState(testNode(4), flags[3], Flags{}, 0)
- ns.SetState(testNode(5), flags[0], Flags{}, 0)
- ns.Persist(testNode(5))
- select {
- case <-saveNode:
- case <-time.After(time.Second):
- t.Fatalf("Timeout")
- }
- ns.Stop()
-
- for i := 0; i < 2; i++ {
- select {
- case <-saveNode:
- case <-time.After(time.Second):
- t.Fatalf("Timeout")
- }
- }
- select {
- case <-saveNode:
- t.Fatalf("Unexpected saveNode")
- case <-time.After(time.Millisecond * 100):
- }
-}
-
-func TestSetField(t *testing.T) {
- mdb, clock := rawdb.NewMemoryDatabase(), &mclock.Simulated{}
-
- s, flags, fields := testSetup([]bool{true}, []reflect.Type{reflect.TypeOf("")})
- ns := NewNodeStateMachine(mdb, []byte("-ns"), clock, s)
-
- saveNode := make(chan *nodeInfo, 1)
- ns.saveNodeHook = func(node *nodeInfo) {
- saveNode <- node
- }
-
- ns.Start()
-
- // Set field before setting state
- ns.SetField(testNode(1), fields[0], "hello world")
-
- field := ns.GetField(testNode(1), fields[0])
- if field == nil {
- t.Fatalf("Field should be set before setting states")
- }
-
- ns.SetField(testNode(1), fields[0], nil)
-
- field = ns.GetField(testNode(1), fields[0])
- if field != nil {
- t.Fatalf("Field should be unset")
- }
- // Set field after setting state
- ns.SetState(testNode(1), flags[0], Flags{}, 0)
- ns.SetField(testNode(1), fields[0], "hello world")
-
- field = ns.GetField(testNode(1), fields[0])
- if field == nil {
- t.Fatalf("Field should be set after setting states")
- }
-
- if err := ns.SetField(testNode(1), fields[0], 123); err == nil {
- t.Fatalf("Invalid field should be rejected")
- }
- // Dirty node should be written back
- ns.Stop()
- select {
- case <-saveNode:
- case <-time.After(time.Second):
- t.Fatalf("Timeout")
- }
-}
-
-func TestSetState(t *testing.T) {
- mdb, clock := rawdb.NewMemoryDatabase(), &mclock.Simulated{}
-
- s, flags, _ := testSetup([]bool{false, false, false}, nil)
- ns := NewNodeStateMachine(mdb, []byte("-ns"), clock, s)
-
- type change struct{ old, new Flags }
-
- set := make(chan change, 1)
-
- ns.SubscribeState(flags[0].Or(flags[1]), func(n *enode.Node, oldState, newState Flags) {
- set <- change{
- old: oldState,
- new: newState,
- }
- })
-
- ns.Start()
-
- check := func(expectOld, expectNew Flags, expectChange bool) {
- if expectChange {
- select {
- case c := <-set:
- if !c.old.Equals(expectOld) {
- t.Fatalf("Old state mismatch")
- }
-
- if !c.new.Equals(expectNew) {
- t.Fatalf("New state mismatch")
- }
- case <-time.After(time.Second):
- }
-
- return
- }
- select {
- case <-set:
- t.Fatalf("Unexpected change")
- case <-time.After(time.Millisecond * 100):
- return
- }
- }
-
- ns.SetState(testNode(1), flags[0], Flags{}, 0)
- check(Flags{}, flags[0], true)
-
- ns.SetState(testNode(1), flags[1], Flags{}, 0)
- check(flags[0], flags[0].Or(flags[1]), true)
-
- ns.SetState(testNode(1), flags[2], Flags{}, 0)
- check(Flags{}, Flags{}, false)
-
- ns.SetState(testNode(1), Flags{}, flags[0], 0)
- check(flags[0].Or(flags[1]), flags[1], true)
-
- ns.SetState(testNode(1), Flags{}, flags[1], 0)
- check(flags[1], Flags{}, true)
-
- ns.SetState(testNode(1), Flags{}, flags[2], 0)
- check(Flags{}, Flags{}, false)
-
- ns.SetState(testNode(1), flags[0].Or(flags[1]), Flags{}, time.Second)
- check(Flags{}, flags[0].Or(flags[1]), true)
- clock.Run(time.Second)
- check(flags[0].Or(flags[1]), Flags{}, true)
-}
-
-func uint64FieldEnc(field interface{}) ([]byte, error) {
- if u, ok := field.(uint64); ok {
- enc, err := rlp.EncodeToBytes(&u)
- return enc, err
- }
-
- return nil, errors.New("invalid field type")
-}
-
-func uint64FieldDec(enc []byte) (interface{}, error) {
- var u uint64
- err := rlp.DecodeBytes(enc, &u)
-
- return u, err
-}
-
-func stringFieldEnc(field interface{}) ([]byte, error) {
- if s, ok := field.(string); ok {
- return []byte(s), nil
- }
-
- return nil, errors.New("invalid field type")
-}
-
-func stringFieldDec(enc []byte) (interface{}, error) {
- return string(enc), nil
-}
-
-func TestPersistentFields(t *testing.T) {
- mdb, clock := rawdb.NewMemoryDatabase(), &mclock.Simulated{}
-
- s, flags, fields := testSetup([]bool{true}, []reflect.Type{reflect.TypeOf(uint64(0)), reflect.TypeOf("")})
- ns := NewNodeStateMachine(mdb, []byte("-ns"), clock, s)
-
- ns.Start()
- ns.SetState(testNode(1), flags[0], Flags{}, 0)
- ns.SetField(testNode(1), fields[0], uint64(100))
- ns.SetField(testNode(1), fields[1], "hello world")
- ns.Stop()
-
- ns2 := NewNodeStateMachine(mdb, []byte("-ns"), clock, s)
-
- ns2.Start()
-
- field0 := ns2.GetField(testNode(1), fields[0])
- if !reflect.DeepEqual(field0, uint64(100)) {
- t.Fatalf("Field changed")
- }
-
- field1 := ns2.GetField(testNode(1), fields[1])
- if !reflect.DeepEqual(field1, "hello world") {
- t.Fatalf("Field changed")
- }
-
- s.Version++
- ns3 := NewNodeStateMachine(mdb, []byte("-ns"), clock, s)
- ns3.Start()
-
- if ns3.GetField(testNode(1), fields[0]) != nil {
- t.Fatalf("Old field version should have been discarded")
- }
-}
-
-func TestFieldSub(t *testing.T) {
- mdb, clock := rawdb.NewMemoryDatabase(), &mclock.Simulated{}
-
- s, flags, fields := testSetup([]bool{true}, []reflect.Type{reflect.TypeOf(uint64(0))})
- ns := NewNodeStateMachine(mdb, []byte("-ns"), clock, s)
-
- var (
- lastState Flags
- lastOldValue, lastNewValue interface{}
- )
-
- ns.SubscribeField(fields[0], func(n *enode.Node, state Flags, oldValue, newValue interface{}) {
- lastState, lastOldValue, lastNewValue = state, oldValue, newValue
- })
-
- check := func(state Flags, oldValue, newValue interface{}) {
- if !lastState.Equals(state) || lastOldValue != oldValue || lastNewValue != newValue {
- t.Fatalf("Incorrect field sub callback (expected [%v %v %v], got [%v %v %v])", state, oldValue, newValue, lastState, lastOldValue, lastNewValue)
- }
- }
-
- ns.Start()
- ns.SetState(testNode(1), flags[0], Flags{}, 0)
- ns.SetField(testNode(1), fields[0], uint64(100))
- check(flags[0], nil, uint64(100))
- ns.Stop()
- check(s.OfflineFlag(), uint64(100), nil)
-
- ns2 := NewNodeStateMachine(mdb, []byte("-ns"), clock, s)
- ns2.SubscribeField(fields[0], func(n *enode.Node, state Flags, oldValue, newValue interface{}) {
- lastState, lastOldValue, lastNewValue = state, oldValue, newValue
- })
- ns2.Start()
- check(s.OfflineFlag(), nil, uint64(100))
- ns2.SetState(testNode(1), Flags{}, flags[0], 0)
- ns2.SetField(testNode(1), fields[0], nil)
- check(Flags{}, uint64(100), nil)
- ns2.Stop()
-}
-
-func TestDuplicatedFlags(t *testing.T) {
- mdb, clock := rawdb.NewMemoryDatabase(), &mclock.Simulated{}
-
- s, flags, _ := testSetup([]bool{true}, nil)
- ns := NewNodeStateMachine(mdb, []byte("-ns"), clock, s)
-
- type change struct{ old, new Flags }
-
- set := make(chan change, 1)
-
- ns.SubscribeState(flags[0], func(n *enode.Node, oldState, newState Flags) {
- set <- change{oldState, newState}
- })
-
- ns.Start()
- defer ns.Stop()
-
- check := func(expectOld, expectNew Flags, expectChange bool) {
- if expectChange {
- select {
- case c := <-set:
- if !c.old.Equals(expectOld) {
- t.Fatalf("Old state mismatch")
- }
-
- if !c.new.Equals(expectNew) {
- t.Fatalf("New state mismatch")
- }
- case <-time.After(time.Second):
- }
-
- return
- }
- select {
- case <-set:
- t.Fatalf("Unexpected change")
- case <-time.After(time.Millisecond * 100):
- return
- }
- }
-
- ns.SetState(testNode(1), flags[0], Flags{}, time.Second)
- check(Flags{}, flags[0], true)
- ns.SetState(testNode(1), flags[0], Flags{}, 2*time.Second) // extend the timeout to 2s
- check(Flags{}, flags[0], false)
-
- clock.Run(2 * time.Second)
- check(flags[0], Flags{}, true)
-}
-
-func TestCallbackOrder(t *testing.T) {
- mdb, clock := rawdb.NewMemoryDatabase(), &mclock.Simulated{}
-
- s, flags, _ := testSetup([]bool{false, false, false, false}, nil)
- ns := NewNodeStateMachine(mdb, []byte("-ns"), clock, s)
-
- ns.SubscribeState(flags[0], func(n *enode.Node, oldState, newState Flags) {
- if newState.Equals(flags[0]) {
- ns.SetStateSub(n, flags[1], Flags{}, 0)
- ns.SetStateSub(n, flags[2], Flags{}, 0)
- }
- })
- ns.SubscribeState(flags[1], func(n *enode.Node, oldState, newState Flags) {
- if newState.Equals(flags[1]) {
- ns.SetStateSub(n, flags[3], Flags{}, 0)
- }
- })
-
- lastState := Flags{}
-
- ns.SubscribeState(MergeFlags(flags[1], flags[2], flags[3]), func(n *enode.Node, oldState, newState Flags) {
- if !oldState.Equals(lastState) {
- t.Fatalf("Wrong callback order")
- }
-
- lastState = newState
- })
-
- ns.Start()
- defer ns.Stop()
-
- ns.SetState(testNode(1), flags[0], Flags{}, 0)
-}
diff --git a/p2p/peer.go b/p2p/peer.go
index 65a7903f58..e4482deae9 100644
--- a/p2p/peer.go
+++ b/p2p/peer.go
@@ -21,6 +21,7 @@ import (
"fmt"
"io"
"net"
+ "slices"
"sync"
"time"
@@ -31,7 +32,6 @@ import (
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/ethereum/go-ethereum/rlp"
- "golang.org/x/exp/slices"
)
var (
diff --git a/p2p/rlpx/rlpx.go b/p2p/rlpx/rlpx.go
index 4bcad7c2ad..04a013e6e2 100644
--- a/p2p/rlpx/rlpx.go
+++ b/p2p/rlpx/rlpx.go
@@ -652,6 +652,11 @@ func (h *handshakeState) readMsg(msg interface{}, prv *ecdsa.PrivateKey, r io.Re
size := binary.BigEndian.Uint16(prefix)
+ // baseProtocolMaxMsgSize = 2 * 1024
+ if size > 2048 {
+ return nil, errors.New("message too big")
+ }
+
// Read the handshake packet.
packet, err := h.rbuf.read(r, int(size))
if err != nil {
diff --git a/p2p/server.go b/p2p/server.go
index d657b059c8..7b442358c7 100644
--- a/p2p/server.go
+++ b/p2p/server.go
@@ -19,6 +19,7 @@ package p2p
import (
"bytes"
+ "cmp"
"crypto/ecdsa"
"encoding/hex"
"errors"
@@ -462,7 +463,7 @@ func (srv *Server) DiscoveryV4() *discover.UDPv4 {
return srv.discv4
}
-// DiscoveryV4 returns the discovery v5 instance, if configured.
+// DiscoveryV5 returns the discovery v5 instance, if configured.
func (srv *Server) DiscoveryV5() *discover.UDPv5 {
return srv.discv5
}
@@ -864,8 +865,10 @@ running:
if p.Inbound() {
inboundCount++
serveSuccessMeter.Mark(1)
+ activeInboundPeerGauge.Inc(1)
} else {
dialSuccessMeter.Mark(1)
+ activeOutboundPeerGauge.Inc(1)
}
activePeerGauge.Inc(1)
}
@@ -879,6 +882,9 @@ running:
srv.dialsched.peerRemoved(pd.rw)
if pd.Inbound() {
inboundCount--
+ activeInboundPeerGauge.Dec(1)
+ } else {
+ activeOutboundPeerGauge.Dec(1)
}
activePeerGauge.Dec(1)
}
@@ -989,7 +995,7 @@ func (srv *Server) listenLoop() {
break
}
- remoteIP := netutil.AddrIP(fd.RemoteAddr())
+ remoteIP := netutil.AddrAddr(fd.RemoteAddr())
if err := srv.checkInboundConn(remoteIP); err != nil {
srv.log.Debug("Rejected inbound connection", "addr", fd.RemoteAddr(), "err", err)
fd.Close()
@@ -997,8 +1003,7 @@ func (srv *Server) listenLoop() {
continue
}
-
- if remoteIP != nil {
+ if remoteIP.IsValid() {
fd = newMeteredConn(fd)
serveMeter.Mark(1)
srv.log.Trace("Accepted connection", "addr", fd.RemoteAddr())
@@ -1011,20 +1016,20 @@ func (srv *Server) listenLoop() {
}
}
-func (srv *Server) checkInboundConn(remoteIP net.IP) error {
- if remoteIP == nil {
+func (srv *Server) checkInboundConn(remoteIP netip.Addr) error {
+ if !remoteIP.IsValid() {
+ // This case happens for internal test connections without remote address.
return nil
}
// Reject connections that do not match NetRestrict.
- if srv.NetRestrict != nil && !srv.NetRestrict.Contains(remoteIP) {
- return fmt.Errorf("not in netrestrict list")
+ if srv.NetRestrict != nil && !srv.NetRestrict.ContainsAddr(remoteIP) {
+ return errors.New("not in netrestrict list")
}
// Reject Internet peers that try too often.
now := srv.clock.Now()
srv.inboundHistory.expire(now, nil)
-
- if !netutil.IsLAN(remoteIP) && srv.inboundHistory.contains(remoteIP.String()) {
- return fmt.Errorf("too many attempts")
+ if !netutil.AddrIsLAN(remoteIP) && srv.inboundHistory.contains(remoteIP.String()) {
+ return errors.New("too many attempts")
}
srv.inboundHistory.add(remoteIP.String(), now.Add(inboundThrottleTime))
@@ -1043,7 +1048,7 @@ func (srv *Server) SetupConn(fd net.Conn, flags connFlag, dialDest *enode.Node)
c.transport = srv.newTransport(fd, dialDest.Pubkey())
}
- err := srv.setupConn(c, flags, dialDest)
+ err := srv.setupConn(c, dialDest)
if err != nil {
if !c.is(inboundConn) {
markDialError(err)
@@ -1054,7 +1059,7 @@ func (srv *Server) SetupConn(fd net.Conn, flags connFlag, dialDest *enode.Node)
return err
}
-func (srv *Server) setupConn(c *conn, flags connFlag, dialDest *enode.Node) error {
+func (srv *Server) setupConn(c *conn, dialDest *enode.Node) error {
// Prevent leftover pending conns from entering the handshake.
srv.lock.Lock()
running := srv.running
@@ -1214,7 +1219,7 @@ func (srv *Server) NodeInfo() *NodeInfo {
Name: srv.Name,
Enode: node.URLv4(),
ID: node.ID().String(),
- IP: node.IP().String(),
+ IP: node.IPAddr().String(),
ListenAddr: srv.ListenAddr,
Protocols: make(map[string]interface{}),
}
@@ -1248,13 +1253,9 @@ func (srv *Server) PeersInfo() []*PeerInfo {
}
}
// Sort the result array alphabetically by node identifier
- for i := 0; i < len(infos); i++ {
- for j := i + 1; j < len(infos); j++ {
- if infos[i].ID > infos[j].ID {
- infos[i], infos[j] = infos[j], infos[i]
- }
- }
- }
+ slices.SortFunc(infos, func(a, b *PeerInfo) int {
+ return cmp.Compare(a.ID, b.ID)
+ })
return infos
}
diff --git a/p2p/server_nat.go b/p2p/server_nat.go
index 354597cc7a..299d275490 100644
--- a/p2p/server_nat.go
+++ b/p2p/server_nat.go
@@ -127,7 +127,7 @@ func (srv *Server) portMappingLoop() {
} else if !ip.Equal(lastExtIP) {
log.Debug("External IP changed", "ip", extip, "interface", srv.NAT)
} else {
- return
+ continue
}
// Here, we either failed to get the external IP, or it has changed.
lastExtIP = ip
diff --git a/p2p/server_nat_test.go b/p2p/server_nat_test.go
index de935fcfc5..cbb1f37e0a 100644
--- a/p2p/server_nat_test.go
+++ b/p2p/server_nat_test.go
@@ -18,6 +18,7 @@ package p2p
import (
"net"
+ "net/netip"
"sync/atomic"
"testing"
"time"
@@ -64,8 +65,8 @@ func TestServerPortMapping(t *testing.T) {
t.Error("wrong request count:", reqCount)
}
enr := srv.LocalNode().Node()
- if enr.IP().String() != "192.0.2.0" {
- t.Error("wrong IP in ENR:", enr.IP())
+ if enr.IPAddr() != netip.MustParseAddr("192.0.2.0") {
+ t.Error("wrong IP in ENR:", enr.IPAddr())
}
if enr.TCP() != 30000 {
t.Error("wrong TCP port in ENR:", enr.TCP())
diff --git a/p2p/simulations/README.md b/p2p/simulations/README.md
index 023f73a098..1f9f72dcda 100644
--- a/p2p/simulations/README.md
+++ b/p2p/simulations/README.md
@@ -123,20 +123,25 @@ The API is initialised with a particular node adapter and has the following
endpoints:
```
-GET / Get network information
-POST /start Start all nodes in the network
-POST /stop Stop all nodes in the network
-GET /events Stream network events
-GET /snapshot Take a network snapshot
-POST /snapshot Load a network snapshot
-POST /nodes Create a node
-GET /nodes Get all nodes in the network
-GET /nodes/:nodeid Get node information
-POST /nodes/:nodeid/start Start a node
-POST /nodes/:nodeid/stop Stop a node
-POST /nodes/:nodeid/conn/:peerid Connect two nodes
-DELETE /nodes/:nodeid/conn/:peerid Disconnect two nodes
-GET /nodes/:nodeid/rpc Make RPC requests to a node via WebSocket
+OPTIONS / Response 200 with "Access-Control-Allow-Headers"" header set to "Content-Type""
+GET / Get network information
+POST /start Start all nodes in the network
+POST /stop Stop all nodes in the network
+POST /mocker/start Start the mocker node simulation
+POST /mocker/stop Stop the mocker node simulation
+GET /mocker Get a list of available mockers
+POST /reset Reset all properties of a network to initial (empty) state
+GET /events Stream network events
+GET /snapshot Take a network snapshot
+POST /snapshot Load a network snapshot
+POST /nodes Create a node
+GET /nodes Get all nodes in the network
+GET /nodes/:nodeid Get node information
+POST /nodes/:nodeid/start Start a node
+POST /nodes/:nodeid/stop Stop a node
+POST /nodes/:nodeid/conn/:peerid Connect two nodes
+DELETE /nodes/:nodeid/conn/:peerid Disconnect two nodes
+GET /nodes/:nodeid/rpc Make RPC requests to a node via WebSocket
```
For convenience, `nodeid` in the URL can be the name of a node rather than its
diff --git a/p2p/simulations/adapters/exec.go b/p2p/simulations/adapters/exec.go
index 6ec3bc4248..1ecde0ddee 100644
--- a/p2p/simulations/adapters/exec.go
+++ b/p2p/simulations/adapters/exec.go
@@ -23,6 +23,7 @@ import (
"errors"
"fmt"
"io"
+ "log/slog"
"net"
"net/http"
"os"
@@ -41,7 +42,6 @@ import (
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/rpc"
"github.com/gorilla/websocket"
- "golang.org/x/exp/slog"
)
func init() {
@@ -322,10 +322,13 @@ func (n *ExecNode) Stop() error {
go func() {
waitErr <- n.Cmd.Wait()
}()
+ timer := time.NewTimer(5 * time.Second)
+ defer timer.Stop()
+
select {
case err := <-waitErr:
return err
- case <-time.After(5 * time.Second):
+ case <-timer.C:
return n.Cmd.Process.Kill()
}
}
@@ -506,7 +509,7 @@ func startExecNodeStack() (*node.Node, error) {
// decode the config
confEnv := os.Getenv(envNodeConfig)
if confEnv == "" {
- return nil, fmt.Errorf("missing " + envNodeConfig)
+ return nil, errors.New("missing " + envNodeConfig)
}
var conf execNodeConfig
diff --git a/p2p/simulations/adapters/inproc.go b/p2p/simulations/adapters/inproc.go
index 79faf0ba75..7ed3d5e072 100644
--- a/p2p/simulations/adapters/inproc.go
+++ b/p2p/simulations/adapters/inproc.go
@@ -20,6 +20,7 @@ import (
"context"
"errors"
"fmt"
+ "maps"
"math"
"net"
"sync"
@@ -224,11 +225,7 @@ func (sn *SimNode) ServeRPC(conn *websocket.Conn) error {
// simulation_snapshot RPC method
func (sn *SimNode) Snapshots() (map[string][]byte, error) {
sn.lock.RLock()
-
- services := make(map[string]node.Lifecycle, len(sn.running))
- for name, service := range sn.running {
- services[name] = service
- }
+ services := maps.Clone(sn.running)
sn.lock.RUnlock()
if len(services) == 0 {
@@ -339,13 +336,7 @@ func (sn *SimNode) Services() []node.Lifecycle {
func (sn *SimNode) ServiceMap() map[string]node.Lifecycle {
sn.lock.RLock()
defer sn.lock.RUnlock()
-
- services := make(map[string]node.Lifecycle, len(sn.running))
- for name, service := range sn.running {
- services[name] = service
- }
-
- return services
+ return maps.Clone(sn.running)
}
// Server returns the underlying p2p.Server
diff --git a/p2p/simulations/adapters/inproc_test.go b/p2p/simulations/adapters/inproc_test.go
index 5bcd8ca4d3..ca271bcfa8 100644
--- a/p2p/simulations/adapters/inproc_test.go
+++ b/p2p/simulations/adapters/inproc_test.go
@@ -84,7 +84,7 @@ func TestTCPPipeBidirections(t *testing.T) {
}
if !bytes.Equal(expected, out) {
- t.Fatalf("expected %#v, got %#v", out, expected)
+ t.Fatalf("expected %#v, got %#v", expected, out)
} else {
msg := []byte(fmt.Sprintf("pong %02d", i))
if _, err := c2.Write(msg); err != nil {
@@ -102,7 +102,7 @@ func TestTCPPipeBidirections(t *testing.T) {
}
if !bytes.Equal(expected, out) {
- t.Fatalf("expected %#v, got %#v", out, expected)
+ t.Fatalf("expected %#v, got %#v", expected, out)
}
}
}
diff --git a/p2p/simulations/adapters/types.go b/p2p/simulations/adapters/types.go
index 965e706bb6..ba979547a8 100644
--- a/p2p/simulations/adapters/types.go
+++ b/p2p/simulations/adapters/types.go
@@ -21,6 +21,7 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
+ "log/slog"
"net"
"os"
"strconv"
@@ -34,7 +35,6 @@ import (
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/ethereum/go-ethereum/rpc"
"github.com/gorilla/websocket"
- "golang.org/x/exp/slog"
)
// Node represents a node in a simulation network which is created by a
@@ -42,7 +42,6 @@ import (
//
// - SimNode, an in-memory node in the same process
// - ExecNode, a child process node
-// - DockerNode, a node running in a Docker container
type Node interface {
// Addr returns the node's address (e.g. an Enode URL)
Addr() []byte
@@ -308,7 +307,7 @@ func RegisterLifecycles(lifecycles LifecycleConstructors) {
}
// adds the host part to the configuration's ENR, signs it
-// creates and the corresponding enode object to the configuration
+// creates and adds the corresponding enode object to the configuration
func (n *NodeConfig) initEnode(ip net.IP, tcpport int, udpport int) error {
enrIp := enr.IP(ip)
n.Record.Set(&enrIp)
diff --git a/p2p/simulations/events.go b/p2p/simulations/events.go
index d5b543c5b3..eaf2bcf20f 100644
--- a/p2p/simulations/events.go
+++ b/p2p/simulations/events.go
@@ -30,7 +30,7 @@ const (
EventTypeNode EventType = "node"
// EventTypeConn is the type of event emitted when a connection is
- // is either established or dropped between two nodes
+ // either established or dropped between two nodes
EventTypeConn EventType = "conn"
// EventTypeMsg is the type of event emitted when a p2p message it
diff --git a/p2p/simulations/examples/ping-pong.go b/p2p/simulations/examples/ping-pong.go
index a6cf058c12..15b2f428ae 100644
--- a/p2p/simulations/examples/ping-pong.go
+++ b/p2p/simulations/examples/ping-pong.go
@@ -33,7 +33,7 @@ import (
"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
)
-var adapterType = flag.String("adapter", "sim", `node adapter to use (one of "sim", "exec" or "docker")`)
+var adapterType = flag.String("adapter", "sim", `node adapter to use (one of "sim" or "exec")`)
// main() starts a simulation network which contains nodes running a simple
// ping-pong protocol
diff --git a/p2p/simulations/http_test.go b/p2p/simulations/http_test.go
index e5adfeaafc..63a912f3d9 100644
--- a/p2p/simulations/http_test.go
+++ b/p2p/simulations/http_test.go
@@ -20,6 +20,7 @@ import (
"context"
"flag"
"fmt"
+ "log/slog"
"math/rand"
"net/http/httptest"
"os"
@@ -37,7 +38,6 @@ import (
"github.com/ethereum/go-ethereum/p2p/simulations/adapters"
"github.com/ethereum/go-ethereum/rpc"
"github.com/mattn/go-colorable"
- "golang.org/x/exp/slog"
)
func TestMain(m *testing.M) {
@@ -291,8 +291,6 @@ func (t *TestAPI) Events(ctx context.Context) (*rpc.Subscription, error) {
return
case <-rpcSub.Err():
return
- case <-notifier.Closed():
- return
}
}
}()
@@ -915,7 +913,7 @@ func TestMsgFilterPassSingle(t *testing.T) {
})
}
-// TestMsgFilterPassSingle tests streaming message events using an invalid
+// TestMsgFilterFailBadParams tests streaming message events using an invalid
// filter
func TestMsgFilterFailBadParams(t *testing.T) {
// start the server
diff --git a/p2p/simulations/mocker.go b/p2p/simulations/mocker.go
index f47d1bd42f..c1ff19c921 100644
--- a/p2p/simulations/mocker.go
+++ b/p2p/simulations/mocker.go
@@ -66,9 +66,12 @@ func startStop(net *Network, quit chan struct{}, nodeCount int) {
if err != nil {
panic("Could not startup node network for mocker")
}
-
- tick := time.NewTicker(10 * time.Second)
+ var (
+ tick = time.NewTicker(10 * time.Second)
+ timer = time.NewTimer(3 * time.Second)
+ )
defer tick.Stop()
+ defer timer.Stop()
for {
select {
@@ -84,11 +87,12 @@ func startStop(net *Network, quit chan struct{}, nodeCount int) {
return
}
+ timer.Reset(3 * time.Second)
select {
case <-quit:
log.Info("Terminating simulation loop")
return
- case <-time.After(3 * time.Second):
+ case <-timer.C:
}
log.Debug("starting node", "id", id)
diff --git a/p2p/simulations/network.go b/p2p/simulations/network.go
index eab262723d..2a5e29984b 100644
--- a/p2p/simulations/network.go
+++ b/p2p/simulations/network.go
@@ -588,7 +588,7 @@ func (net *Network) GetRandomUpNode(excludeIDs ...enode.ID) *Node {
return net.getRandomUpNode(excludeIDs...)
}
-// GetRandomUpNode returns a random node on the network, which is running.
+// getRandomUpNode returns a random node on the network, which is running.
func (net *Network) getRandomUpNode(excludeIDs ...enode.ID) *Node {
return net.getRandomNode(net.getUpNodeIDs(), excludeIDs)
}
@@ -1135,11 +1135,14 @@ func (net *Network) Load(snap *Snapshot) error {
}
}
+ timeout := time.NewTimer(snapshotLoadTimeout)
+ defer timeout.Stop()
+
select {
// Wait until all connections from the snapshot are established.
case <-allConnected:
// Make sure that we do not wait forever.
- case <-time.After(snapshotLoadTimeout):
+ case <-timeout.C:
return errors.New("snapshot connections not established")
}
diff --git a/p2p/transport.go b/p2p/transport.go
index b4be03a661..ab20ffbf59 100644
--- a/p2p/transport.go
+++ b/p2p/transport.go
@@ -19,6 +19,7 @@ package p2p
import (
"bytes"
"crypto/ecdsa"
+ "errors"
"fmt"
"io"
"net"
@@ -167,7 +168,7 @@ func readProtocolHandshake(rw MsgReader) (*protoHandshake, error) {
}
if msg.Size > baseProtocolMaxMsgSize {
- return nil, fmt.Errorf("message too big")
+ return nil, errors.New("message too big")
}
if msg.Code == discMsg {
diff --git a/packaging/templates/mainnet-v1/archive/config.toml b/packaging/templates/mainnet-v1/archive/config.toml
index 9be166bac8..a62dda85b1 100644
--- a/packaging/templates/mainnet-v1/archive/config.toml
+++ b/packaging/templates/mainnet-v1/archive/config.toml
@@ -24,7 +24,7 @@ gcmode = "archive"
# enable-block-tracking = false
[p2p]
- maxpeers = 50
+ maxpeers = 200
port = 30303
# maxpendpeers = 50
# bind = "0.0.0.0"
@@ -37,12 +37,12 @@ gcmode = "archive"
# [p2p.discovery]
# v4disc = true
# v5disc = false
- # bootnodes = ["enode://b8f1cc9c5d4403703fbf377116469667d2b1823c0daf16b7250aa576bacf399e42c3930ccfcb02c5df6879565a2b8931335565f0e8d3f8e72385ecf4a4bf160a@3.36.224.80:30303", "enode://8729e0c825f3d9cad382555f3e46dcff21af323e89025a0e6312df541f4a9e73abfa562d64906f5e59c51fe6f0501b3e61b07979606c56329c020ed739910759@54.194.245.5:30303"]
+ bootnodes = [ "enode://b8f1cc9c5d4403703fbf377116469667d2b1823c0daf16b7250aa576bacf399e42c3930ccfcb02c5df6879565a2b8931335565f0e8d3f8e72385ecf4a4bf160a@3.36.224.80:30303", "enode://8729e0c825f3d9cad382555f3e46dcff21af323e89025a0e6312df541f4a9e73abfa562d64906f5e59c51fe6f0501b3e61b07979606c56329c020ed739910759@54.194.245.5:30303" ]
# bootnodesv4 = []
# bootnodesv5 = []
- # static-nodes = []
+ static-nodes = [ "enode://ad9180a1468702c7c6a7210544593b4bd444768ca754382d1da92fe9abaf408e58160dc72505936df63ca6afc3052e993cade199fe3ff067a5f11b0ee3c6e378@13.209.168.182:30303", "enode://7cf051238a3f92bbee811472a84592ab547ab2692ec09bd2104182551ca6de55f5a7cea48a3d36b411deccb4df976f27076d32019d9ccc4486a916c0e30f3a74@43.201.242.62:30303", "enode://40b4ad081f835ac974472cee8553a455be720263d45d091d395d747c6fa9b615c76e74afe8b9646cddde79ce5fa1dfbfda4d563ab58199681d100c5bbaf7be82@43.202.78.165:30303", "enode://a0da3a49d43404c12a1f350211f4a448cf6715eaa5667813e14e7af88a90820e6b2fb6fcc1a75b0207c19c98c4f6320b4c5c1bdeda408e1fa72710942d4ad6f6@3.38.254.221:30303", "enode://46feaae067017d18cc5c0dee365c970d5004d34e2cf65a82c051b16040b31b1a6714cc14aadc14d95b7c98cc5da3db1d3b8611e19f4ca4e8bee2b0498978c160@15.165.197.16:30303", "enode://fbf7edc7386abc991097687c699e80034518bd3ecc333b0718a49afdf34e93d4ddde377f7210dae4c8e7580e4901d6cbb82a043debe119b71a267c323c6c1ad6@52.78.154.236:30303", "enode://60572bb4659e41d9b2f0a06b2b7c4cf2a7517f2e5e4e49664974bf4c0f52630846f16f190818497d642dcc046698850b689d36d6a9dcd42e388a20e4a46a0de8@52.209.21.164:30303", "enode://71467975c9fbea1d1087693d7af1c8d12bc43029d52c9470b328f7cfe5252475f1886013ddc85ff880b0e7d26b4ce3e33566895ea95d67730e9d91daafbbab2d@99.81.158.129:30303", "enode://4bf816ccbdcd379e4623f65b42b91c18545c1721b58217cbd7258911418f5a112f1f1e01a6580d485844ac2635b3fa1cb6d6c0022319ee5c3a00388aad0b5279@34.254.124.45:30303", "enode://88a7d837d229ec20d9c5805ccb121e2580f2b8b92c3e8b669418addd34f36784ca20d68a672e24ae1daa8862480deed9d73c095b65baa0ce94a6290a1504fd27@34.252.116.193:30303", "enode://a1c1e190a397e351deda6c31faebbd45b459b11cb4ffe63fe894ca4b7860c3c2404ee888f8166c98906f4174c55a64d4f6a2955f6edf3de86d49a5c58e8e955f@54.76.109.39:30303", "enode://0e07395fb40ab63f4f13b0c5630eb94f72f5d4c4b04e5d2c91a1a950a9bfb504889ea9eb811cffb0df55b72883e20e6fde9aba14c9c5d1a48fae18ab3212a7ba@34.246.232.184:30303" ]
# trusted-nodes = []
- # dns = []
+ dns = [ "enrtree://AKUEZKN7PSKVNR65FZDHECMKOJQSGPARGTPPBI7WS2VUL4EGR6XPC@pos.polygon-peers.io" ]
# [heimdall]
# url = "http://localhost:1317"
@@ -51,7 +51,7 @@ gcmode = "archive"
[txpool]
nolocals = true
- pricelimit = 30000000000
+ pricelimit = 25000000000
accountslots = 16
globalslots = 32768
accountqueue = 16
@@ -64,7 +64,7 @@ gcmode = "archive"
[miner]
gaslimit = 30000000
- gasprice = "30000000000"
+ gasprice = "25000000000"
# mine = false
# etherbase = ""
# extradata = ""
@@ -121,7 +121,7 @@ gcmode = "archive"
# maxheaderhistory = 1024
# maxblockhistory = 1024
# maxprice = "5000000000000"
- ignoreprice = "30000000000"
+ ignoreprice = "25000000000"
[telemetry]
metrics = true
@@ -145,7 +145,7 @@ gcmode = "archive"
gc = 0
snapshot = 20
# database = 50
- trie = 30
+ # trie = 30
# noprefetch = false
# preimages = false
# txlookuplimit = 2350000
diff --git a/packaging/templates/mainnet-v1/sentry/sentry/bor/config.toml b/packaging/templates/mainnet-v1/sentry/sentry/bor/config.toml
index 5dec42f6b6..0ee56f339c 100644
--- a/packaging/templates/mainnet-v1/sentry/sentry/bor/config.toml
+++ b/packaging/templates/mainnet-v1/sentry/sentry/bor/config.toml
@@ -4,7 +4,7 @@ chain = "mainnet"
# vmdebug = false
datadir = "/var/lib/bor/data"
# ancient = ""
-# "db.engine" = "leveldb"
+# db.engine = "leveldb"
# keystore = ""
# "rpc.batchlimit" = 100
# "rpc.returndatalimit" = 100000
@@ -24,7 +24,7 @@ syncmode = "full"
# enable-block-tracking = false
[p2p]
- maxpeers = 50
+ maxpeers = 200
port = 30303
# maxpendpeers = 50
# bind = "0.0.0.0"
@@ -37,12 +37,12 @@ syncmode = "full"
# [p2p.discovery]
# v4disc = true
# v5disc = false
- # bootnodes = []
+ bootnodes = [ "enode://b8f1cc9c5d4403703fbf377116469667d2b1823c0daf16b7250aa576bacf399e42c3930ccfcb02c5df6879565a2b8931335565f0e8d3f8e72385ecf4a4bf160a@3.36.224.80:30303", "enode://8729e0c825f3d9cad382555f3e46dcff21af323e89025a0e6312df541f4a9e73abfa562d64906f5e59c51fe6f0501b3e61b07979606c56329c020ed739910759@54.194.245.5:30303" ]
# bootnodesv4 = []
# bootnodesv5 = []
- # static-nodes = []
+ static-nodes = [ "enode://ad9180a1468702c7c6a7210544593b4bd444768ca754382d1da92fe9abaf408e58160dc72505936df63ca6afc3052e993cade199fe3ff067a5f11b0ee3c6e378@13.209.168.182:30303", "enode://7cf051238a3f92bbee811472a84592ab547ab2692ec09bd2104182551ca6de55f5a7cea48a3d36b411deccb4df976f27076d32019d9ccc4486a916c0e30f3a74@43.201.242.62:30303", "enode://40b4ad081f835ac974472cee8553a455be720263d45d091d395d747c6fa9b615c76e74afe8b9646cddde79ce5fa1dfbfda4d563ab58199681d100c5bbaf7be82@43.202.78.165:30303", "enode://a0da3a49d43404c12a1f350211f4a448cf6715eaa5667813e14e7af88a90820e6b2fb6fcc1a75b0207c19c98c4f6320b4c5c1bdeda408e1fa72710942d4ad6f6@3.38.254.221:30303", "enode://46feaae067017d18cc5c0dee365c970d5004d34e2cf65a82c051b16040b31b1a6714cc14aadc14d95b7c98cc5da3db1d3b8611e19f4ca4e8bee2b0498978c160@15.165.197.16:30303", "enode://fbf7edc7386abc991097687c699e80034518bd3ecc333b0718a49afdf34e93d4ddde377f7210dae4c8e7580e4901d6cbb82a043debe119b71a267c323c6c1ad6@52.78.154.236:30303", "enode://60572bb4659e41d9b2f0a06b2b7c4cf2a7517f2e5e4e49664974bf4c0f52630846f16f190818497d642dcc046698850b689d36d6a9dcd42e388a20e4a46a0de8@52.209.21.164:30303", "enode://71467975c9fbea1d1087693d7af1c8d12bc43029d52c9470b328f7cfe5252475f1886013ddc85ff880b0e7d26b4ce3e33566895ea95d67730e9d91daafbbab2d@99.81.158.129:30303", "enode://4bf816ccbdcd379e4623f65b42b91c18545c1721b58217cbd7258911418f5a112f1f1e01a6580d485844ac2635b3fa1cb6d6c0022319ee5c3a00388aad0b5279@34.254.124.45:30303", "enode://88a7d837d229ec20d9c5805ccb121e2580f2b8b92c3e8b669418addd34f36784ca20d68a672e24ae1daa8862480deed9d73c095b65baa0ce94a6290a1504fd27@34.252.116.193:30303", "enode://a1c1e190a397e351deda6c31faebbd45b459b11cb4ffe63fe894ca4b7860c3c2404ee888f8166c98906f4174c55a64d4f6a2955f6edf3de86d49a5c58e8e955f@54.76.109.39:30303", "enode://0e07395fb40ab63f4f13b0c5630eb94f72f5d4c4b04e5d2c91a1a950a9bfb504889ea9eb811cffb0df55b72883e20e6fde9aba14c9c5d1a48fae18ab3212a7ba@34.246.232.184:30303" ]
# trusted-nodes = [":"] # Recommended setting with sentry <> validator architecture
- # dns = []
+ dns = [ "enrtree://AKUEZKN7PSKVNR65FZDHECMKOJQSGPARGTPPBI7WS2VUL4EGR6XPC@pos.polygon-peers.io" ]
# [heimdall]
# url = "http://localhost:1317"
@@ -51,7 +51,7 @@ syncmode = "full"
[txpool]
nolocals = true
- pricelimit = 30000000000
+ pricelimit = 25000000000
accountslots = 16
globalslots = 32768
accountqueue = 16
@@ -64,7 +64,7 @@ syncmode = "full"
[miner]
gaslimit = 30000000
- gasprice = "30000000000"
+ gasprice = "25000000000"
# mine = false
# etherbase = ""
# extradata = ""
@@ -121,7 +121,7 @@ syncmode = "full"
# maxheaderhistory = 1024
# maxblockhistory = 1024
# maxprice = "5000000000000"
- ignoreprice = "30000000000"
+ ignoreprice = "25000000000"
[telemetry]
metrics = true
diff --git a/packaging/templates/testnet-v4/archive/config.toml b/packaging/templates/mainnet-v1/sentry/sentry/bor/pbss_config.toml
similarity index 51%
rename from packaging/templates/testnet-v4/archive/config.toml
rename to packaging/templates/mainnet-v1/sentry/sentry/bor/pbss_config.toml
index 4bbefafe0d..3d1d06400e 100644
--- a/packaging/templates/testnet-v4/archive/config.toml
+++ b/packaging/templates/mainnet-v1/sentry/sentry/bor/pbss_config.toml
@@ -1,15 +1,17 @@
-chain = "mumbai"
+chain = "mainnet"
# identity = "node_name"
# verbosity = 3
# vmdebug = false
datadir = "/var/lib/bor/data"
# ancient = ""
-# "db.engine" = "leveldb"
+"db.engine" = "pebble"
+"state.scheme" = "path"
# keystore = ""
# "rpc.batchlimit" = 100
# "rpc.returndatalimit" = 100000
syncmode = "full"
-gcmode = "archive"
+# pbss does not support archive
+# gcmode = "full"
# snapshot = true
# ethstats = ""
# devfakeauthor = false
@@ -24,7 +26,7 @@ gcmode = "archive"
# enable-block-tracking = false
[p2p]
- maxpeers = 50
+ maxpeers = 200
port = 30303
# maxpendpeers = 50
# bind = "0.0.0.0"
@@ -37,12 +39,12 @@ gcmode = "archive"
# [p2p.discovery]
# v4disc = true
# v5disc = false
- # bootnodes = []
+ bootnodes = [ "enode://b8f1cc9c5d4403703fbf377116469667d2b1823c0daf16b7250aa576bacf399e42c3930ccfcb02c5df6879565a2b8931335565f0e8d3f8e72385ecf4a4bf160a@3.36.224.80:30303", "enode://8729e0c825f3d9cad382555f3e46dcff21af323e89025a0e6312df541f4a9e73abfa562d64906f5e59c51fe6f0501b3e61b07979606c56329c020ed739910759@54.194.245.5:30303" ]
# bootnodesv4 = []
# bootnodesv5 = []
- # static-nodes = []
- # trusted-nodes = []
- # dns = []
+ static-nodes = [ "enode://ad9180a1468702c7c6a7210544593b4bd444768ca754382d1da92fe9abaf408e58160dc72505936df63ca6afc3052e993cade199fe3ff067a5f11b0ee3c6e378@13.209.168.182:30303", "enode://7cf051238a3f92bbee811472a84592ab547ab2692ec09bd2104182551ca6de55f5a7cea48a3d36b411deccb4df976f27076d32019d9ccc4486a916c0e30f3a74@43.201.242.62:30303", "enode://40b4ad081f835ac974472cee8553a455be720263d45d091d395d747c6fa9b615c76e74afe8b9646cddde79ce5fa1dfbfda4d563ab58199681d100c5bbaf7be82@43.202.78.165:30303", "enode://a0da3a49d43404c12a1f350211f4a448cf6715eaa5667813e14e7af88a90820e6b2fb6fcc1a75b0207c19c98c4f6320b4c5c1bdeda408e1fa72710942d4ad6f6@3.38.254.221:30303", "enode://46feaae067017d18cc5c0dee365c970d5004d34e2cf65a82c051b16040b31b1a6714cc14aadc14d95b7c98cc5da3db1d3b8611e19f4ca4e8bee2b0498978c160@15.165.197.16:30303", "enode://fbf7edc7386abc991097687c699e80034518bd3ecc333b0718a49afdf34e93d4ddde377f7210dae4c8e7580e4901d6cbb82a043debe119b71a267c323c6c1ad6@52.78.154.236:30303", "enode://60572bb4659e41d9b2f0a06b2b7c4cf2a7517f2e5e4e49664974bf4c0f52630846f16f190818497d642dcc046698850b689d36d6a9dcd42e388a20e4a46a0de8@52.209.21.164:30303", "enode://71467975c9fbea1d1087693d7af1c8d12bc43029d52c9470b328f7cfe5252475f1886013ddc85ff880b0e7d26b4ce3e33566895ea95d67730e9d91daafbbab2d@99.81.158.129:30303", "enode://4bf816ccbdcd379e4623f65b42b91c18545c1721b58217cbd7258911418f5a112f1f1e01a6580d485844ac2635b3fa1cb6d6c0022319ee5c3a00388aad0b5279@34.254.124.45:30303", "enode://88a7d837d229ec20d9c5805ccb121e2580f2b8b92c3e8b669418addd34f36784ca20d68a672e24ae1daa8862480deed9d73c095b65baa0ce94a6290a1504fd27@34.252.116.193:30303", "enode://a1c1e190a397e351deda6c31faebbd45b459b11cb4ffe63fe894ca4b7860c3c2404ee888f8166c98906f4174c55a64d4f6a2955f6edf3de86d49a5c58e8e955f@54.76.109.39:30303", "enode://0e07395fb40ab63f4f13b0c5630eb94f72f5d4c4b04e5d2c91a1a950a9bfb504889ea9eb811cffb0df55b72883e20e6fde9aba14c9c5d1a48fae18ab3212a7ba@34.246.232.184:30303" ]
+ # trusted-nodes = [":"] # Recommended setting with sentry <> validator architecture
+ dns = [ "enrtree://AKUEZKN7PSKVNR65FZDHECMKOJQSGPARGTPPBI7WS2VUL4EGR6XPC@pos.polygon-peers.io" ]
# [heimdall]
# url = "http://localhost:1317"
@@ -51,20 +53,20 @@ gcmode = "archive"
[txpool]
nolocals = true
+ pricelimit = 25000000000
accountslots = 16
- globalslots = 131072
- accountqueue = 64
- globalqueue = 131072
+ globalslots = 32768
+ accountqueue = 16
+ globalqueue = 32768
lifetime = "1h30m0s"
# locals = []
# journal = ""
# rejournal = "1h0m0s"
- # pricelimit = 30000000000
# pricebump = 10
[miner]
gaslimit = 30000000
- # gasprice = "30000000000"
+ gasprice = "25000000000"
# mine = false
# etherbase = ""
# extradata = ""
@@ -82,20 +84,20 @@ gcmode = "archive"
[jsonrpc.http]
enabled = true
port = 8545
- host = "0.0.0.0"
+ host = "127.0.0.1"
api = ["eth", "net", "web3", "txpool", "bor"]
vhosts = ["*"]
corsdomain = ["*"]
# prefix = ""
# ep-size = 40
# ep-requesttimeout = "0s"
- [jsonrpc.ws]
- enabled = true
- port = 8546
+ # [jsonrpc.ws]
+ # enabled = false
+ # port = 8546
# prefix = ""
# host = "localhost"
# api = ["web3", "net"]
- origins = ["*"]
+ # origins = ["*"]
# ep-size = 40
# ep-requesttimeout = "0s"
# [jsonrpc.graphql]
@@ -115,13 +117,13 @@ gcmode = "archive"
# write = "30s"
# idle = "2m0s"
-# [gpo]
+[gpo]
# blocks = 20
# percentile = 60
# maxheaderhistory = 1024
# maxblockhistory = 1024
# maxprice = "5000000000000"
- # ignoreprice = "30000000000"
+ ignoreprice = "25000000000"
[telemetry]
metrics = true
@@ -141,11 +143,11 @@ gcmode = "archive"
# [telemetry.influx.tags]
[cache]
- # cache = 1024
- gc = 0
- snapshot = 20
+ cache = 4096
+ # gc = 25
+ # snapshot = 10
# database = 50
- trie = 30
+ # trie = 15
# noprefetch = false
# preimages = false
# txlookuplimit = 2350000
diff --git a/packaging/templates/mainnet-v1/sentry/validator/bor/config.toml b/packaging/templates/mainnet-v1/sentry/validator/bor/config.toml
index b9ad57f5c2..bcf19bbcbe 100644
--- a/packaging/templates/mainnet-v1/sentry/validator/bor/config.toml
+++ b/packaging/templates/mainnet-v1/sentry/validator/bor/config.toml
@@ -6,7 +6,7 @@ chain = "mainnet"
# vmdebug = false
datadir = "/var/lib/bor/data"
# ancient = ""
-# "db.engine" = "leveldb"
+# db.engine = "leveldb"
# keystore = "$BOR_DIR/keystore"
# "rpc.batchlimit" = 100
# "rpc.returndatalimit" = 100000
@@ -26,7 +26,7 @@ syncmode = "full"
# enable-block-tracking = false
[p2p]
- maxpeers = 20
+ maxpeers = 200
port = 30303
nodiscover = true
# maxpendpeers = 50
@@ -39,12 +39,12 @@ syncmode = "full"
# [p2p.discovery]
# v4disc = true
# v5disc = false
- # bootnodes = ["enode://b8f1cc9c5d4403703fbf377116469667d2b1823c0daf16b7250aa576bacf399e42c3930ccfcb02c5df6879565a2b8931335565f0e8d3f8e72385ecf4a4bf160a@3.36.224.80:30303", "enode://8729e0c825f3d9cad382555f3e46dcff21af323e89025a0e6312df541f4a9e73abfa562d64906f5e59c51fe6f0501b3e61b07979606c56329c020ed739910759@54.194.245.5:30303"]
+ bootnodes = ["enode://b8f1cc9c5d4403703fbf377116469667d2b1823c0daf16b7250aa576bacf399e42c3930ccfcb02c5df6879565a2b8931335565f0e8d3f8e72385ecf4a4bf160a@3.36.224.80:30303", "enode://8729e0c825f3d9cad382555f3e46dcff21af323e89025a0e6312df541f4a9e73abfa562d64906f5e59c51fe6f0501b3e61b07979606c56329c020ed739910759@54.194.245.5:30303"]
# bootnodesv4 = []
# bootnodesv5 = []
- # static-nodes = [":"] # Recommended setting with sentry <> validator architecture
+ static-nodes = [ "enode://ad9180a1468702c7c6a7210544593b4bd444768ca754382d1da92fe9abaf408e58160dc72505936df63ca6afc3052e993cade199fe3ff067a5f11b0ee3c6e378@13.209.168.182:30303", "enode://7cf051238a3f92bbee811472a84592ab547ab2692ec09bd2104182551ca6de55f5a7cea48a3d36b411deccb4df976f27076d32019d9ccc4486a916c0e30f3a74@43.201.242.62:30303", "enode://40b4ad081f835ac974472cee8553a455be720263d45d091d395d747c6fa9b615c76e74afe8b9646cddde79ce5fa1dfbfda4d563ab58199681d100c5bbaf7be82@43.202.78.165:30303", "enode://a0da3a49d43404c12a1f350211f4a448cf6715eaa5667813e14e7af88a90820e6b2fb6fcc1a75b0207c19c98c4f6320b4c5c1bdeda408e1fa72710942d4ad6f6@3.38.254.221:30303", "enode://46feaae067017d18cc5c0dee365c970d5004d34e2cf65a82c051b16040b31b1a6714cc14aadc14d95b7c98cc5da3db1d3b8611e19f4ca4e8bee2b0498978c160@15.165.197.16:30303", "enode://fbf7edc7386abc991097687c699e80034518bd3ecc333b0718a49afdf34e93d4ddde377f7210dae4c8e7580e4901d6cbb82a043debe119b71a267c323c6c1ad6@52.78.154.236:30303", "enode://60572bb4659e41d9b2f0a06b2b7c4cf2a7517f2e5e4e49664974bf4c0f52630846f16f190818497d642dcc046698850b689d36d6a9dcd42e388a20e4a46a0de8@52.209.21.164:30303", "enode://71467975c9fbea1d1087693d7af1c8d12bc43029d52c9470b328f7cfe5252475f1886013ddc85ff880b0e7d26b4ce3e33566895ea95d67730e9d91daafbbab2d@99.81.158.129:30303", "enode://4bf816ccbdcd379e4623f65b42b91c18545c1721b58217cbd7258911418f5a112f1f1e01a6580d485844ac2635b3fa1cb6d6c0022319ee5c3a00388aad0b5279@34.254.124.45:30303", "enode://88a7d837d229ec20d9c5805ccb121e2580f2b8b92c3e8b669418addd34f36784ca20d68a672e24ae1daa8862480deed9d73c095b65baa0ce94a6290a1504fd27@34.252.116.193:30303", "enode://a1c1e190a397e351deda6c31faebbd45b459b11cb4ffe63fe894ca4b7860c3c2404ee888f8166c98906f4174c55a64d4f6a2955f6edf3de86d49a5c58e8e955f@54.76.109.39:30303", "enode://0e07395fb40ab63f4f13b0c5630eb94f72f5d4c4b04e5d2c91a1a950a9bfb504889ea9eb811cffb0df55b72883e20e6fde9aba14c9c5d1a48fae18ab3212a7ba@34.246.232.184:30303" ] # Recommended setting with sentry <> validator architecture
# trusted-nodes = []
- # dns = []
+ dns = [ "enrtree://AKUEZKN7PSKVNR65FZDHECMKOJQSGPARGTPPBI7WS2VUL4EGR6XPC@pos.polygon-peers.io" ]
# [heimdall]
# url = "http://localhost:1317"
@@ -53,7 +53,7 @@ syncmode = "full"
[txpool]
nolocals = true
- pricelimit = 30000000000
+ pricelimit = 25000000000
accountslots = 16
globalslots = 32768
accountqueue = 16
@@ -67,7 +67,7 @@ syncmode = "full"
[miner]
mine = true
gaslimit = 30000000
- gasprice = "30000000000"
+ gasprice = "25000000000"
# etherbase = ""
# extradata = ""
# recommit = "2m5s"
@@ -123,7 +123,7 @@ syncmode = "full"
# maxheaderhistory = 1024
# maxblockhistory = 1024
# maxprice = "5000000000000"
- ignoreprice = "30000000000"
+ ignoreprice = "25000000000"
[telemetry]
metrics = true
diff --git a/packaging/templates/mainnet-v1/sentry/validator/bor/pbss_config.toml b/packaging/templates/mainnet-v1/sentry/validator/bor/pbss_config.toml
new file mode 100644
index 0000000000..6e71ad1cf9
--- /dev/null
+++ b/packaging/templates/mainnet-v1/sentry/validator/bor/pbss_config.toml
@@ -0,0 +1,180 @@
+# NOTE: Update and uncomment: `keystore`, `password`, and `unlock` fields.
+
+chain = "mainnet"
+# identity = "node_name"
+# verbosity = 3
+# vmdebug = false
+datadir = "/var/lib/bor/data"
+# ancient = ""
+"db.engine" = "pebble"
+"state.scheme" = "path"
+# keystore = "$BOR_DIR/keystore"
+# "rpc.batchlimit" = 100
+# "rpc.returndatalimit" = 100000
+syncmode = "full"
+# PBSS does not support archive
+# gcmode = "full"
+# snapshot = true
+# ethstats = ""
+# devfakeauthor = false
+
+# ["eth.requiredblocks"]
+
+# [log]
+ # vmodule = ""
+ # json = false
+ # backtrace = ""
+ # debug = true
+ # enable-block-tracking = false
+
+[p2p]
+ maxpeers = 200
+ port = 30303
+ nodiscover = true
+ # maxpendpeers = 50
+ # bind = "0.0.0.0"
+ # nat = "any"
+ # netrestrict = ""
+ # nodekey = ""
+ # nodekeyhex = ""
+ # txarrivalwait = "500ms"
+ # [p2p.discovery]
+ # v4disc = true
+ # v5disc = false
+ bootnodes = ["enode://b8f1cc9c5d4403703fbf377116469667d2b1823c0daf16b7250aa576bacf399e42c3930ccfcb02c5df6879565a2b8931335565f0e8d3f8e72385ecf4a4bf160a@3.36.224.80:30303", "enode://8729e0c825f3d9cad382555f3e46dcff21af323e89025a0e6312df541f4a9e73abfa562d64906f5e59c51fe6f0501b3e61b07979606c56329c020ed739910759@54.194.245.5:30303"]
+ # bootnodesv4 = []
+ # bootnodesv5 = []
+ static-nodes = [ "enode://ad9180a1468702c7c6a7210544593b4bd444768ca754382d1da92fe9abaf408e58160dc72505936df63ca6afc3052e993cade199fe3ff067a5f11b0ee3c6e378@13.209.168.182:30303", "enode://7cf051238a3f92bbee811472a84592ab547ab2692ec09bd2104182551ca6de55f5a7cea48a3d36b411deccb4df976f27076d32019d9ccc4486a916c0e30f3a74@43.201.242.62:30303", "enode://40b4ad081f835ac974472cee8553a455be720263d45d091d395d747c6fa9b615c76e74afe8b9646cddde79ce5fa1dfbfda4d563ab58199681d100c5bbaf7be82@43.202.78.165:30303", "enode://a0da3a49d43404c12a1f350211f4a448cf6715eaa5667813e14e7af88a90820e6b2fb6fcc1a75b0207c19c98c4f6320b4c5c1bdeda408e1fa72710942d4ad6f6@3.38.254.221:30303", "enode://46feaae067017d18cc5c0dee365c970d5004d34e2cf65a82c051b16040b31b1a6714cc14aadc14d95b7c98cc5da3db1d3b8611e19f4ca4e8bee2b0498978c160@15.165.197.16:30303", "enode://fbf7edc7386abc991097687c699e80034518bd3ecc333b0718a49afdf34e93d4ddde377f7210dae4c8e7580e4901d6cbb82a043debe119b71a267c323c6c1ad6@52.78.154.236:30303", "enode://60572bb4659e41d9b2f0a06b2b7c4cf2a7517f2e5e4e49664974bf4c0f52630846f16f190818497d642dcc046698850b689d36d6a9dcd42e388a20e4a46a0de8@52.209.21.164:30303", "enode://71467975c9fbea1d1087693d7af1c8d12bc43029d52c9470b328f7cfe5252475f1886013ddc85ff880b0e7d26b4ce3e33566895ea95d67730e9d91daafbbab2d@99.81.158.129:30303", "enode://4bf816ccbdcd379e4623f65b42b91c18545c1721b58217cbd7258911418f5a112f1f1e01a6580d485844ac2635b3fa1cb6d6c0022319ee5c3a00388aad0b5279@34.254.124.45:30303", "enode://88a7d837d229ec20d9c5805ccb121e2580f2b8b92c3e8b669418addd34f36784ca20d68a672e24ae1daa8862480deed9d73c095b65baa0ce94a6290a1504fd27@34.252.116.193:30303", "enode://a1c1e190a397e351deda6c31faebbd45b459b11cb4ffe63fe894ca4b7860c3c2404ee888f8166c98906f4174c55a64d4f6a2955f6edf3de86d49a5c58e8e955f@54.76.109.39:30303", "enode://0e07395fb40ab63f4f13b0c5630eb94f72f5d4c4b04e5d2c91a1a950a9bfb504889ea9eb811cffb0df55b72883e20e6fde9aba14c9c5d1a48fae18ab3212a7ba@34.246.232.184:30303" ] # Recommended setting with sentry <> validator architecture
+ # trusted-nodes = []
+ dns = [ "enrtree://AKUEZKN7PSKVNR65FZDHECMKOJQSGPARGTPPBI7WS2VUL4EGR6XPC@pos.polygon-peers.io" ]
+
+# [heimdall]
+ # url = "http://localhost:1317"
+ # "bor.without" = false
+ # grpc-address = ""
+
+[txpool]
+ nolocals = true
+ pricelimit = 25000000000
+ accountslots = 16
+ globalslots = 32768
+ accountqueue = 16
+ globalqueue = 32768
+ lifetime = "1h30m0s"
+ # locals = []
+ # journal = ""
+ # rejournal = "1h0m0s"
+ # pricebump = 10
+
+[miner]
+ mine = true
+ gaslimit = 30000000
+ gasprice = "25000000000"
+ # etherbase = ""
+ # extradata = ""
+ # recommit = "2m5s"
+ # commitinterrupt = true
+
+[jsonrpc]
+ ipcpath = "/var/lib/bor/bor.ipc"
+ # ipcdisable = false
+ # gascap = 50000000
+ # evmtimeout = "5s"
+ # txfeecap = 5.0
+ # allow-unprotected-txs = false
+ # enabledeprecatedpersonal = false
+ [jsonrpc.http]
+ enabled = true
+ port = 8545
+ host = "127.0.0.1"
+ api = ["eth", "net", "web3", "txpool", "bor"]
+ vhosts = ["*"]
+ corsdomain = ["*"]
+ # prefix = ""
+ # ep-size = 40
+ # ep-requesttimeout = "0s"
+ # [jsonrpc.ws]
+ # enabled = false
+ # port = 8546
+ # prefix = ""
+ # host = "localhost"
+ # api = ["web3", "net"]
+ # origins = ["*"]
+ # ep-size = 40
+ # ep-requesttimeout = "0s"
+ # [jsonrpc.graphql]
+ # enabled = false
+ # port = 0
+ # prefix = ""
+ # host = ""
+ # vhosts = ["*"]
+ # corsdomain = ["*"]
+ # [jsonrpc.auth]
+ # jwtsecret = ""
+ # addr = "localhost"
+ # port = 8551
+ # vhosts = ["localhost"]
+ # [jsonrpc.timeouts]
+ # read = "10s"
+ # write = "30s"
+ # idle = "2m0s"
+
+[gpo]
+ # blocks = 20
+ # percentile = 60
+ # maxheaderhistory = 1024
+ # maxblockhistory = 1024
+ # maxprice = "5000000000000"
+ ignoreprice = "25000000000"
+
+[telemetry]
+ metrics = true
+ # expensive = false
+ # prometheus-addr = ""
+ # opencollector-endpoint = ""
+ # [telemetry.influx]
+ # influxdb = false
+ # endpoint = ""
+ # database = ""
+ # username = ""
+ # password = ""
+ # influxdbv2 = false
+ # token = ""
+ # bucket = ""
+ # organization = ""
+ # [telemetry.influx.tags]
+
+[cache]
+ cache = 4096
+ # gc = 25
+ # snapshot = 10
+ # database = 50
+ # trie = 15
+ # noprefetch = false
+ # preimages = false
+ # txlookuplimit = 2350000
+ # blocklogs = 32
+ # timeout = "1h0m0s"
+ # fdlimit = 0
+
+[accounts]
+ allow-insecure-unlock = true
+ # password = "$BOR_DIR/password.txt"
+ # unlock = ["$ADDRESS"]
+ # lightkdf = false
+ # disable-bor-wallet = false
+
+# [grpc]
+ # addr = ":3131"
+
+# [developer]
+ # dev = false
+ # period = 0
+ # gaslimit = 11500000
+
+# [pprof]
+# pprof = false
+# port = 6060
+# addr = "127.0.0.1"
+# memprofilerate = 524288
+# blockprofilerate = 0
diff --git a/packaging/templates/mainnet-v1/without-sentry/bor/config.toml b/packaging/templates/mainnet-v1/without-sentry/bor/config.toml
index c7a7a3ddb6..24d25b4406 100644
--- a/packaging/templates/mainnet-v1/without-sentry/bor/config.toml
+++ b/packaging/templates/mainnet-v1/without-sentry/bor/config.toml
@@ -6,7 +6,7 @@ chain = "mainnet"
# vmdebug = false
datadir = "/var/lib/bor/data"
# ancient = ""
-# "db.engine" = "leveldb"
+# db.engine = "leveldb"
# keystore = "$BOR_DIR/keystore"
# "rpc.batchlimit" = 100
# "rpc.returndatalimit" = 100000
@@ -26,7 +26,7 @@ syncmode = "full"
# enable-block-tracking = false
[p2p]
- maxpeers = 50
+ maxpeers = 200
port = 30303
# maxpendpeers = 50
# bind = "0.0.0.0"
@@ -39,12 +39,12 @@ syncmode = "full"
# [p2p.discovery]
# v4disc = true
# v5disc = false
- # bootnodes = []
+ bootnodes = [ "enode://b8f1cc9c5d4403703fbf377116469667d2b1823c0daf16b7250aa576bacf399e42c3930ccfcb02c5df6879565a2b8931335565f0e8d3f8e72385ecf4a4bf160a@3.36.224.80:30303", "enode://8729e0c825f3d9cad382555f3e46dcff21af323e89025a0e6312df541f4a9e73abfa562d64906f5e59c51fe6f0501b3e61b07979606c56329c020ed739910759@54.194.245.5:30303" ]
# bootnodesv4 = []
# bootnodesv5 = []
- # static-nodes = []
+ static-nodes = [ "enode://ad9180a1468702c7c6a7210544593b4bd444768ca754382d1da92fe9abaf408e58160dc72505936df63ca6afc3052e993cade199fe3ff067a5f11b0ee3c6e378@13.209.168.182:30303", "enode://7cf051238a3f92bbee811472a84592ab547ab2692ec09bd2104182551ca6de55f5a7cea48a3d36b411deccb4df976f27076d32019d9ccc4486a916c0e30f3a74@43.201.242.62:30303", "enode://40b4ad081f835ac974472cee8553a455be720263d45d091d395d747c6fa9b615c76e74afe8b9646cddde79ce5fa1dfbfda4d563ab58199681d100c5bbaf7be82@43.202.78.165:30303", "enode://a0da3a49d43404c12a1f350211f4a448cf6715eaa5667813e14e7af88a90820e6b2fb6fcc1a75b0207c19c98c4f6320b4c5c1bdeda408e1fa72710942d4ad6f6@3.38.254.221:30303", "enode://46feaae067017d18cc5c0dee365c970d5004d34e2cf65a82c051b16040b31b1a6714cc14aadc14d95b7c98cc5da3db1d3b8611e19f4ca4e8bee2b0498978c160@15.165.197.16:30303", "enode://fbf7edc7386abc991097687c699e80034518bd3ecc333b0718a49afdf34e93d4ddde377f7210dae4c8e7580e4901d6cbb82a043debe119b71a267c323c6c1ad6@52.78.154.236:30303", "enode://60572bb4659e41d9b2f0a06b2b7c4cf2a7517f2e5e4e49664974bf4c0f52630846f16f190818497d642dcc046698850b689d36d6a9dcd42e388a20e4a46a0de8@52.209.21.164:30303", "enode://71467975c9fbea1d1087693d7af1c8d12bc43029d52c9470b328f7cfe5252475f1886013ddc85ff880b0e7d26b4ce3e33566895ea95d67730e9d91daafbbab2d@99.81.158.129:30303", "enode://4bf816ccbdcd379e4623f65b42b91c18545c1721b58217cbd7258911418f5a112f1f1e01a6580d485844ac2635b3fa1cb6d6c0022319ee5c3a00388aad0b5279@34.254.124.45:30303", "enode://88a7d837d229ec20d9c5805ccb121e2580f2b8b92c3e8b669418addd34f36784ca20d68a672e24ae1daa8862480deed9d73c095b65baa0ce94a6290a1504fd27@34.252.116.193:30303", "enode://a1c1e190a397e351deda6c31faebbd45b459b11cb4ffe63fe894ca4b7860c3c2404ee888f8166c98906f4174c55a64d4f6a2955f6edf3de86d49a5c58e8e955f@54.76.109.39:30303", "enode://0e07395fb40ab63f4f13b0c5630eb94f72f5d4c4b04e5d2c91a1a950a9bfb504889ea9eb811cffb0df55b72883e20e6fde9aba14c9c5d1a48fae18ab3212a7ba@34.246.232.184:30303" ]
# trusted-nodes = []
- # dns = []
+ dns = [ "enrtree://AKUEZKN7PSKVNR65FZDHECMKOJQSGPARGTPPBI7WS2VUL4EGR6XPC@pos.polygon-peers.io" ]
# [heimdall]
# url = "http://localhost:1317"
@@ -53,7 +53,7 @@ syncmode = "full"
[txpool]
nolocals = true
- pricelimit = 30000000000
+ pricelimit = 25000000000
accountslots = 16
globalslots = 32768
accountqueue = 16
@@ -67,7 +67,7 @@ syncmode = "full"
[miner]
mine = true
gaslimit = 30000000
- gasprice = "30000000000"
+ gasprice = "25000000000"
# etherbase = ""
# extradata = ""
# recommit = "2m5s"
@@ -123,7 +123,7 @@ syncmode = "full"
# maxheaderhistory = 1024
# maxblockhistory = 1024
# maxprice = "5000000000000"
- ignoreprice = "30000000000"
+ ignoreprice = "25000000000"
[telemetry]
metrics = true
diff --git a/packaging/templates/mainnet-v1/without-sentry/bor/pbss_config.toml b/packaging/templates/mainnet-v1/without-sentry/bor/pbss_config.toml
new file mode 100644
index 0000000000..ac23de5789
--- /dev/null
+++ b/packaging/templates/mainnet-v1/without-sentry/bor/pbss_config.toml
@@ -0,0 +1,179 @@
+# NOTE: Update and uncomment: `keystore`, `password`, and `unlock` fields.
+
+chain = "mainnet"
+# identity = "node_name"
+# verbosity = 3
+# vmdebug = false
+datadir = "/var/lib/bor/data"
+# ancient = ""
+"db.engine" = "pebble"
+"state.scheme" = "path"
+# keystore = "$BOR_DIR/keystore"
+# "rpc.batchlimit" = 100
+# "rpc.returndatalimit" = 100000
+syncmode = "full"
+# gcmode = "full"
+# snapshot = true
+# ethstats = ""
+# devfakeauthor = false
+
+# ["eth.requiredblocks"]
+
+# [log]
+ # vmodule = ""
+ # json = false
+ # backtrace = ""
+ # debug = true
+ # enable-block-tracking = false
+
+[p2p]
+ maxpeers = 200
+ port = 30303
+ # maxpendpeers = 50
+ # bind = "0.0.0.0"
+ # nodiscover = false
+ # nat = "any"
+ # netrestrict = ""
+ # nodekey = ""
+ # nodekeyhex = ""
+ # txarrivalwait = "500ms"
+ # [p2p.discovery]
+ # v4disc = true
+ # v5disc = false
+ bootnodes = [ "enode://b8f1cc9c5d4403703fbf377116469667d2b1823c0daf16b7250aa576bacf399e42c3930ccfcb02c5df6879565a2b8931335565f0e8d3f8e72385ecf4a4bf160a@3.36.224.80:30303", "enode://8729e0c825f3d9cad382555f3e46dcff21af323e89025a0e6312df541f4a9e73abfa562d64906f5e59c51fe6f0501b3e61b07979606c56329c020ed739910759@54.194.245.5:30303" ]
+ # bootnodesv4 = []
+ # bootnodesv5 = []
+ static-nodes = [ "enode://ad9180a1468702c7c6a7210544593b4bd444768ca754382d1da92fe9abaf408e58160dc72505936df63ca6afc3052e993cade199fe3ff067a5f11b0ee3c6e378@13.209.168.182:30303", "enode://7cf051238a3f92bbee811472a84592ab547ab2692ec09bd2104182551ca6de55f5a7cea48a3d36b411deccb4df976f27076d32019d9ccc4486a916c0e30f3a74@43.201.242.62:30303", "enode://40b4ad081f835ac974472cee8553a455be720263d45d091d395d747c6fa9b615c76e74afe8b9646cddde79ce5fa1dfbfda4d563ab58199681d100c5bbaf7be82@43.202.78.165:30303", "enode://a0da3a49d43404c12a1f350211f4a448cf6715eaa5667813e14e7af88a90820e6b2fb6fcc1a75b0207c19c98c4f6320b4c5c1bdeda408e1fa72710942d4ad6f6@3.38.254.221:30303", "enode://46feaae067017d18cc5c0dee365c970d5004d34e2cf65a82c051b16040b31b1a6714cc14aadc14d95b7c98cc5da3db1d3b8611e19f4ca4e8bee2b0498978c160@15.165.197.16:30303", "enode://fbf7edc7386abc991097687c699e80034518bd3ecc333b0718a49afdf34e93d4ddde377f7210dae4c8e7580e4901d6cbb82a043debe119b71a267c323c6c1ad6@52.78.154.236:30303", "enode://60572bb4659e41d9b2f0a06b2b7c4cf2a7517f2e5e4e49664974bf4c0f52630846f16f190818497d642dcc046698850b689d36d6a9dcd42e388a20e4a46a0de8@52.209.21.164:30303", "enode://71467975c9fbea1d1087693d7af1c8d12bc43029d52c9470b328f7cfe5252475f1886013ddc85ff880b0e7d26b4ce3e33566895ea95d67730e9d91daafbbab2d@99.81.158.129:30303", "enode://4bf816ccbdcd379e4623f65b42b91c18545c1721b58217cbd7258911418f5a112f1f1e01a6580d485844ac2635b3fa1cb6d6c0022319ee5c3a00388aad0b5279@34.254.124.45:30303", "enode://88a7d837d229ec20d9c5805ccb121e2580f2b8b92c3e8b669418addd34f36784ca20d68a672e24ae1daa8862480deed9d73c095b65baa0ce94a6290a1504fd27@34.252.116.193:30303", "enode://a1c1e190a397e351deda6c31faebbd45b459b11cb4ffe63fe894ca4b7860c3c2404ee888f8166c98906f4174c55a64d4f6a2955f6edf3de86d49a5c58e8e955f@54.76.109.39:30303", "enode://0e07395fb40ab63f4f13b0c5630eb94f72f5d4c4b04e5d2c91a1a950a9bfb504889ea9eb811cffb0df55b72883e20e6fde9aba14c9c5d1a48fae18ab3212a7ba@34.246.232.184:30303" ]
+ # trusted-nodes = []
+ dns = [ "enrtree://AKUEZKN7PSKVNR65FZDHECMKOJQSGPARGTPPBI7WS2VUL4EGR6XPC@pos.polygon-peers.io" ]
+
+# [heimdall]
+ # url = "http://localhost:1317"
+ # "bor.without" = false
+ # grpc-address = ""
+
+[txpool]
+ nolocals = true
+ pricelimit = 25000000000
+ accountslots = 16
+ globalslots = 32768
+ accountqueue = 16
+ globalqueue = 32768
+ lifetime = "1h30m0s"
+ # locals = []
+ # journal = ""
+ # rejournal = "1h0m0s"
+ # pricebump = 10
+
+[miner]
+ mine = true
+ gaslimit = 30000000
+ gasprice = "25000000000"
+ # etherbase = ""
+ # extradata = ""
+ # recommit = "2m5s"
+ # commitinterrupt = true
+
+[jsonrpc]
+ ipcpath = "/var/lib/bor/bor.ipc"
+ # ipcdisable = false
+ # gascap = 50000000
+ # evmtimeout = "5s"
+ # txfeecap = 5.0
+ # allow-unprotected-txs = false
+ # enabledeprecatedpersonal = false
+ [jsonrpc.http]
+ enabled = true
+ port = 8545
+ host = "127.0.0.1"
+ api = ["eth", "net", "web3", "txpool", "bor"]
+ vhosts = ["*"]
+ corsdomain = ["*"]
+ # prefix = ""
+ # ep-size = 40
+ # ep-requesttimeout = "0s"
+ # [jsonrpc.ws]
+ # enabled = false
+ # port = 8546
+ # prefix = ""
+ # host = "localhost"
+ # api = ["web3", "net"]
+ # origins = ["*"]
+ # ep-size = 40
+ # ep-requesttimeout = "0s"
+ # [jsonrpc.graphql]
+ # enabled = false
+ # port = 0
+ # prefix = ""
+ # host = ""
+ # vhosts = ["*"]
+ # corsdomain = ["*"]
+ # [jsonrpc.auth]
+ # jwtsecret = ""
+ # addr = "localhost"
+ # port = 8551
+ # vhosts = ["localhost"]
+ # [jsonrpc.timeouts]
+ # read = "10s"
+ # write = "30s"
+ # idle = "2m0s"
+
+[gpo]
+# blocks = 20
+# percentile = 60
+# maxheaderhistory = 1024
+# maxblockhistory = 1024
+# maxprice = "5000000000000"
+ ignoreprice = "25000000000"
+
+[telemetry]
+ metrics = true
+ # expensive = false
+ # prometheus-addr = ""
+ # opencollector-endpoint = ""
+ # [telemetry.influx]
+ # influxdb = false
+ # endpoint = ""
+ # database = ""
+ # username = ""
+ # password = ""
+ # influxdbv2 = false
+ # token = ""
+ # bucket = ""
+ # organization = ""
+ # [telemetry.influx.tags]
+
+[cache]
+ cache = 4096
+# gc = 25
+# snapshot = 10
+# database = 50
+# trie = 15
+# noprefetch = false
+# preimages = false
+# txlookuplimit = 2350000
+# blocklogs = 32
+# timeout = "1h0m0s"
+# fdlimit = 0
+
+[accounts]
+ allow-insecure-unlock = true
+ # password = "$BOR_DIR/password.txt"
+ # unlock = ["$ADDRESS"]
+ # lightkdf = false
+ # disable-bor-wallet = false
+
+# [grpc]
+ # addr = ":3131"
+
+# [developer]
+ # dev = false
+ # period = 0
+ # gaslimit = 11500000
+
+# [pprof]
+# pprof = false
+# port = 6060
+# addr = "127.0.0.1"
+# memprofilerate = 524288
+# blockprofilerate = 0
diff --git a/packaging/templates/package_scripts/control b/packaging/templates/package_scripts/control
index b95ef8aa6d..9008ea5c32 100644
--- a/packaging/templates/package_scripts/control
+++ b/packaging/templates/package_scripts/control
@@ -1,5 +1,5 @@
Source: bor
-Version: 1.3.3
+Version: 1.5.2
Section: develop
Priority: standard
Maintainer: Polygon
diff --git a/packaging/templates/package_scripts/control.arm64 b/packaging/templates/package_scripts/control.arm64
index f8a37a1c29..9b67e9dc56 100644
--- a/packaging/templates/package_scripts/control.arm64
+++ b/packaging/templates/package_scripts/control.arm64
@@ -1,5 +1,5 @@
Source: bor
-Version: 1.3.3
+Version: 1.5.2
Section: develop
Priority: standard
Maintainer: Polygon
diff --git a/packaging/templates/package_scripts/control.profile.amd64 b/packaging/templates/package_scripts/control.profile.amd64
index d9e7edfd90..591848766f 100644
--- a/packaging/templates/package_scripts/control.profile.amd64
+++ b/packaging/templates/package_scripts/control.profile.amd64
@@ -1,5 +1,5 @@
Source: bor-profile
-Version: 1.3.3
+Version: 1.5.2
Section: develop
Priority: standard
Maintainer: Polygon
diff --git a/packaging/templates/package_scripts/control.profile.arm64 b/packaging/templates/package_scripts/control.profile.arm64
index cf6823c4e2..28c58b93a7 100644
--- a/packaging/templates/package_scripts/control.profile.arm64
+++ b/packaging/templates/package_scripts/control.profile.arm64
@@ -1,5 +1,5 @@
Source: bor-profile
-Version: 1.3.3
+Version: 1.5.2
Section: develop
Priority: standard
Maintainer: Polygon
diff --git a/packaging/templates/package_scripts/control.validator b/packaging/templates/package_scripts/control.validator
index 6da01046a3..617c260911 100644
--- a/packaging/templates/package_scripts/control.validator
+++ b/packaging/templates/package_scripts/control.validator
@@ -1,5 +1,5 @@
Source: bor-profile
-Version: 1.3.3
+Version: 1.5.2
Section: develop
Priority: standard
Maintainer: Polygon
diff --git a/packaging/templates/package_scripts/control.validator.arm64 b/packaging/templates/package_scripts/control.validator.arm64
index e7679e5e46..8c22ec7920 100644
--- a/packaging/templates/package_scripts/control.validator.arm64
+++ b/packaging/templates/package_scripts/control.validator.arm64
@@ -1,5 +1,5 @@
Source: bor-profile
-Version: 1.3.3
+Version: 1.5.2
Section: develop
Priority: standard
Maintainer: Polygon
diff --git a/packaging/templates/testnet-amoy/archive/config.toml b/packaging/templates/testnet-amoy/archive/config.toml
index 0940fd7819..d7f19551e5 100644
--- a/packaging/templates/testnet-amoy/archive/config.toml
+++ b/packaging/templates/testnet-amoy/archive/config.toml
@@ -23,7 +23,7 @@ gcmode = "archive"
# debug = true
[p2p]
- maxpeers = 50
+ maxpeers = 200
port = 30303
# maxpendpeers = 50
# bind = "0.0.0.0"
@@ -35,10 +35,10 @@ gcmode = "archive"
# txarrivalwait = "500ms"
# [p2p.discovery]
# v5disc = false
- # bootnodes = []
# bootnodesv4 = []
# bootnodesv5 = []
- # static-nodes = []
+ bootnodes = [ "enode://bce861be777e91b0a5a49d58a51e14f32f201b4c6c2d1fbea6c7a1f14756cbb3f931f3188d6b65de8b07b53ff28d03b6e366d09e56360d2124a9fc5a15a0913d@54.217.171.196:30303", "enode://4a3dc0081a346d26a73d79dd88216a9402d2292318e2db9947dbc97ea9c4afb2498dc519c0af04420dc13a238c279062da0320181e7c1461216ce4513bfd40bf@13.251.184.185:30303" ]
+ static-nodes = [ "enode://383ec39eb7f7e23538ea846f502602632110a6bcfc7521bfc2b8833f5a190779507d006b28650d83674b75d188cb36bcb3c3e168a0f2b3d98f9a651cc6603146@52.214.229.208:30303", "enode://bce861be777e91b0a5a49d58a51e14f32f201b4c6c2d1fbea6c7a1f14756cbb3f931f3188d6b65de8b07b53ff28d03b6e366d09e56360d2124a9fc5a15a0913d@54.217.171.196:30303", "enode://a4a387ad423a2fd0d652808b270082250d3c616b7e8537209584ebad4806dd50ef8dc66a371c85c7f55e6c1f53747edbb11055c8073cfacf312047eaeb328f58@54.171.220.164:30303", "enode://4a3dc0081a346d26a73d79dd88216a9402d2292318e2db9947dbc97ea9c4afb2498dc519c0af04420dc13a238c279062da0320181e7c1461216ce4513bfd40bf@13.251.184.185:30303", "enode://e8fe33b52f90d4bc7a4e75800945df449d1a091bd347c9f11cd1dbcd98ea28cb4c231cb3b1c6feacdabca2aa91f1a6744724b44edc9382c107968792abdef261@52.74.18.182:30303", "enode://b240f1f18e8f3cc61df96a164ba215ea6fc3f00717e4300da6283362a0438bda53f81ecc24c575ff130066d42096319fa027c952681bbb4f003e0bdd5d5b4e61@52.76.37.145:30303", "enode://de55d16b6e1fca28cdd3d11eb0dd89e3b77b96d4722172bd5e04ac255922324076a87748e97bc021af2307dccbb5ef8062389cfcba1845f77219eee7935dea9f@52.74.125.36:30303", "enode://7f2272685fc3e31c8e43c7687dda43ea3192fd310ba01efcb7811d5dc7ad5a64402ea8cd827650e573a174cf29bb69331dffcca6f0b9894ef17eeafabd97a41d@47.128.184.10:30303", "enode://c66e12243b425b63528dd8b1ce87f2f7fbc85f35485e2d8bf6bbf0ec0dcd05b3a582ef62daadbde061b58058735788335d09ed972a451242b9943b85d323c239@63.32.214.97:30303", "enode://bd56c0f00dd37e14ae2b84f5eb50e357d3a2d326bdbb0cbb987411268b3f132288f6c86157fc132c6902d18b9be0de8bbdcd12d926e16232ebadd8e274aae780@52.208.81.179:30303", "enode://2f015d5b1571165975382281a2117a9b514e1b38e87a8116596fc9b3b121a93cfb238eb6f7b3ae30cf9c0154384372745ce9edc09cbc30526ab7e2059f57ddee@54.74.160.230:30303" ]
# trusted-nodes = []
# dns = []
@@ -57,12 +57,12 @@ gcmode = "archive"
# locals = []
# journal = ""
# rejournal = "1h0m0s"
- # pricelimit = 30000000000
+ # pricelimit = 25000000000
# pricebump = 10
[miner]
gaslimit = 30000000
- # gasprice = "30000000000"
+ # gasprice = "25000000000"
# mine = false
# etherbase = ""
# extradata = ""
@@ -119,7 +119,7 @@ gcmode = "archive"
# maxheaderhistory = 1024
# maxblockhistory = 1024
# maxprice = "5000000000000"
- # ignoreprice = "30000000000"
+ # ignoreprice = "25000000000"
[telemetry]
metrics = true
diff --git a/packaging/templates/testnet-amoy/sentry/sentry/bor/config.toml b/packaging/templates/testnet-amoy/sentry/sentry/bor/config.toml
index 94c195a2fe..e0d976ed57 100644
--- a/packaging/templates/testnet-amoy/sentry/sentry/bor/config.toml
+++ b/packaging/templates/testnet-amoy/sentry/sentry/bor/config.toml
@@ -23,7 +23,7 @@ syncmode = "full"
# debug = true
[p2p]
- maxpeers = 50
+ maxpeers = 200
port = 30303
# maxpendpeers = 50
# bind = "0.0.0.0"
@@ -35,10 +35,10 @@ syncmode = "full"
# txarrivalwait = "500ms"
# [p2p.discovery]
# v5disc = false
- # bootnodes = []
# bootnodesv4 = []
# bootnodesv5 = []
- # static-nodes = []
+ bootnodes = [ "enode://bce861be777e91b0a5a49d58a51e14f32f201b4c6c2d1fbea6c7a1f14756cbb3f931f3188d6b65de8b07b53ff28d03b6e366d09e56360d2124a9fc5a15a0913d@54.217.171.196:30303", "enode://4a3dc0081a346d26a73d79dd88216a9402d2292318e2db9947dbc97ea9c4afb2498dc519c0af04420dc13a238c279062da0320181e7c1461216ce4513bfd40bf@13.251.184.185:30303" ]
+ static-nodes = [ "enode://383ec39eb7f7e23538ea846f502602632110a6bcfc7521bfc2b8833f5a190779507d006b28650d83674b75d188cb36bcb3c3e168a0f2b3d98f9a651cc6603146@52.214.229.208:30303", "enode://bce861be777e91b0a5a49d58a51e14f32f201b4c6c2d1fbea6c7a1f14756cbb3f931f3188d6b65de8b07b53ff28d03b6e366d09e56360d2124a9fc5a15a0913d@54.217.171.196:30303", "enode://a4a387ad423a2fd0d652808b270082250d3c616b7e8537209584ebad4806dd50ef8dc66a371c85c7f55e6c1f53747edbb11055c8073cfacf312047eaeb328f58@54.171.220.164:30303", "enode://4a3dc0081a346d26a73d79dd88216a9402d2292318e2db9947dbc97ea9c4afb2498dc519c0af04420dc13a238c279062da0320181e7c1461216ce4513bfd40bf@13.251.184.185:30303", "enode://e8fe33b52f90d4bc7a4e75800945df449d1a091bd347c9f11cd1dbcd98ea28cb4c231cb3b1c6feacdabca2aa91f1a6744724b44edc9382c107968792abdef261@52.74.18.182:30303", "enode://b240f1f18e8f3cc61df96a164ba215ea6fc3f00717e4300da6283362a0438bda53f81ecc24c575ff130066d42096319fa027c952681bbb4f003e0bdd5d5b4e61@52.76.37.145:30303", "enode://de55d16b6e1fca28cdd3d11eb0dd89e3b77b96d4722172bd5e04ac255922324076a87748e97bc021af2307dccbb5ef8062389cfcba1845f77219eee7935dea9f@52.74.125.36:30303", "enode://7f2272685fc3e31c8e43c7687dda43ea3192fd310ba01efcb7811d5dc7ad5a64402ea8cd827650e573a174cf29bb69331dffcca6f0b9894ef17eeafabd97a41d@47.128.184.10:30303", "enode://c66e12243b425b63528dd8b1ce87f2f7fbc85f35485e2d8bf6bbf0ec0dcd05b3a582ef62daadbde061b58058735788335d09ed972a451242b9943b85d323c239@63.32.214.97:30303", "enode://bd56c0f00dd37e14ae2b84f5eb50e357d3a2d326bdbb0cbb987411268b3f132288f6c86157fc132c6902d18b9be0de8bbdcd12d926e16232ebadd8e274aae780@52.208.81.179:30303", "enode://2f015d5b1571165975382281a2117a9b514e1b38e87a8116596fc9b3b121a93cfb238eb6f7b3ae30cf9c0154384372745ce9edc09cbc30526ab7e2059f57ddee@54.74.160.230:30303" ]
# trusted-nodes = []
# dns = []
@@ -57,12 +57,12 @@ syncmode = "full"
# locals = []
# journal = ""
# rejournal = "1h0m0s"
- # pricelimit = 30000000000
+ # pricelimit = 25000000000
# pricebump = 10
[miner]
gaslimit = 30000000
- # gasprice = "30000000000"
+ # gasprice = "25000000000"
# mine = false
# etherbase = ""
# extradata = ""
@@ -119,7 +119,7 @@ syncmode = "full"
# maxheaderhistory = 1024
# maxblockhistory = 1024
# maxprice = "5000000000000"
- # ignoreprice = "30000000000"
+ # ignoreprice = "25000000000"
[telemetry]
metrics = true
diff --git a/packaging/templates/testnet-v4/sentry/sentry/bor/config.toml b/packaging/templates/testnet-amoy/sentry/sentry/bor/pbss_config.toml
similarity index 59%
rename from packaging/templates/testnet-v4/sentry/sentry/bor/config.toml
rename to packaging/templates/testnet-amoy/sentry/sentry/bor/pbss_config.toml
index a21a1eb3eb..6f72c5a3b2 100644
--- a/packaging/templates/testnet-v4/sentry/sentry/bor/config.toml
+++ b/packaging/templates/testnet-amoy/sentry/sentry/bor/pbss_config.toml
@@ -1,10 +1,11 @@
-chain = "mumbai"
+chain = "amoy"
# identity = "node_name"
# verbosity = 3
# vmdebug = false
datadir = "/var/lib/bor/data"
# ancient = ""
-# "db.engine" = "leveldb"
+db.engine = "pebble"
+state.scheme = "path"
# keystore = ""
# "rpc.batchlimit" = 100
# "rpc.returndatalimit" = 100000
@@ -21,10 +22,9 @@ syncmode = "full"
# json = false
# backtrace = ""
# debug = true
- # enable-block-tracking = false
[p2p]
- maxpeers = 50
+ maxpeers = 200
port = 30303
# maxpendpeers = 50
# bind = "0.0.0.0"
@@ -35,12 +35,11 @@ syncmode = "full"
# nodekeyhex = ""
# txarrivalwait = "500ms"
# [p2p.discovery]
- # v4disc = true
# v5disc = false
- # bootnodes = []
# bootnodesv4 = []
# bootnodesv5 = []
- # static-nodes = []
+ bootnodes = [ "enode://bce861be777e91b0a5a49d58a51e14f32f201b4c6c2d1fbea6c7a1f14756cbb3f931f3188d6b65de8b07b53ff28d03b6e366d09e56360d2124a9fc5a15a0913d@54.217.171.196:30303", "enode://4a3dc0081a346d26a73d79dd88216a9402d2292318e2db9947dbc97ea9c4afb2498dc519c0af04420dc13a238c279062da0320181e7c1461216ce4513bfd40bf@13.251.184.185:30303" ]
+ static-nodes = [ "enode://383ec39eb7f7e23538ea846f502602632110a6bcfc7521bfc2b8833f5a190779507d006b28650d83674b75d188cb36bcb3c3e168a0f2b3d98f9a651cc6603146@52.214.229.208:30303", "enode://bce861be777e91b0a5a49d58a51e14f32f201b4c6c2d1fbea6c7a1f14756cbb3f931f3188d6b65de8b07b53ff28d03b6e366d09e56360d2124a9fc5a15a0913d@54.217.171.196:30303", "enode://a4a387ad423a2fd0d652808b270082250d3c616b7e8537209584ebad4806dd50ef8dc66a371c85c7f55e6c1f53747edbb11055c8073cfacf312047eaeb328f58@54.171.220.164:30303", "enode://4a3dc0081a346d26a73d79dd88216a9402d2292318e2db9947dbc97ea9c4afb2498dc519c0af04420dc13a238c279062da0320181e7c1461216ce4513bfd40bf@13.251.184.185:30303", "enode://e8fe33b52f90d4bc7a4e75800945df449d1a091bd347c9f11cd1dbcd98ea28cb4c231cb3b1c6feacdabca2aa91f1a6744724b44edc9382c107968792abdef261@52.74.18.182:30303", "enode://b240f1f18e8f3cc61df96a164ba215ea6fc3f00717e4300da6283362a0438bda53f81ecc24c575ff130066d42096319fa027c952681bbb4f003e0bdd5d5b4e61@52.76.37.145:30303", "enode://de55d16b6e1fca28cdd3d11eb0dd89e3b77b96d4722172bd5e04ac255922324076a87748e97bc021af2307dccbb5ef8062389cfcba1845f77219eee7935dea9f@52.74.125.36:30303", "enode://7f2272685fc3e31c8e43c7687dda43ea3192fd310ba01efcb7811d5dc7ad5a64402ea8cd827650e573a174cf29bb69331dffcca6f0b9894ef17eeafabd97a41d@47.128.184.10:30303", "enode://c66e12243b425b63528dd8b1ce87f2f7fbc85f35485e2d8bf6bbf0ec0dcd05b3a582ef62daadbde061b58058735788335d09ed972a451242b9943b85d323c239@63.32.214.97:30303", "enode://bd56c0f00dd37e14ae2b84f5eb50e357d3a2d326bdbb0cbb987411268b3f132288f6c86157fc132c6902d18b9be0de8bbdcd12d926e16232ebadd8e274aae780@52.208.81.179:30303", "enode://2f015d5b1571165975382281a2117a9b514e1b38e87a8116596fc9b3b121a93cfb238eb6f7b3ae30cf9c0154384372745ce9edc09cbc30526ab7e2059f57ddee@54.74.160.230:30303" ]
# trusted-nodes = []
# dns = []
@@ -59,12 +58,12 @@ syncmode = "full"
# locals = []
# journal = ""
# rejournal = "1h0m0s"
- # pricelimit = 30000000000
+ # pricelimit = 25000000000
# pricebump = 10
[miner]
gaslimit = 30000000
- # gasprice = "30000000000"
+ # gasprice = "25000000000"
# mine = false
# etherbase = ""
# extradata = ""
@@ -121,7 +120,7 @@ syncmode = "full"
# maxheaderhistory = 1024
# maxblockhistory = 1024
# maxprice = "5000000000000"
- # ignoreprice = "30000000000"
+ # ignoreprice = "25000000000"
[telemetry]
metrics = true
@@ -146,10 +145,11 @@ syncmode = "full"
# snapshot = 10
# database = 50
# trie = 15
+ # journal = "triecache"
+ # rejournal = "1h0m0s"
# noprefetch = false
# preimages = false
# txlookuplimit = 2350000
- # blocklogs = 32
# timeout = "1h0m0s"
# fdlimit = 0
diff --git a/packaging/templates/testnet-amoy/sentry/validator/bor/config.toml b/packaging/templates/testnet-amoy/sentry/validator/bor/config.toml
index 7c12b2c8b7..7180b4e422 100644
--- a/packaging/templates/testnet-amoy/sentry/validator/bor/config.toml
+++ b/packaging/templates/testnet-amoy/sentry/validator/bor/config.toml
@@ -25,7 +25,7 @@ syncmode = "full"
# debug = true
[p2p]
- maxpeers = 3
+ maxpeers = 200
port = 30303
nodiscover = true
# maxpendpeers = 50
@@ -37,10 +37,10 @@ syncmode = "full"
# txarrivalwait = "500ms"
# [p2p.discovery]
# v5disc = false
- # bootnodes = []
# bootnodesv4 = []
# bootnodesv5 = []
- # static-nodes = []
+ bootnodes = [ "enode://bce861be777e91b0a5a49d58a51e14f32f201b4c6c2d1fbea6c7a1f14756cbb3f931f3188d6b65de8b07b53ff28d03b6e366d09e56360d2124a9fc5a15a0913d@54.217.171.196:30303", "enode://4a3dc0081a346d26a73d79dd88216a9402d2292318e2db9947dbc97ea9c4afb2498dc519c0af04420dc13a238c279062da0320181e7c1461216ce4513bfd40bf@13.251.184.185:30303" ]
+ static-nodes = [ "enode://383ec39eb7f7e23538ea846f502602632110a6bcfc7521bfc2b8833f5a190779507d006b28650d83674b75d188cb36bcb3c3e168a0f2b3d98f9a651cc6603146@52.214.229.208:30303", "enode://bce861be777e91b0a5a49d58a51e14f32f201b4c6c2d1fbea6c7a1f14756cbb3f931f3188d6b65de8b07b53ff28d03b6e366d09e56360d2124a9fc5a15a0913d@54.217.171.196:30303", "enode://a4a387ad423a2fd0d652808b270082250d3c616b7e8537209584ebad4806dd50ef8dc66a371c85c7f55e6c1f53747edbb11055c8073cfacf312047eaeb328f58@54.171.220.164:30303", "enode://4a3dc0081a346d26a73d79dd88216a9402d2292318e2db9947dbc97ea9c4afb2498dc519c0af04420dc13a238c279062da0320181e7c1461216ce4513bfd40bf@13.251.184.185:30303", "enode://e8fe33b52f90d4bc7a4e75800945df449d1a091bd347c9f11cd1dbcd98ea28cb4c231cb3b1c6feacdabca2aa91f1a6744724b44edc9382c107968792abdef261@52.74.18.182:30303", "enode://b240f1f18e8f3cc61df96a164ba215ea6fc3f00717e4300da6283362a0438bda53f81ecc24c575ff130066d42096319fa027c952681bbb4f003e0bdd5d5b4e61@52.76.37.145:30303", "enode://de55d16b6e1fca28cdd3d11eb0dd89e3b77b96d4722172bd5e04ac255922324076a87748e97bc021af2307dccbb5ef8062389cfcba1845f77219eee7935dea9f@52.74.125.36:30303", "enode://7f2272685fc3e31c8e43c7687dda43ea3192fd310ba01efcb7811d5dc7ad5a64402ea8cd827650e573a174cf29bb69331dffcca6f0b9894ef17eeafabd97a41d@47.128.184.10:30303", "enode://c66e12243b425b63528dd8b1ce87f2f7fbc85f35485e2d8bf6bbf0ec0dcd05b3a582ef62daadbde061b58058735788335d09ed972a451242b9943b85d323c239@63.32.214.97:30303", "enode://bd56c0f00dd37e14ae2b84f5eb50e357d3a2d326bdbb0cbb987411268b3f132288f6c86157fc132c6902d18b9be0de8bbdcd12d926e16232ebadd8e274aae780@52.208.81.179:30303", "enode://2f015d5b1571165975382281a2117a9b514e1b38e87a8116596fc9b3b121a93cfb238eb6f7b3ae30cf9c0154384372745ce9edc09cbc30526ab7e2059f57ddee@54.74.160.230:30303" ]
# trusted-nodes = []
# dns = []
@@ -59,13 +59,13 @@ syncmode = "full"
# locals = []
# journal = ""
# rejournal = "1h0m0s"
- # pricelimit = 30000000000
+ # pricelimit = 25000000000
# pricebump = 10
[miner]
mine = true
gaslimit = 30000000
- # gasprice = "30000000000"
+ # gasprice = "25000000000"
# etherbase = ""
# extradata = ""
# recommit = "2m5s"
@@ -121,7 +121,7 @@ syncmode = "full"
# maxheaderhistory = 1024
# maxblockhistory = 1024
# maxprice = "5000000000000"
- # ignoreprice = "30000000000"
+ # ignoreprice = "25000000000"
[telemetry]
metrics = true
diff --git a/packaging/templates/testnet-v4/sentry/validator/bor/config.toml b/packaging/templates/testnet-amoy/sentry/validator/bor/pbss_config.toml
similarity index 60%
rename from packaging/templates/testnet-v4/sentry/validator/bor/config.toml
rename to packaging/templates/testnet-amoy/sentry/validator/bor/pbss_config.toml
index ed1fac2a51..5a58afd786 100644
--- a/packaging/templates/testnet-v4/sentry/validator/bor/config.toml
+++ b/packaging/templates/testnet-amoy/sentry/validator/bor/pbss_config.toml
@@ -1,12 +1,13 @@
# NOTE: Update and uncomment: `keystore`, `password`, and `unlock` fields.
-chain = "mumbai"
+chain = "amoy"
# identity = "node_name"
# verbosity = 3
# vmdebug = false
datadir = "/var/lib/bor/data"
# ancient = ""
-# "db.engine" = "leveldb"
+db.engine = "pebble"
+state.scheme = "path"
# keystore = "$BOR_DIR/keystore"
# "rpc.batchlimit" = 100
# "rpc.returndatalimit" = 100000
@@ -23,10 +24,9 @@ syncmode = "full"
# json = false
# backtrace = ""
# debug = true
- # enable-block-tracking = false
[p2p]
- maxpeers = 1
+ maxpeers = 200
port = 30303
nodiscover = true
# maxpendpeers = 50
@@ -37,12 +37,11 @@ syncmode = "full"
# nodekeyhex = ""
# txarrivalwait = "500ms"
# [p2p.discovery]
- # v4disc = true
# v5disc = false
- # bootnodes = []
# bootnodesv4 = []
# bootnodesv5 = []
- # static-nodes = []
+ bootnodes = [ "enode://bce861be777e91b0a5a49d58a51e14f32f201b4c6c2d1fbea6c7a1f14756cbb3f931f3188d6b65de8b07b53ff28d03b6e366d09e56360d2124a9fc5a15a0913d@54.217.171.196:30303", "enode://4a3dc0081a346d26a73d79dd88216a9402d2292318e2db9947dbc97ea9c4afb2498dc519c0af04420dc13a238c279062da0320181e7c1461216ce4513bfd40bf@13.251.184.185:30303" ]
+ static-nodes = [ "enode://383ec39eb7f7e23538ea846f502602632110a6bcfc7521bfc2b8833f5a190779507d006b28650d83674b75d188cb36bcb3c3e168a0f2b3d98f9a651cc6603146@52.214.229.208:30303", "enode://bce861be777e91b0a5a49d58a51e14f32f201b4c6c2d1fbea6c7a1f14756cbb3f931f3188d6b65de8b07b53ff28d03b6e366d09e56360d2124a9fc5a15a0913d@54.217.171.196:30303", "enode://a4a387ad423a2fd0d652808b270082250d3c616b7e8537209584ebad4806dd50ef8dc66a371c85c7f55e6c1f53747edbb11055c8073cfacf312047eaeb328f58@54.171.220.164:30303", "enode://4a3dc0081a346d26a73d79dd88216a9402d2292318e2db9947dbc97ea9c4afb2498dc519c0af04420dc13a238c279062da0320181e7c1461216ce4513bfd40bf@13.251.184.185:30303", "enode://e8fe33b52f90d4bc7a4e75800945df449d1a091bd347c9f11cd1dbcd98ea28cb4c231cb3b1c6feacdabca2aa91f1a6744724b44edc9382c107968792abdef261@52.74.18.182:30303", "enode://b240f1f18e8f3cc61df96a164ba215ea6fc3f00717e4300da6283362a0438bda53f81ecc24c575ff130066d42096319fa027c952681bbb4f003e0bdd5d5b4e61@52.76.37.145:30303", "enode://de55d16b6e1fca28cdd3d11eb0dd89e3b77b96d4722172bd5e04ac255922324076a87748e97bc021af2307dccbb5ef8062389cfcba1845f77219eee7935dea9f@52.74.125.36:30303", "enode://7f2272685fc3e31c8e43c7687dda43ea3192fd310ba01efcb7811d5dc7ad5a64402ea8cd827650e573a174cf29bb69331dffcca6f0b9894ef17eeafabd97a41d@47.128.184.10:30303", "enode://c66e12243b425b63528dd8b1ce87f2f7fbc85f35485e2d8bf6bbf0ec0dcd05b3a582ef62daadbde061b58058735788335d09ed972a451242b9943b85d323c239@63.32.214.97:30303", "enode://bd56c0f00dd37e14ae2b84f5eb50e357d3a2d326bdbb0cbb987411268b3f132288f6c86157fc132c6902d18b9be0de8bbdcd12d926e16232ebadd8e274aae780@52.208.81.179:30303", "enode://2f015d5b1571165975382281a2117a9b514e1b38e87a8116596fc9b3b121a93cfb238eb6f7b3ae30cf9c0154384372745ce9edc09cbc30526ab7e2059f57ddee@54.74.160.230:30303" ]
# trusted-nodes = []
# dns = []
@@ -61,13 +60,13 @@ syncmode = "full"
# locals = []
# journal = ""
# rejournal = "1h0m0s"
- # pricelimit = 30000000000
+ # pricelimit = 25000000000
# pricebump = 10
[miner]
mine = true
gaslimit = 30000000
- # gasprice = "30000000000"
+ # gasprice = "25000000000"
# etherbase = ""
# extradata = ""
# recommit = "2m5s"
@@ -123,7 +122,7 @@ syncmode = "full"
# maxheaderhistory = 1024
# maxblockhistory = 1024
# maxprice = "5000000000000"
- # ignoreprice = "30000000000"
+ # ignoreprice = "25000000000"
[telemetry]
metrics = true
@@ -148,10 +147,11 @@ syncmode = "full"
# snapshot = 10
# database = 50
# trie = 15
+ # journal = "triecache"
+ # rejournal = "1h0m0s"
# noprefetch = false
# preimages = false
# txlookuplimit = 2350000
- # blocklogs = 32
# timeout = "1h0m0s"
# fdlimit = 0
diff --git a/packaging/templates/testnet-amoy/without-sentry/bor/config.toml b/packaging/templates/testnet-amoy/without-sentry/bor/config.toml
index 64053f7c31..91bd871c94 100644
--- a/packaging/templates/testnet-amoy/without-sentry/bor/config.toml
+++ b/packaging/templates/testnet-amoy/without-sentry/bor/config.toml
@@ -25,7 +25,7 @@ syncmode = "full"
# debug = true
[p2p]
- maxpeers = 50
+ maxpeers = 200
port = 30303
# maxpendpeers = 50
# bind = "0.0.0.0"
@@ -37,10 +37,10 @@ syncmode = "full"
# txarrivalwait = "500ms"
# [p2p.discovery]
# v5disc = false
- # bootnodes = []
# bootnodesv4 = []
# bootnodesv5 = []
- # static-nodes = []
+ bootnodes = [ "enode://bce861be777e91b0a5a49d58a51e14f32f201b4c6c2d1fbea6c7a1f14756cbb3f931f3188d6b65de8b07b53ff28d03b6e366d09e56360d2124a9fc5a15a0913d@54.217.171.196:30303", "enode://4a3dc0081a346d26a73d79dd88216a9402d2292318e2db9947dbc97ea9c4afb2498dc519c0af04420dc13a238c279062da0320181e7c1461216ce4513bfd40bf@13.251.184.185:30303" ]
+ static-nodes = [ "enode://383ec39eb7f7e23538ea846f502602632110a6bcfc7521bfc2b8833f5a190779507d006b28650d83674b75d188cb36bcb3c3e168a0f2b3d98f9a651cc6603146@52.214.229.208:30303", "enode://bce861be777e91b0a5a49d58a51e14f32f201b4c6c2d1fbea6c7a1f14756cbb3f931f3188d6b65de8b07b53ff28d03b6e366d09e56360d2124a9fc5a15a0913d@54.217.171.196:30303", "enode://a4a387ad423a2fd0d652808b270082250d3c616b7e8537209584ebad4806dd50ef8dc66a371c85c7f55e6c1f53747edbb11055c8073cfacf312047eaeb328f58@54.171.220.164:30303", "enode://4a3dc0081a346d26a73d79dd88216a9402d2292318e2db9947dbc97ea9c4afb2498dc519c0af04420dc13a238c279062da0320181e7c1461216ce4513bfd40bf@13.251.184.185:30303", "enode://e8fe33b52f90d4bc7a4e75800945df449d1a091bd347c9f11cd1dbcd98ea28cb4c231cb3b1c6feacdabca2aa91f1a6744724b44edc9382c107968792abdef261@52.74.18.182:30303", "enode://b240f1f18e8f3cc61df96a164ba215ea6fc3f00717e4300da6283362a0438bda53f81ecc24c575ff130066d42096319fa027c952681bbb4f003e0bdd5d5b4e61@52.76.37.145:30303", "enode://de55d16b6e1fca28cdd3d11eb0dd89e3b77b96d4722172bd5e04ac255922324076a87748e97bc021af2307dccbb5ef8062389cfcba1845f77219eee7935dea9f@52.74.125.36:30303", "enode://7f2272685fc3e31c8e43c7687dda43ea3192fd310ba01efcb7811d5dc7ad5a64402ea8cd827650e573a174cf29bb69331dffcca6f0b9894ef17eeafabd97a41d@47.128.184.10:30303", "enode://c66e12243b425b63528dd8b1ce87f2f7fbc85f35485e2d8bf6bbf0ec0dcd05b3a582ef62daadbde061b58058735788335d09ed972a451242b9943b85d323c239@63.32.214.97:30303", "enode://bd56c0f00dd37e14ae2b84f5eb50e357d3a2d326bdbb0cbb987411268b3f132288f6c86157fc132c6902d18b9be0de8bbdcd12d926e16232ebadd8e274aae780@52.208.81.179:30303", "enode://2f015d5b1571165975382281a2117a9b514e1b38e87a8116596fc9b3b121a93cfb238eb6f7b3ae30cf9c0154384372745ce9edc09cbc30526ab7e2059f57ddee@54.74.160.230:30303" ]
# trusted-nodes = []
# dns = []
@@ -59,13 +59,13 @@ syncmode = "full"
# locals = []
# journal = ""
# rejournal = "1h0m0s"
- # pricelimit = 30000000000
+ # pricelimit = 25000000000
# pricebump = 10
[miner]
mine = true
gaslimit = 30000000
- # gasprice = "30000000000"
+ # gasprice = "25000000000"
# etherbase = ""
# extradata = ""
# recommit = "2m5s"
@@ -121,7 +121,7 @@ syncmode = "full"
# maxheaderhistory = 1024
# maxblockhistory = 1024
# maxprice = "5000000000000"
-# ignoreprice = "30000000000"
+# ignoreprice = "25000000000"
[telemetry]
metrics = true
diff --git a/packaging/templates/testnet-v4/without-sentry/bor/config.toml b/packaging/templates/testnet-amoy/without-sentry/bor/pbss_config.toml
similarity index 60%
rename from packaging/templates/testnet-v4/without-sentry/bor/config.toml
rename to packaging/templates/testnet-amoy/without-sentry/bor/pbss_config.toml
index e9e3b0d1cd..9b16fd2035 100644
--- a/packaging/templates/testnet-v4/without-sentry/bor/config.toml
+++ b/packaging/templates/testnet-amoy/without-sentry/bor/pbss_config.toml
@@ -1,12 +1,13 @@
# NOTE: Update and uncomment: `keystore`, `password`, and `unlock` fields.
-chain = "mumbai"
+chain = "amoy"
# identity = "node_name"
# verbosity = 3
# vmdebug = false
datadir = "/var/lib/bor/data"
# ancient = ""
-# "db.engine" = "leveldb"
+db.engine = "pebble"
+state.scheme = "path"
# keystore = "$BOR_DIR/keystore"
# "rpc.batchlimit" = 100
# "rpc.returndatalimit" = 100000
@@ -23,10 +24,9 @@ syncmode = "full"
# json = false
# backtrace = ""
# debug = true
- # enable-block-tracking = false
[p2p]
- maxpeers = 50
+ maxpeers = 200
port = 30303
# maxpendpeers = 50
# bind = "0.0.0.0"
@@ -37,12 +37,11 @@ syncmode = "full"
# nodekeyhex = ""
# txarrivalwait = "500ms"
# [p2p.discovery]
- # v4disc = true
# v5disc = false
- # bootnodes = []
- # bootnodesv4 = []
# bootnodesv5 = []
- # static-nodes = []
+ # bootnodesv4 = []
+ bootnodes = [ "enode://bce861be777e91b0a5a49d58a51e14f32f201b4c6c2d1fbea6c7a1f14756cbb3f931f3188d6b65de8b07b53ff28d03b6e366d09e56360d2124a9fc5a15a0913d@54.217.171.196:30303", "enode://4a3dc0081a346d26a73d79dd88216a9402d2292318e2db9947dbc97ea9c4afb2498dc519c0af04420dc13a238c279062da0320181e7c1461216ce4513bfd40bf@13.251.184.185:30303" ]
+ static-nodes = [ "enode://383ec39eb7f7e23538ea846f502602632110a6bcfc7521bfc2b8833f5a190779507d006b28650d83674b75d188cb36bcb3c3e168a0f2b3d98f9a651cc6603146@52.214.229.208:30303", "enode://bce861be777e91b0a5a49d58a51e14f32f201b4c6c2d1fbea6c7a1f14756cbb3f931f3188d6b65de8b07b53ff28d03b6e366d09e56360d2124a9fc5a15a0913d@54.217.171.196:30303", "enode://a4a387ad423a2fd0d652808b270082250d3c616b7e8537209584ebad4806dd50ef8dc66a371c85c7f55e6c1f53747edbb11055c8073cfacf312047eaeb328f58@54.171.220.164:30303", "enode://4a3dc0081a346d26a73d79dd88216a9402d2292318e2db9947dbc97ea9c4afb2498dc519c0af04420dc13a238c279062da0320181e7c1461216ce4513bfd40bf@13.251.184.185:30303", "enode://e8fe33b52f90d4bc7a4e75800945df449d1a091bd347c9f11cd1dbcd98ea28cb4c231cb3b1c6feacdabca2aa91f1a6744724b44edc9382c107968792abdef261@52.74.18.182:30303", "enode://b240f1f18e8f3cc61df96a164ba215ea6fc3f00717e4300da6283362a0438bda53f81ecc24c575ff130066d42096319fa027c952681bbb4f003e0bdd5d5b4e61@52.76.37.145:30303", "enode://de55d16b6e1fca28cdd3d11eb0dd89e3b77b96d4722172bd5e04ac255922324076a87748e97bc021af2307dccbb5ef8062389cfcba1845f77219eee7935dea9f@52.74.125.36:30303", "enode://7f2272685fc3e31c8e43c7687dda43ea3192fd310ba01efcb7811d5dc7ad5a64402ea8cd827650e573a174cf29bb69331dffcca6f0b9894ef17eeafabd97a41d@47.128.184.10:30303", "enode://c66e12243b425b63528dd8b1ce87f2f7fbc85f35485e2d8bf6bbf0ec0dcd05b3a582ef62daadbde061b58058735788335d09ed972a451242b9943b85d323c239@63.32.214.97:30303", "enode://bd56c0f00dd37e14ae2b84f5eb50e357d3a2d326bdbb0cbb987411268b3f132288f6c86157fc132c6902d18b9be0de8bbdcd12d926e16232ebadd8e274aae780@52.208.81.179:30303", "enode://2f015d5b1571165975382281a2117a9b514e1b38e87a8116596fc9b3b121a93cfb238eb6f7b3ae30cf9c0154384372745ce9edc09cbc30526ab7e2059f57ddee@54.74.160.230:30303" ]
# trusted-nodes = []
# dns = []
@@ -61,13 +60,13 @@ syncmode = "full"
# locals = []
# journal = ""
# rejournal = "1h0m0s"
- # pricelimit = 30000000000
+ # pricelimit = 25000000000
# pricebump = 10
[miner]
mine = true
gaslimit = 30000000
- # gasprice = "30000000000"
+ # gasprice = "25000000000"
# etherbase = ""
# extradata = ""
# recommit = "2m5s"
@@ -123,7 +122,7 @@ syncmode = "full"
# maxheaderhistory = 1024
# maxblockhistory = 1024
# maxprice = "5000000000000"
-# ignoreprice = "30000000000"
+# ignoreprice = "25000000000"
[telemetry]
metrics = true
@@ -148,10 +147,11 @@ syncmode = "full"
# snapshot = 10
# database = 50
# trie = 15
+# journal = "triecache"
+# rejournal = "1h0m0s"
# noprefetch = false
# preimages = false
# txlookuplimit = 2350000
-# blocklogs = 32
# timeout = "1h0m0s"
# fdlimit = 0
diff --git a/params/config.go b/params/config.go
index 963a00b120..ba60575dfc 100644
--- a/params/config.go
+++ b/params/config.go
@@ -23,11 +23,13 @@ import (
"strconv"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/params/forks"
)
// Genesis hashes to enforce below configs on.
var (
MainnetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
+ HoleskyGenesisHash = common.HexToHash("0xb5f7f912443c940f21fd611f12828d75b534364ed9e95ca4e307729a4661bde4")
SepoliaGenesisHash = common.HexToHash("0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9")
RinkebyGenesisHash = common.HexToHash("0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")
GoerliGenesisHash = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a")
@@ -62,6 +64,29 @@ var (
TerminalTotalDifficultyPassed: true,
Ethash: new(EthashConfig),
}
+ // HoleskyChainConfig contains the chain parameters to run a node on the Holesky test network.
+ HoleskyChainConfig = &ChainConfig{
+ ChainID: big.NewInt(17000),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: true,
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ MuirGlacierBlock: nil,
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ ArrowGlacierBlock: nil,
+ GrayGlacierBlock: nil,
+ TerminalTotalDifficulty: big.NewInt(0),
+ TerminalTotalDifficultyPassed: true,
+ MergeNetsplitBlock: nil,
+ Ethash: new(EthashConfig),
+ }
// SepoliaChainConfig contains the chain parameters to run a node on the Sepolia test network.
SepoliaChainConfig = &ChainConfig{
ChainID: big.NewInt(11155111),
@@ -268,9 +293,10 @@ var (
ShanghaiBlock: big.NewInt(73100),
CancunBlock: big.NewInt(5423600),
Bor: &BorConfig{
- JaipurBlock: big.NewInt(73100),
- DelhiBlock: big.NewInt(73100),
- IndoreBlock: big.NewInt(73100),
+ JaipurBlock: big.NewInt(73100),
+ DelhiBlock: big.NewInt(73100),
+ IndoreBlock: big.NewInt(73100),
+ AhmedabadBlock: big.NewInt(11865856),
StateSyncConfirmationDelay: map[string]uint64{
"0": 128,
},
@@ -292,6 +318,29 @@ var (
"0": "0x000000000000000000000000000000000000dead",
"73100": "0xeCDD77cE6f146cCf5dab707941d318Bd50eeD2C9",
},
+ BlockAlloc: map[string]interface{}{
+ // write as interface since that is how it is decoded in genesis
+ "11865856": map[string]interface{}{
+ "0000000000000000000000000000000000001001": map[string]interface{}{
+ "balance": "0x0",
+ "code": "0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c80635407ca671161008c578063abca220411610066578063abca2204146102fa578063d72a0b6714610302578063ee3a87f21461031f578063f165053614610342576100cf565b80635407ca67146102585780636757e5d914610260578063942af179146102f2576100cf565b806303112a17146100d457806319494a17146100f357806330e69fc31461017e578063318926f7146101985780633434735f146101bc57806351950cd9146101c4575b600080fd5b6100f1600480360360208110156100ea57600080fd5b503561034a565b005b61016a6004803603604081101561010957600080fd5b8135919081019060408101602082013564010000000081111561012b57600080fd5b82018360208201111561013d57600080fd5b8035906020019184600183028401116401000000008311171561015f57600080fd5b50909250905061060d565b604080519115158252519081900360200190f35b61018661093e565b60408051918252519081900360200190f35b6101a0610944565b604080516001600160a01b039092168252519081900360200190f35b6101a0610968565b6100f160048036036102808110156101db57600080fd5b61020082013590610220830135906001600160a01b036102408501351690840184610280810161026082013564010000000081111561021957600080fd5b82018360208201111561022b57600080fd5b8035906020019184600183028401116401000000008311171561024d57600080fd5b509092509050610973565b610186610c78565b61027d6004803603602081101561027657600080fd5b5035610c7e565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102b757818101518382015260200161029f565b50505050905090810190601f1680156102e45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610186610d19565b610186610d1f565b61016a6004803603602081101561031857600080fd5b5035610d25565b6100f16004803603604081101561033557600080fd5b5080359060200135610d3a565b610186610db0565b60008181526003602090815260409182902080548351601f60026000196101006001861615020190931692909204918201849004840281018401909452808452606093928301828280156103df5780601f106103b4576101008083540402835291602001916103df565b820191906000526020600020905b8154815290600101906020018083116103c257829003601f168201915b50505050509050805160001415610426576040805162461bcd60e51b815260206004820152600660248201526508599bdd5b9960d21b604482015290519081900360640190fd5b600082815260036020526040812061043d916112bb565b6000606082806020019051604081101561045657600080fd5b81516020830180516040519294929383019291908464010000000082111561047d57600080fd5b90830190602082018581111561049257600080fd5b82516401000000008111828201881017156104ac57600080fd5b82525081516020918201929091019080838360005b838110156104d95781810151838201526020016104c1565b50505050905090810190601f1680156105065780820380516001836020036101000a031916815260200191505b5060405250505091509150837f8797144948782adcede8e04bfa0bd8fd56941e0df7508bd02a629b477f7b073a60405160405180910390a2604080516313629df560e11b815260048101868152602482019283528351604483015283516001600160a01b038616936326c53bea938993879390929160640190602085019080838360005b838110156105a257818101518382015260200161058a565b50505050905090810190601f1680156105cf5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b1580156105ef57600080fd5b505af1158015610603573d6000803e3d6000fd5b5050505050505050565b6000336002600160a01b031461065f576040805162461bcd60e51b81526020600482015260126024820152714e6f742053797374656d204164646573732160701b604482015290519081900360640190fd5b60606106a86106a385858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610db592505050565b610ddb565b905060006106c9826000815181106106bc57fe5b6020026020010151610f14565b90508060005460010114610724576040805162461bcd60e51b815260206004820152601b60248201527f537461746549647320617265206e6f742073657175656e7469616c0000000000604482015290519081900360640190fd5b6000805460019081018255835161074c918591811061073f57fe5b6020026020010151610f62565b9050606061076d8460028151811061076057fe5b6020026020010151610f82565b905061077882610fff565b15610933576000624c4b409050606084836040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156107cf5781810151838201526020016107b7565b50505050905090810190601f1680156107fc5780820380516001836020036101000a031916815260200191505b5060408051601f198184030181529190526020810180516001600160e01b03166313629df560e11b1781528151919650600095508594509092509050828887f1604080518215158152905191985086917f5a22725590b0a51c923940223f7458512164b1113359a735e86e7f27f44791ee9181900360200190a28661093057838360405160200180836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156108cc5781810151838201526020016108b4565b50505050905090810190601f1680156108f95780820380516001836020036101000a031916815260200191505b5060408051601f1981840301815291815260008b815260036020908152919020825161092e9750909550910192509050611302565b505b50505b505050509392505050565b60045481565b7f000000000000000000000000be971fef2bb60f709e1daf3e55d00914e230cd9481565b6002600160a01b0381565b6201000085106109be576040805162461bcd60e51b81526020600482015260116024820152700d2dcecc2d8d2c840d8cac2cc92dcc8caf607b1b604482015290519081900360640190fd5b60045460058054600101908190551115610a05576040805162461bcd60e51b8152602060048201526003602482015262195b9960ea1b604482015290519081900360640190fd5b60015480610a42576040805162461bcd60e51b8152602060048201526005602482015264085c9bdbdd60da1b604482015290519081900360640190fd5b60008585858560405160200180858152602001846001600160a01b0316815260200180602001828103825284848281815260200192508082843760008184015260408051601f19601f909301831690940184810390920184525250805160209091012096507f28cf91ac064e179f8a42e4b7a20ba080187781da55fd4f3f18870b7a25bacb559550505050828414801592509050610aef575060008281526002602052604090205460ff16155b610b29576040805162461bcd60e51b815260206004808301919091526024820152631d5cd95960e21b604482015290519081900360640190fd5b60008281526002602052604090819020805460ff191660011790558051610200818101909252610b74918b9060109083908390808284376000920191909152508b915085905061100b565b8314610bb0576040805162461bcd60e51b815260206004820152600660248201526510b83937b7b360d11b604482015290519081900360640190fd5b60405187907f8797144948782adcede8e04bfa0bd8fd56941e0df7508bd02a629b477f7b073a90600090a2604080516313629df560e11b81526004810189815260248201928352604482018790526001600160a01b038916926326c53bea928b928a928a92606401848480828437600081840152601f19601f820116905080830192505050945050505050600060405180830381600087803b158015610c5557600080fd5b505af1158015610c69573d6000803e3d6000fd5b50505050505050505050505050565b60005481565b60036020908152600091825260409182902080548351601f600260001961010060018616150201909316929092049182018490048402810184019094528084529091830182828015610d115780601f10610ce657610100808354040283529160200191610d11565b820191906000526020600020905b815481529060010190602001808311610cf457829003601f168201915b505050505081565b60055481565b60015481565b60026020526000908152604090205460ff1681565b336001600160a01b037f000000000000000000000000be971fef2bb60f709e1daf3e55d00914e230cd941614610da5576040805162461bcd60e51b815260206004820152600b60248201526a10b937b7ba29b2ba3a32b960a91b604482015290519081900360640190fd5b600191909155600455565b601081565b610dbd611380565b5060408051808201909152815181526020828101908201525b919050565b6060610de6826110b6565b610def57600080fd5b6000610dfa836110f0565b905060608167ffffffffffffffff81118015610e1557600080fd5b50604051908082528060200260200182016040528015610e4f57816020015b610e3c611380565b815260200190600190039081610e345790505b5090506000610e618560200151611148565b60208601510190506000805b84811015610eb857610e7e836111ab565b9150604051806040016040528083815260200184815250848281518110610ea157fe5b602090810291909101015291810191600101610e6d565b5085516020870151830314610f0a576040805162461bcd60e51b81526020600482015260136024820152722bb937b733903a37ba30b6103632b733ba341760691b604482015290519081900360640190fd5b5090949350505050565b805160009015801590610f2957508151602110155b610f3257600080fd5b600080610f3e84611244565b815191935091506020821015610f5a5760208290036101000a90045b949350505050565b8051600090601514610f7357600080fd5b610f7c82610f14565b92915050565b8051606090610f9057600080fd5b600080610f9c84611244565b9150915060608167ffffffffffffffff81118015610fb957600080fd5b506040519080825280601f01601f191660200182016040528015610fe4576020820181803683370190505b50905060208101610ff684828561126a565b50949350505050565b3b63ffffffff16151590565b600081815b6010811015610ff657600185821c8116141561106c5785816010811061103257fe5b60200201518260405160200180838152602001828152602001925050506040516020818303038152906040528051906020012091506110ae565b8186826010811061107957fe5b602002015160405160200180838152602001828152602001925050506040516020818303038152906040528051906020012091505b600101611010565b80516000906110c757506000610dd6565b6020820151805160001a9060c08210156110e657600092505050610dd6565b5060019392505050565b805160009061110157506000610dd6565b6000806111118460200151611148565b602085015185519181019250015b8082101561113f57611130826111ab565b6001909301929091019061111f565b50909392505050565b8051600090811a6080811015611162576000915050610dd6565b60b881108061117d575060c0811080159061117d575060f881105b1561118c576001915050610dd6565b60c08110156111a05760b519019050610dd6565b60f519019050610dd6565b80516000908190811a60808110156111c6576001915061123d565b60b88110156111db57607e198101915061123d565b60c08110156112085760b78103600185019450806020036101000a8551046001820181019350505061123d565b60f881101561121d5760be198101915061123d565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b60008060006112568460200151611148565b602085015194519481019594039392505050565b80611274576112b6565b5b60208110611294578251825260209283019290910190601f1901611275565b80156112b6578251825160208390036101000a60001901801990921691161782525b505050565b50805460018160011615610100020316600290046000825580601f106112e157506112ff565b601f0160209004906000526020600020908101906112ff919061139a565b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061134357805160ff1916838001178555611370565b82800160010185558215611370579182015b82811115611370578251825591602001919060010190611355565b5061137c92915061139a565b5090565b604051806040016040528060008152602001600081525090565b5b8082111561137c576000815560010161139b56fea164736f6c634300060c000a",
+ },
+ "0000000000000000000000000000000000001010": map[string]interface{}{
+ "balance": "0x0",
+ "code": "0x6080604052600436106101b75760003560e01c80638da5cb5b116100ec578063b789543c1161008a578063e614d0d611610064578063e614d0d614610695578063ed9ef524146106aa578063f2fde38b146106dd578063fc0c546a14610710576101b7565b8063b789543c14610626578063cc79f97b1461066b578063e306f77914610680576101b7565b806395d89b41116100c657806395d89b41146105a6578063a9059cbb146105bb578063abceeba2146105e7578063acd06cb3146105fc576101b7565b80638da5cb5b146105535780638f32d59b146105685780639025e64c14610591576101b7565b806347e7ef241161015957806370a082311161013357806370a082311461043c578063715018a61461046f578063771282f61461048457806377d32e9414610499576101b7565b806347e7ef24146103b3578063485cc955146103ec57806360f96a8f14610427576101b7565b806319d27d9c1161019557806319d27d9c146102a25780632e1a7d4d14610356578063313ce5671461037357806342fc47fb1461039e576101b7565b806306fdde03146101bc5780631499c5921461024657806318160ddd1461027b575b600080fd5b3480156101c857600080fd5b506101d1610725565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561020b5781810151838201526020016101f3565b50505050905090810190601f1680156102385780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025257600080fd5b506102796004803603602081101561026957600080fd5b50356001600160a01b031661075c565b005b34801561028757600080fd5b5061029061079c565b60408051918252519081900360200190f35b3480156102ae57600080fd5b5061033a600480360360a08110156102c557600080fd5b8101906020810181356401000000008111156102e057600080fd5b8201836020820111156102f257600080fd5b8035906020019184600183028401116401000000008311171561031457600080fd5b9193509150803590602081013590604081013590606001356001600160a01b03166107ac565b604080516001600160a01b039092168252519081900360200190f35b6102796004803603602081101561036c57600080fd5b50356107ee565b34801561037f57600080fd5b506103886108c6565b6040805160ff9092168252519081900360200190f35b3480156103aa57600080fd5b5061033a6108cb565b3480156103bf57600080fd5b50610279600480360360408110156103d657600080fd5b506001600160a01b0381351690602001356108da565b3480156103f857600080fd5b506102796004803603604081101561040f57600080fd5b506001600160a01b03813581169160200135166109a8565b34801561043357600080fd5b5061033a610a21565b34801561044857600080fd5b506102906004803603602081101561045f57600080fd5b50356001600160a01b0316610a30565b34801561047b57600080fd5b50610279610a3d565b34801561049057600080fd5b50610290610a98565b3480156104a557600080fd5b5061033a600480360360408110156104bc57600080fd5b813591908101906040810160208201356401000000008111156104de57600080fd5b8201836020820111156104f057600080fd5b8035906020019184600183028401116401000000008311171561051257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610a9e945050505050565b34801561055f57600080fd5b5061033a610bc2565b34801561057457600080fd5b5061057d610bd1565b604080519115158252519081900360200190f35b34801561059d57600080fd5b506101d1610be2565b3480156105b257600080fd5b506101d1610c00565b61057d600480360360408110156105d157600080fd5b506001600160a01b038135169060200135610c1d565b3480156105f357600080fd5b50610290610c40565b34801561060857600080fd5b5061057d6004803603602081101561061f57600080fd5b5035610cc9565b34801561063257600080fd5b506102906004803603608081101561064957600080fd5b506001600160a01b038135169060208101359060408101359060600135610cde565b34801561067757600080fd5b50610290610cfd565b34801561068c57600080fd5b50610290610d03565b3480156106a157600080fd5b50610290610d09565b3480156106b657600080fd5b50610279600480360360208110156106cd57600080fd5b50356001600160a01b0316610d53565b3480156106e957600080fd5b506102796004803603602081101561070057600080fd5b50356001600160a01b0316610e05565b34801561071c57600080fd5b5061033a610e22565b60408051808201909152601781527f506f6c79676f6e2045636f73797374656d20546f6b656e000000000000000000602082015290565b6040805162461bcd60e51b815260206004820152601060248201526f44697361626c6564206665617475726560801b604482015290519081900360640190fd5b6b204fce5e3e2502611000000090565b6040805162461bcd60e51b815260206004820152601060248201526f44697361626c6564206665617475726560801b6044820152905160009181900360640190fd5b3360006107fa82610a30565b600654909150610810908463ffffffff610e3116565b600655821580159061082157508234145b610868576040805162461bcd60e51b8152602060048201526013602482015272125b9cdd59999a58da595b9d08185b5bdd5b9d606a1b604482015290519081900360640190fd5b6002546001600160a01b0380841691167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f85846108a487610a30565b60408051938452602084019290925282820152519081900360600190a3505050565b601290565b6003546001600160a01b031681565b6108e2610bd1565b6108eb57600080fd5b60008111801561090357506001600160a01b03821615155b61093e5760405162461bcd60e51b815260040180806020018281038252602381526020018061138d6023913960400191505060405180910390fd5b600061094983610a30565b60065490915061095f908363ffffffff610e4616565b60065561096c8383610e58565b6002546001600160a01b0380851691167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f684846108a488610a30565b60075460ff16156109ea5760405162461bcd60e51b815260040180806020018281038252602381526020018061136a6023913960400191505060405180910390fd5b6007805460ff19166001179055600280546001600160a01b0383166001600160a01b0319909116179055610a1d82610f17565b5050565b6004546001600160a01b031681565b6001600160a01b03163190565b610a45610bd1565b610a4e57600080fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b60065481565b6000806000808451604114610ab95760009350505050610bbc565b50505060208201516040830151604184015160ff16601b811015610adb57601b015b8060ff16601b14158015610af357508060ff16601c14155b15610b045760009350505050610bbc565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa158015610b5b573d6000803e3d6000fd5b5050604051601f1901519450506001600160a01b038416610bb8576040805162461bcd60e51b815260206004820152601260248201527122b93937b91034b71032b1b932b1b7bb32b960711b604482015290519081900360640190fd5b5050505b92915050565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b604051806040016040528060028152602001613a9960f01b81525081565b6040805180820190915260038152621413d360ea1b602082015290565b6000813414610c2e57506000610bbc565b610c39338484610f85565b9392505050565b6040518060800160405280605b8152602001611434605b91396040516020018082805190602001908083835b60208310610c8b5780518252601f199092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b60056020526000908152604090205460ff1681565b6000610cf4610cef868686866111d2565b61128b565b95945050505050565b613a9981565b60015481565b6040518060800160405280605281526020016113b06052913960405160200180828051906020019080838360208310610c8b5780518252601f199092019160209182019101610c6c565b610d5b610bd1565b610d6457600080fd5b6001600160a01b038116610da95760405162461bcd60e51b81526004018080602001828103825260328152602001806114026032913960400191505060405180910390fd5b6003546040516001600160a01b038084169216907f1f9f3556dd336016cdf20adaead7d5c73665dba664b60e8c17e9a4eb91ce1d3990600090a3600380546001600160a01b0319166001600160a01b0392909216919091179055565b610e0d610bd1565b610e1657600080fd5b610e1f81610f17565b50565b6002546001600160a01b031681565b600082821115610e4057600080fd5b50900390565b600082820183811015610c3957600080fd5b60085415610e9a576040805162461bcd60e51b815260206004820152600a6024820152697265656e7472616e637960b01b604482015290519081900360640190fd5b6001600855604051611388906000906060906001600160a01b038616908490869085818181858888f193505050503d8060008114610ef4576040519150601f19603f3d011682016040523d82523d6000602084013e610ef9565b606091505b509150915081610f0b57805160208201fd5b50506000600855505050565b6001600160a01b038116610f2a57600080fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b604080516370a0823160e01b81526001600160a01b03851660048201529051600091829130916370a08231916024808301926020929190829003018186803b158015610fd057600080fd5b505afa158015610fe4573d6000803e3d6000fd5b505050506040513d6020811015610ffa57600080fd5b5051604080516370a0823160e01b81526001600160a01b0387166004820152905191925060009130916370a08231916024808301926020929190829003018186803b15801561104857600080fd5b505afa15801561105c573d6000803e3d6000fd5b505050506040513d602081101561107257600080fd5b50519050611081868686611299565b600254604080516370a0823160e01b81526001600160a01b03898116600483018190529251818a1694909116917fe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c49189918891889130916370a0823191602480820192602092909190829003018186803b1580156110fe57600080fd5b505afa158015611112573d6000803e3d6000fd5b505050506040513d602081101561112857600080fd5b5051604080516370a0823160e01b81526001600160a01b038f166004820152905130916370a08231916024808301926020929190829003018186803b15801561117057600080fd5b505afa158015611184573d6000803e3d6000fd5b505050506040513d602081101561119a57600080fd5b50516040805195865260208601949094528484019290925260608401526080830152519081900360a00190a450600195945050505050565b6000806040518060800160405280605b8152602001611434605b91396040516020018082805190602001908083835b602083106112205780518252601f199092019160209182019101611201565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f1901835280855282519282019290922082526001600160a01b039b909b169a81019a909a5250880196909652505050606084019190915260808301525060a0902090565b6000610bbc82600154611347565b6001600160a01b0382163014156112ed576040805162461bcd60e51b8152602060048201526013602482015272063616e27742073656e6420746f204d5243323606c1b604482015290519081900360640190fd5b6112f78282610e58565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b60405161190160f01b815260028101919091526022810191909152604290209056fe54686520636f6e747261637420697320616c726561647920696e697469616c697a6564496e73756666696369656e7420616d6f756e74206f7220696e76616c69642075736572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e7472616374294368696c6420746f6b656e3a206e6577206368696c64206164647265737320697320746865207a65726f2061646472657373546f6b656e5472616e736665724f726465722861646472657373207370656e6465722c75696e7432353620746f6b656e49644f72416d6f756e742c6279746573333220646174612c75696e743235362065787069726174696f6e29a265627a7a723158205f23be7574e70cfc01d0cfd6803b871f92465e9ae4a10fe95ed31ccb810bda3e64736f6c63430005110032",
+ },
+ "360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9": map[string]interface{}{
+ "balance": "0x0",
+ "code": "0x6080604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b9578063095ea7b31461014957806318160ddd146101ae57806323b872dd146101d95780632e1a7d4d1461025e578063313ce5671461028b57806370a08231146102bc57806395d89b4114610313578063a9059cbb146103a3578063d0e30db014610408578063dd62ed3e14610412575b6100b7610489565b005b3480156100c557600080fd5b506100ce610526565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561010e5780820151818401526020810190506100f3565b50505050905090810190601f16801561013b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015557600080fd5b50610194600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105c4565b604051808215151515815260200191505060405180910390f35b3480156101ba57600080fd5b506101c36106b6565b6040518082815260200191505060405180910390f35b3480156101e557600080fd5b50610244600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506106d5565b604051808215151515815260200191505060405180910390f35b34801561026a57600080fd5b5061028960048036038101908080359060200190929190505050610a22565b005b34801561029757600080fd5b506102a0610b55565b604051808260ff1660ff16815260200191505060405180910390f35b3480156102c857600080fd5b506102fd600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b68565b6040518082815260200191505060405180910390f35b34801561031f57600080fd5b50610328610b80565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036857808201518184015260208101905061034d565b50505050905090810190601f1680156103955780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103af57600080fd5b506103ee600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610c1e565b604051808215151515815260200191505060405180910390f35b610410610489565b005b34801561041e57600080fd5b50610473600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c33565b6040518082815260200191505060405180910390f35b34600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055503373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a2565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156105bc5780601f10610591576101008083540402835291602001916105bc565b820191906000526020600020905b81548152906001019060200180831161059f57829003601f168201915b505050505081565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60003073ffffffffffffffffffffffffffffffffffffffff1631905090565b600081600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561072557600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141580156107fd57507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414155b156109185781600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561088d57600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b81600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a7057600080fd5b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610b03573d6000803e3d6000fd5b503373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65826040518082815260200191505060405180910390a250565b600260009054906101000a900460ff1681565b60036020528060005260406000206000915090505481565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610c165780601f10610beb57610100808354040283529160200191610c16565b820191906000526020600020905b815481529060010190602001808311610bf957829003601f168201915b505050505081565b6000610c2b3384846106d5565b905092915050565b60046020528160005260406000206020528060005260406000206000915091505054815600a165627a7a72305820ea7b3a90a89969eb00d2a56f58b0f80481944475908acf25438759b53be73e5b0029",
+ },
+ },
+ "12121856": map[string]interface{}{
+ "360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9": map[string]interface{}{
+ "balance": "0x0",
+ "code": "0x6080604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b9578063095ea7b31461014957806318160ddd146101ae57806323b872dd146101d95780632e1a7d4d1461025e578063313ce5671461028b57806370a08231146102bc57806395d89b4114610313578063a9059cbb146103a3578063d0e30db014610408578063dd62ed3e14610412575b6100b7610489565b005b3480156100c557600080fd5b506100ce610526565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561010e5780820151818401526020810190506100f3565b50505050905090810190601f16801561013b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015557600080fd5b50610194600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610563565b604051808215151515815260200191505060405180910390f35b3480156101ba57600080fd5b506101c3610655565b6040518082815260200191505060405180910390f35b3480156101e557600080fd5b50610244600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610674565b604051808215151515815260200191505060405180910390f35b34801561026a57600080fd5b50610289600480360381019080803590602001909291905050506109c1565b005b34801561029757600080fd5b506102a0610af4565b604051808260ff1660ff16815260200191505060405180910390f35b3480156102c857600080fd5b506102fd600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610afd565b6040518082815260200191505060405180910390f35b34801561031f57600080fd5b50610328610b15565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036857808201518184015260208101905061034d565b50505050905090810190601f1680156103955780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103af57600080fd5b506103ee600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610b52565b604051808215151515815260200191505060405180910390f35b610410610489565b005b34801561041e57600080fd5b50610473600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b67565b6040518082815260200191505060405180910390f35b34600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055503373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a2565b60606040805190810160405280601f81526020017f5772617070656420506f6c79676f6e2045636f73797374656d20546f6b656e00815250905090565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60003073ffffffffffffffffffffffffffffffffffffffff1631905090565b600081600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156106c457600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415801561079c57507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414155b156108b75781600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561082c57600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b81600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a0f57600080fd5b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610aa2573d6000803e3d6000fd5b503373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65826040518082815260200191505060405180910390a250565b60006012905090565b60036020528060005260406000206000915090505481565b60606040805190810160405280600481526020017f57504f4c00000000000000000000000000000000000000000000000000000000815250905090565b6000610b5f338484610674565b905092915050565b60046020528160005260406000206020528060005260406000206000915091505054815600a165627a7a723058208d70d8aa2d752533105b5ccda8206dae8b0c1de765f89fb1f0c5727cbac1b40d0029",
+ },
+ },
+ },
},
}
@@ -313,9 +362,10 @@ var (
ShanghaiBlock: big.NewInt(50523000),
CancunBlock: big.NewInt(54876000),
Bor: &BorConfig{
- JaipurBlock: big.NewInt(23850000),
- DelhiBlock: big.NewInt(38189056),
- IndoreBlock: big.NewInt(44934656),
+ JaipurBlock: big.NewInt(23850000),
+ DelhiBlock: big.NewInt(38189056),
+ IndoreBlock: big.NewInt(44934656),
+ AhmedabadBlock: big.NewInt(62278656),
StateSyncConfirmationDelay: map[string]uint64{
"44934656": 128,
},
@@ -365,6 +415,23 @@ var (
"code": "0x608060405234801561001057600080fd5b506004361061005e576000357c01000000000000000000000000000000000000000000000000000000009004806319494a17146100635780633434735f146100fe5780635407ca6714610148575b600080fd5b6100e46004803603604081101561007957600080fd5b8101908080359060200190929190803590602001906401000000008111156100a057600080fd5b8201836020820111156100b257600080fd5b803590602001918460018302840111640100000000831117156100d457600080fd5b9091929391929390505050610166565b604051808215151515815260200191505060405180910390f35b6101066104d3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101506104eb565b6040518082815260200191505060405180910390f35b600073fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461021d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4e6f742053797374656d2041646465737321000000000000000000000000000081525060200191505060405180910390fd5b606061027461026f85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506104f1565b61051f565b905060006102958260008151811061028857fe5b60200260200101516105fc565b90508060016000540114610311576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f537461746549647320617265206e6f742073657175656e7469616c000000000081525060200191505060405180910390fd5b600080815480929190600101919050555060006103418360018151811061033457fe5b602002602001015161066d565b905060606103628460028151811061035557fe5b6020026020010151610690565b905061036d8261071c565b156104c8576000624c4b409050606084836040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156103c75780820151818401526020810190506103ac565b50505050905090810190601f1680156103f45780820380516001836020036101000a031916815260200191505b5093505050506040516020818303038152906040527f26c53bea000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060008082516020840160008887f19650847f5a22725590b0a51c923940223f7458512164b1113359a735e86e7f27f44791ee88604051808215151515815260200191505060405180910390a250505b505050509392505050565b73fffffffffffffffffffffffffffffffffffffffe81565b60005481565b6104f961099c565b600060208301905060405180604001604052808451815260200182815250915050919050565b606061052a82610735565b61053357600080fd5b600061053e83610783565b905060608160405190808252806020026020018201604052801561057c57816020015b6105696109b6565b8152602001906001900390816105615790505b509050600061058e85602001516107f4565b8560200151019050600080600090505b848110156105ef576105af8361087d565b91506040518060400160405280838152602001848152508482815181106105d257fe5b60200260200101819052508183019250808060010191505061059e565b5082945050505050919050565b600080826000015111801561061657506021826000015111155b61061f57600080fd5b600061062e83602001516107f4565b9050600081846000015103905060008083866020015101905080519150602083101561066157826020036101000a820491505b81945050505050919050565b6000601582600001511461068057600080fd5b610689826105fc565b9050919050565b606060008260000151116106a357600080fd5b60006106b283602001516107f4565b905060008184600001510390506060816040519080825280601f01601f1916602001820160405280156106f45781602001600182028038833980820191505090505b5090506000816020019050610710848760200151018285610935565b81945050505050919050565b600080823b905060008163ffffffff1611915050919050565b6000808260000151141561074c576000905061077e565b60008083602001519050805160001a915060c060ff168260ff1610156107775760009250505061077e565b6001925050505b919050565b6000808260000151141561079a57600090506107ef565b600080905060006107ae84602001516107f4565b84602001510190506000846000015185602001510190505b808210156107e8576107d78261087d565b8201915082806001019350506107c6565b8293505050505b919050565b600080825160001a9050608060ff16811015610814576000915050610878565b60b860ff16811080610839575060c060ff168110158015610838575060f860ff1681105b5b15610848576001915050610878565b60c060ff168110156108685760018060b80360ff16820301915050610878565b60018060f80360ff168203019150505b919050565b6000806000835160001a9050608060ff1681101561089e576001915061092b565b60b860ff168110156108bb576001608060ff16820301915061092a565b60c060ff168110156108eb5760b78103600185019450806020036101000a85510460018201810193505050610929565b60f860ff1681101561090857600160c060ff168203019150610928565b60f78103600185019450806020036101000a855104600182018101935050505b5b5b5b8192505050919050565b600081141561094357610997565b5b602060ff1681106109735782518252602060ff1683019250602060ff1682019150602060ff1681039050610944565b6000600182602060ff16036101000a03905080198451168184511681811785525050505b505050565b604051806040016040528060008152602001600081525090565b60405180604001604052806000815260200160008152509056fea265627a7a723158208f1ea6fcf63d6911ac5dbfe340be1029614581802c6a750e7d6354b32ce6647c64736f6c63430005110032",
},
},
+ "62278656": map[string]interface{}{
+ // StateReceiver contract
+ "0000000000000000000000000000000000001001": map[string]interface{}{
+ "balance": "0x0",
+ "code": "0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c80635407ca671161008c578063abca220411610066578063abca2204146102fa578063d72a0b6714610302578063ee3a87f21461031f578063f165053614610342576100cf565b80635407ca67146102585780636757e5d914610260578063942af179146102f2576100cf565b806303112a17146100d457806319494a17146100f357806330e69fc31461017e578063318926f7146101985780633434735f146101bc57806351950cd9146101c4575b600080fd5b6100f1600480360360208110156100ea57600080fd5b503561034a565b005b61016a6004803603604081101561010957600080fd5b8135919081019060408101602082013564010000000081111561012b57600080fd5b82018360208201111561013d57600080fd5b8035906020019184600183028401116401000000008311171561015f57600080fd5b50909250905061060d565b604080519115158252519081900360200190f35b61018661093e565b60408051918252519081900360200190f35b6101a0610944565b604080516001600160a01b039092168252519081900360200190f35b6101a0610968565b6100f160048036036102808110156101db57600080fd5b61020082013590610220830135906001600160a01b036102408501351690840184610280810161026082013564010000000081111561021957600080fd5b82018360208201111561022b57600080fd5b8035906020019184600183028401116401000000008311171561024d57600080fd5b509092509050610973565b610186610c78565b61027d6004803603602081101561027657600080fd5b5035610c7e565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102b757818101518382015260200161029f565b50505050905090810190601f1680156102e45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610186610d19565b610186610d1f565b61016a6004803603602081101561031857600080fd5b5035610d25565b6100f16004803603604081101561033557600080fd5b5080359060200135610d3a565b610186610db0565b60008181526003602090815260409182902080548351601f60026000196101006001861615020190931692909204918201849004840281018401909452808452606093928301828280156103df5780601f106103b4576101008083540402835291602001916103df565b820191906000526020600020905b8154815290600101906020018083116103c257829003601f168201915b50505050509050805160001415610426576040805162461bcd60e51b815260206004820152600660248201526508599bdd5b9960d21b604482015290519081900360640190fd5b600082815260036020526040812061043d916112bb565b6000606082806020019051604081101561045657600080fd5b81516020830180516040519294929383019291908464010000000082111561047d57600080fd5b90830190602082018581111561049257600080fd5b82516401000000008111828201881017156104ac57600080fd5b82525081516020918201929091019080838360005b838110156104d95781810151838201526020016104c1565b50505050905090810190601f1680156105065780820380516001836020036101000a031916815260200191505b5060405250505091509150837f8797144948782adcede8e04bfa0bd8fd56941e0df7508bd02a629b477f7b073a60405160405180910390a2604080516313629df560e11b815260048101868152602482019283528351604483015283516001600160a01b038616936326c53bea938993879390929160640190602085019080838360005b838110156105a257818101518382015260200161058a565b50505050905090810190601f1680156105cf5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b1580156105ef57600080fd5b505af1158015610603573d6000803e3d6000fd5b5050505050505050565b6000336002600160a01b031461065f576040805162461bcd60e51b81526020600482015260126024820152714e6f742053797374656d204164646573732160701b604482015290519081900360640190fd5b60606106a86106a385858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610db592505050565b610ddb565b905060006106c9826000815181106106bc57fe5b6020026020010151610f14565b90508060005460010114610724576040805162461bcd60e51b815260206004820152601b60248201527f537461746549647320617265206e6f742073657175656e7469616c0000000000604482015290519081900360640190fd5b6000805460019081018255835161074c918591811061073f57fe5b6020026020010151610f62565b9050606061076d8460028151811061076057fe5b6020026020010151610f82565b905061077882610fff565b15610933576000624c4b409050606084836040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156107cf5781810151838201526020016107b7565b50505050905090810190601f1680156107fc5780820380516001836020036101000a031916815260200191505b5060408051601f198184030181529190526020810180516001600160e01b03166313629df560e11b1781528151919650600095508594509092509050828887f1604080518215158152905191985086917f5a22725590b0a51c923940223f7458512164b1113359a735e86e7f27f44791ee9181900360200190a28661093057838360405160200180836001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156108cc5781810151838201526020016108b4565b50505050905090810190601f1680156108f95780820380516001836020036101000a031916815260200191505b5060408051601f1981840301815291815260008b815260036020908152919020825161092e9750909550910192509050611302565b505b50505b505050509392505050565b60045481565b7f000000000000000000000000eb1cd9e44ab6bfe5a55ee96c468086e51b1b873a81565b6002600160a01b0381565b6201000085106109be576040805162461bcd60e51b81526020600482015260116024820152700d2dcecc2d8d2c840d8cac2cc92dcc8caf607b1b604482015290519081900360640190fd5b60045460058054600101908190551115610a05576040805162461bcd60e51b8152602060048201526003602482015262195b9960ea1b604482015290519081900360640190fd5b60015480610a42576040805162461bcd60e51b8152602060048201526005602482015264085c9bdbdd60da1b604482015290519081900360640190fd5b60008585858560405160200180858152602001846001600160a01b0316815260200180602001828103825284848281815260200192508082843760008184015260408051601f19601f909301831690940184810390920184525250805160209091012096507f28cf91ac064e179f8a42e4b7a20ba080187781da55fd4f3f18870b7a25bacb559550505050828414801592509050610aef575060008281526002602052604090205460ff16155b610b29576040805162461bcd60e51b815260206004808301919091526024820152631d5cd95960e21b604482015290519081900360640190fd5b60008281526002602052604090819020805460ff191660011790558051610200818101909252610b74918b9060109083908390808284376000920191909152508b915085905061100b565b8314610bb0576040805162461bcd60e51b815260206004820152600660248201526510b83937b7b360d11b604482015290519081900360640190fd5b60405187907f8797144948782adcede8e04bfa0bd8fd56941e0df7508bd02a629b477f7b073a90600090a2604080516313629df560e11b81526004810189815260248201928352604482018790526001600160a01b038916926326c53bea928b928a928a92606401848480828437600081840152601f19601f820116905080830192505050945050505050600060405180830381600087803b158015610c5557600080fd5b505af1158015610c69573d6000803e3d6000fd5b50505050505050505050505050565b60005481565b60036020908152600091825260409182902080548351601f600260001961010060018616150201909316929092049182018490048402810184019094528084529091830182828015610d115780601f10610ce657610100808354040283529160200191610d11565b820191906000526020600020905b815481529060010190602001808311610cf457829003601f168201915b505050505081565b60055481565b60015481565b60026020526000908152604090205460ff1681565b336001600160a01b037f000000000000000000000000eb1cd9e44ab6bfe5a55ee96c468086e51b1b873a1614610da5576040805162461bcd60e51b815260206004820152600b60248201526a10b937b7ba29b2ba3a32b960a91b604482015290519081900360640190fd5b600191909155600455565b601081565b610dbd611380565b5060408051808201909152815181526020828101908201525b919050565b6060610de6826110b6565b610def57600080fd5b6000610dfa836110f0565b905060608167ffffffffffffffff81118015610e1557600080fd5b50604051908082528060200260200182016040528015610e4f57816020015b610e3c611380565b815260200190600190039081610e345790505b5090506000610e618560200151611148565b60208601510190506000805b84811015610eb857610e7e836111ab565b9150604051806040016040528083815260200184815250848281518110610ea157fe5b602090810291909101015291810191600101610e6d565b5085516020870151830314610f0a576040805162461bcd60e51b81526020600482015260136024820152722bb937b733903a37ba30b6103632b733ba341760691b604482015290519081900360640190fd5b5090949350505050565b805160009015801590610f2957508151602110155b610f3257600080fd5b600080610f3e84611244565b815191935091506020821015610f5a5760208290036101000a90045b949350505050565b8051600090601514610f7357600080fd5b610f7c82610f14565b92915050565b8051606090610f9057600080fd5b600080610f9c84611244565b9150915060608167ffffffffffffffff81118015610fb957600080fd5b506040519080825280601f01601f191660200182016040528015610fe4576020820181803683370190505b50905060208101610ff684828561126a565b50949350505050565b3b63ffffffff16151590565b600081815b6010811015610ff657600185821c8116141561106c5785816010811061103257fe5b60200201518260405160200180838152602001828152602001925050506040516020818303038152906040528051906020012091506110ae565b8186826010811061107957fe5b602002015160405160200180838152602001828152602001925050506040516020818303038152906040528051906020012091505b600101611010565b80516000906110c757506000610dd6565b6020820151805160001a9060c08210156110e657600092505050610dd6565b5060019392505050565b805160009061110157506000610dd6565b6000806111118460200151611148565b602085015185519181019250015b8082101561113f57611130826111ab565b6001909301929091019061111f565b50909392505050565b8051600090811a6080811015611162576000915050610dd6565b60b881108061117d575060c0811080159061117d575060f881105b1561118c576001915050610dd6565b60c08110156111a05760b519019050610dd6565b60f519019050610dd6565b80516000908190811a60808110156111c6576001915061123d565b60b88110156111db57607e198101915061123d565b60c08110156112085760b78103600185019450806020036101000a8551046001820181019350505061123d565b60f881101561121d5760be198101915061123d565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b60008060006112568460200151611148565b602085015194519481019594039392505050565b80611274576112b6565b5b60208110611294578251825260209283019290910190601f1901611275565b80156112b6578251825160208390036101000a60001901801990921691161782525b505050565b50805460018160011615610100020316600290046000825580601f106112e157506112ff565b601f0160209004906000526020600020908101906112ff919061139a565b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061134357805160ff1916838001178555611370565b82800160010185558215611370579182015b82811115611370578251825591602001919060010190611355565b5061137c92915061139a565b5090565b604051806040016040528060008152602001600081525090565b5b8082111561137c576000815560010161139b56fea164736f6c634300060c000a",
+ },
+ // MRC20 contract
+ "0000000000000000000000000000000000001010": map[string]interface{}{
+ "balance": "0x0",
+ "code": "0x6080604052600436106101b75760003560e01c80638da5cb5b116100ec578063b789543c1161008a578063e614d0d611610064578063e614d0d614610695578063ed9ef524146106aa578063f2fde38b146106dd578063fc0c546a14610710576101b7565b8063b789543c14610626578063cc79f97b1461066b578063e306f77914610680576101b7565b806395d89b41116100c657806395d89b41146105a6578063a9059cbb146105bb578063abceeba2146105e7578063acd06cb3146105fc576101b7565b80638da5cb5b146105535780638f32d59b146105685780639025e64c14610591576101b7565b806347e7ef241161015957806370a082311161013357806370a082311461043c578063715018a61461046f578063771282f61461048457806377d32e9414610499576101b7565b806347e7ef24146103b3578063485cc955146103ec57806360f96a8f14610427576101b7565b806319d27d9c1161019557806319d27d9c146102a25780632e1a7d4d14610356578063313ce5671461037357806342fc47fb1461039e576101b7565b806306fdde03146101bc5780631499c5921461024657806318160ddd1461027b575b600080fd5b3480156101c857600080fd5b506101d1610725565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561020b5781810151838201526020016101f3565b50505050905090810190601f1680156102385780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025257600080fd5b506102796004803603602081101561026957600080fd5b50356001600160a01b031661075c565b005b34801561028757600080fd5b5061029061079c565b60408051918252519081900360200190f35b3480156102ae57600080fd5b5061033a600480360360a08110156102c557600080fd5b8101906020810181356401000000008111156102e057600080fd5b8201836020820111156102f257600080fd5b8035906020019184600183028401116401000000008311171561031457600080fd5b9193509150803590602081013590604081013590606001356001600160a01b03166107ac565b604080516001600160a01b039092168252519081900360200190f35b6102796004803603602081101561036c57600080fd5b50356107ee565b34801561037f57600080fd5b506103886108c6565b6040805160ff9092168252519081900360200190f35b3480156103aa57600080fd5b5061033a6108cb565b3480156103bf57600080fd5b50610279600480360360408110156103d657600080fd5b506001600160a01b0381351690602001356108da565b3480156103f857600080fd5b506102796004803603604081101561040f57600080fd5b506001600160a01b03813581169160200135166109a8565b34801561043357600080fd5b5061033a610a21565b34801561044857600080fd5b506102906004803603602081101561045f57600080fd5b50356001600160a01b0316610a30565b34801561047b57600080fd5b50610279610a3d565b34801561049057600080fd5b50610290610a98565b3480156104a557600080fd5b5061033a600480360360408110156104bc57600080fd5b813591908101906040810160208201356401000000008111156104de57600080fd5b8201836020820111156104f057600080fd5b8035906020019184600183028401116401000000008311171561051257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610a9e945050505050565b34801561055f57600080fd5b5061033a610bc2565b34801561057457600080fd5b5061057d610bd1565b604080519115158252519081900360200190f35b34801561059d57600080fd5b506101d1610be2565b3480156105b257600080fd5b506101d1610c00565b61057d600480360360408110156105d157600080fd5b506001600160a01b038135169060200135610c1d565b3480156105f357600080fd5b50610290610c40565b34801561060857600080fd5b5061057d6004803603602081101561061f57600080fd5b5035610cc9565b34801561063257600080fd5b506102906004803603608081101561064957600080fd5b506001600160a01b038135169060208101359060408101359060600135610cde565b34801561067757600080fd5b50610290610cfd565b34801561068c57600080fd5b50610290610d03565b3480156106a157600080fd5b50610290610d09565b3480156106b657600080fd5b50610279600480360360208110156106cd57600080fd5b50356001600160a01b0316610d53565b3480156106e957600080fd5b506102796004803603602081101561070057600080fd5b50356001600160a01b0316610e05565b34801561071c57600080fd5b5061033a610e22565b60408051808201909152601781527f506f6c79676f6e2045636f73797374656d20546f6b656e000000000000000000602082015290565b6040805162461bcd60e51b815260206004820152601060248201526f44697361626c6564206665617475726560801b604482015290519081900360640190fd5b6b204fce5e3e2502611000000090565b6040805162461bcd60e51b815260206004820152601060248201526f44697361626c6564206665617475726560801b6044820152905160009181900360640190fd5b3360006107fa82610a30565b600654909150610810908463ffffffff610e3116565b600655821580159061082157508234145b610868576040805162461bcd60e51b8152602060048201526013602482015272125b9cdd59999a58da595b9d08185b5bdd5b9d606a1b604482015290519081900360640190fd5b6002546001600160a01b0380841691167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f85846108a487610a30565b60408051938452602084019290925282820152519081900360600190a3505050565b601290565b6003546001600160a01b031681565b6108e2610bd1565b6108eb57600080fd5b60008111801561090357506001600160a01b03821615155b61093e5760405162461bcd60e51b815260040180806020018281038252602381526020018061138d6023913960400191505060405180910390fd5b600061094983610a30565b60065490915061095f908363ffffffff610e4616565b60065561096c8383610e58565b6002546001600160a01b0380851691167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f684846108a488610a30565b60075460ff16156109ea5760405162461bcd60e51b815260040180806020018281038252602381526020018061136a6023913960400191505060405180910390fd5b6007805460ff19166001179055600280546001600160a01b0383166001600160a01b0319909116179055610a1d82610f17565b5050565b6004546001600160a01b031681565b6001600160a01b03163190565b610a45610bd1565b610a4e57600080fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b60065481565b6000806000808451604114610ab95760009350505050610bbc565b50505060208201516040830151604184015160ff16601b811015610adb57601b015b8060ff16601b14158015610af357508060ff16601c14155b15610b045760009350505050610bbc565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa158015610b5b573d6000803e3d6000fd5b5050604051601f1901519450506001600160a01b038416610bb8576040805162461bcd60e51b815260206004820152601260248201527122b93937b91034b71032b1b932b1b7bb32b960711b604482015290519081900360640190fd5b5050505b92915050565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b604051806040016040528060028152602001613a9960f01b81525081565b6040805180820190915260038152621413d360ea1b602082015290565b6000813414610c2e57506000610bbc565b610c39338484610f85565b9392505050565b6040518060800160405280605b8152602001611434605b91396040516020018082805190602001908083835b60208310610c8b5780518252601f199092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b60056020526000908152604090205460ff1681565b6000610cf4610cef868686866111d2565b61128b565b95945050505050565b613a9981565b60015481565b6040518060800160405280605281526020016113b06052913960405160200180828051906020019080838360208310610c8b5780518252601f199092019160209182019101610c6c565b610d5b610bd1565b610d6457600080fd5b6001600160a01b038116610da95760405162461bcd60e51b81526004018080602001828103825260328152602001806114026032913960400191505060405180910390fd5b6003546040516001600160a01b038084169216907f1f9f3556dd336016cdf20adaead7d5c73665dba664b60e8c17e9a4eb91ce1d3990600090a3600380546001600160a01b0319166001600160a01b0392909216919091179055565b610e0d610bd1565b610e1657600080fd5b610e1f81610f17565b50565b6002546001600160a01b031681565b600082821115610e4057600080fd5b50900390565b600082820183811015610c3957600080fd5b60085415610e9a576040805162461bcd60e51b815260206004820152600a6024820152697265656e7472616e637960b01b604482015290519081900360640190fd5b6001600855604051611388906000906060906001600160a01b038616908490869085818181858888f193505050503d8060008114610ef4576040519150601f19603f3d011682016040523d82523d6000602084013e610ef9565b606091505b509150915081610f0b57805160208201fd5b50506000600855505050565b6001600160a01b038116610f2a57600080fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b604080516370a0823160e01b81526001600160a01b03851660048201529051600091829130916370a08231916024808301926020929190829003018186803b158015610fd057600080fd5b505afa158015610fe4573d6000803e3d6000fd5b505050506040513d6020811015610ffa57600080fd5b5051604080516370a0823160e01b81526001600160a01b0387166004820152905191925060009130916370a08231916024808301926020929190829003018186803b15801561104857600080fd5b505afa15801561105c573d6000803e3d6000fd5b505050506040513d602081101561107257600080fd5b50519050611081868686611299565b600254604080516370a0823160e01b81526001600160a01b03898116600483018190529251818a1694909116917fe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c49189918891889130916370a0823191602480820192602092909190829003018186803b1580156110fe57600080fd5b505afa158015611112573d6000803e3d6000fd5b505050506040513d602081101561112857600080fd5b5051604080516370a0823160e01b81526001600160a01b038f166004820152905130916370a08231916024808301926020929190829003018186803b15801561117057600080fd5b505afa158015611184573d6000803e3d6000fd5b505050506040513d602081101561119a57600080fd5b50516040805195865260208601949094528484019290925260608401526080830152519081900360a00190a450600195945050505050565b6000806040518060800160405280605b8152602001611434605b91396040516020018082805190602001908083835b602083106112205780518252601f199092019160209182019101611201565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f1901835280855282519282019290922082526001600160a01b039b909b169a81019a909a5250880196909652505050606084019190915260808301525060a0902090565b6000610bbc82600154611347565b6001600160a01b0382163014156112ed576040805162461bcd60e51b8152602060048201526013602482015272063616e27742073656e6420746f204d5243323606c1b604482015290519081900360640190fd5b6112f78282610e58565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b60405161190160f01b815260028101919091526022810191909152604290209056fe54686520636f6e747261637420697320616c726561647920696e697469616c697a6564496e73756666696369656e7420616d6f756e74206f7220696e76616c69642075736572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e7472616374294368696c6420746f6b656e3a206e6577206368696c64206164647265737320697320746865207a65726f2061646472657373546f6b656e5472616e736665724f726465722861646472657373207370656e6465722c75696e7432353620746f6b656e49644f72416d6f756e742c6279746573333220646174612c75696e743235362065787069726174696f6e29a265627a7a723158205f23be7574e70cfc01d0cfd6803b871f92465e9ae4a10fe95ed31ccb810bda3e64736f6c63430005110032",
+ },
+ // WMATIC contract
+ "0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270": map[string]interface{}{
+ "balance": "0x0",
+ "code": "0x6080604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b9578063095ea7b31461014957806318160ddd146101ae57806323b872dd146101d95780632e1a7d4d1461025e578063313ce5671461028b57806370a08231146102bc57806395d89b4114610313578063a9059cbb146103a3578063d0e30db014610408578063dd62ed3e14610412575b6100b7610489565b005b3480156100c557600080fd5b506100ce610526565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561010e5780820151818401526020810190506100f3565b50505050905090810190601f16801561013b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015557600080fd5b50610194600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610563565b604051808215151515815260200191505060405180910390f35b3480156101ba57600080fd5b506101c3610655565b6040518082815260200191505060405180910390f35b3480156101e557600080fd5b50610244600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610674565b604051808215151515815260200191505060405180910390f35b34801561026a57600080fd5b50610289600480360381019080803590602001909291905050506109c1565b005b34801561029757600080fd5b506102a0610af4565b604051808260ff1660ff16815260200191505060405180910390f35b3480156102c857600080fd5b506102fd600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610afd565b6040518082815260200191505060405180910390f35b34801561031f57600080fd5b50610328610b15565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036857808201518184015260208101905061034d565b50505050905090810190601f1680156103955780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103af57600080fd5b506103ee600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610b52565b604051808215151515815260200191505060405180910390f35b610410610489565b005b34801561041e57600080fd5b50610473600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b67565b6040518082815260200191505060405180910390f35b34600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055503373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a2565b60606040805190810160405280601f81526020017f5772617070656420506f6c79676f6e2045636f73797374656d20546f6b656e00815250905090565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60003073ffffffffffffffffffffffffffffffffffffffff1631905090565b600081600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156106c457600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415801561079c57507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414155b156108b75781600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561082c57600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b81600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a0f57600080fd5b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610aa2573d6000803e3d6000fd5b503373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65826040518082815260200191505060405180910390a250565b60006012905090565b60036020528060005260406000206000915090505481565b60606040805190810160405280600481526020017f57504f4c00000000000000000000000000000000000000000000000000000000815250905090565b6000610b5f338484610674565b905092915050565b60046020528160005260406000206020528060005260406000206000915091505054815600a165627a7a723058208d70d8aa2d752533105b5ccda8206dae8b0c1de765f89fb1f0c5727cbac1b40d0029",
+ },
+ },
},
},
}
@@ -490,6 +557,36 @@ var (
BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"}},
}
+ // MergedTestChainConfig contains every protocol change (EIPs) introduced
+ // and accepted by the Ethereum core developers for testing purposes.
+ MergedTestChainConfig = &ChainConfig{
+ ChainID: big.NewInt(1),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: nil,
+ DAOForkSupport: false,
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ MuirGlacierBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ ArrowGlacierBlock: big.NewInt(0),
+ GrayGlacierBlock: big.NewInt(0),
+ MergeNetsplitBlock: big.NewInt(0),
+ TerminalTotalDifficulty: big.NewInt(0),
+ TerminalTotalDifficultyPassed: true,
+ Ethash: new(EthashConfig),
+ Clique: nil,
+ Bor: &BorConfig{
+ Sprint: map[string]uint64{
+ "0": 4},
+ BurntContract: map[string]string{"0": "0x000000000000000000000000000000000000dead"}},
+ }
+
// NonActivatedConfig defines the chain configuration without activating
// any protocol change (EIPs).
NonActivatedConfig = &ChainConfig{
@@ -575,6 +672,8 @@ type ChainConfig struct {
// TerminalTotalDifficultyPassed is a flag specifying that the network already
// passed the terminal total difficulty. Its purpose is to disable legacy sync
// even without having seen the TTD locally (safer long term).
+ //
+ // TODO(karalabe): Drop this field eventually (always assuming PoS mode)
TerminalTotalDifficultyPassed bool `json:"terminalTotalDifficultyPassed,omitempty"`
// Various consensus engines
@@ -588,7 +687,7 @@ type ChainConfig struct {
type EthashConfig struct{}
// String implements the stringer interface, returning the consensus engine details.
-func (c *EthashConfig) String() string {
+func (c EthashConfig) String() string {
return "ethash"
}
@@ -599,8 +698,8 @@ type CliqueConfig struct {
}
// String implements the stringer interface, returning the consensus engine details.
-func (c *CliqueConfig) String() string {
- return "clique"
+func (c CliqueConfig) String() string {
+ return fmt.Sprintf("clique(period: %d, epoch: %d)", c.Period, c.Epoch)
}
// BorConfig is the consensus engine configs for Matic bor based sealing.
@@ -618,10 +717,11 @@ type BorConfig struct {
DelhiBlock *big.Int `json:"delhiBlock"` // Delhi switch block (nil = no fork, 0 = already on delhi)
IndoreBlock *big.Int `json:"indoreBlock"` // Indore switch block (nil = no fork, 0 = already on indore)
StateSyncConfirmationDelay map[string]uint64 `json:"stateSyncConfirmationDelay"` // StateSync Confirmation Delay, in seconds, to calculate `to`
+ AhmedabadBlock *big.Int `json:"ahmedabadBlock"` // Ahmedabad switch block (nil = no fork, 0 = already on ahmedabad)
}
// String implements the stringer interface, returning the consensus engine details.
-func (b *BorConfig) String() string {
+func (c *BorConfig) String() string {
return "bor"
}
@@ -657,6 +757,10 @@ func (c *BorConfig) CalculateStateSyncDelay(number uint64) uint64 {
return borKeyValueConfigHelper(c.StateSyncConfirmationDelay, number)
}
+func (c *BorConfig) IsAhmedabad(number *big.Int) bool {
+ return isBlockForked(c.AhmedabadBlock, number)
+}
+
// // TODO: modify this function once the block number is finalized
// func (c *BorConfig) IsNapoli(number *big.Int) bool {
// if c.NapoliBlock != nil {
@@ -910,6 +1014,11 @@ func (c *ChainConfig) IsVerkle(num *big.Int) bool {
return c.IsLondon(num) && isBlockForked(c.VerkleBlock, num)
}
+// IsEIP4762 returns whether eip 4762 has been activated at given block.
+func (c *ChainConfig) IsEIP4762(num *big.Int, time uint64) bool {
+ return c.IsVerkle(num)
+}
+
// CheckCompatible checks whether scheduled fork transitions have been imported
// with a mismatching chain configuration.
func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64, time uint64) *ConfigCompatError {
@@ -978,7 +1087,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
lastFork.name, cur.name, cur.block)
} else {
return fmt.Errorf("unsupported fork ordering: %v not enabled, but %v enabled at timestamp %v",
- lastFork.name, cur.name, cur.timestamp)
+ lastFork.name, cur.name, *cur.timestamp)
}
// Fork (whether defined by block or timestamp) must follow the fork definition sequence
@@ -988,7 +1097,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
lastFork.name, lastFork.block, cur.name, cur.block)
} else if lastFork.timestamp != nil && *lastFork.timestamp > *cur.timestamp {
return fmt.Errorf("unsupported fork ordering: %v enabled at timestamp %v, but %v enabled at timestamp %v",
- lastFork.name, lastFork.timestamp, cur.name, cur.timestamp)
+ lastFork.name, *lastFork.timestamp, cur.name, *cur.timestamp)
}
// Timestamp based forks can follow block based ones, but not the other way around
@@ -1107,6 +1216,23 @@ func (c *ChainConfig) ElasticityMultiplier() uint64 {
return DefaultElasticityMultiplier
}
+// LatestFork returns the latest time-based fork that would be active for the given time.
+func (c *ChainConfig) LatestFork(time uint64) forks.Fork {
+ // Assume last non-time-based fork has passed.
+ london := c.LondonBlock
+
+ switch {
+ case c.IsPrague(london):
+ return forks.Prague
+ case c.IsCancun(london):
+ return forks.Cancun
+ case c.IsShanghai(london):
+ return forks.Shanghai
+ default:
+ return forks.Paris
+ }
+}
+
// isForkBlockIncompatible returns true if a fork scheduled at block s1 cannot be
// rescheduled to block s2 because head is already past the fork.
func isForkBlockIncompatible(s1, s2, head *big.Int) bool {
@@ -1179,12 +1305,43 @@ func newBlockCompatError(what string, storedblock, newblock *big.Int) *ConfigCom
return err
}
+// nolint
+func newTimestampCompatError(what string, storedtime, newtime *uint64) *ConfigCompatError {
+ var rew *uint64
+ switch {
+ case storedtime == nil:
+ rew = newtime
+ case newtime == nil || *storedtime < *newtime:
+ rew = storedtime
+ default:
+ rew = newtime
+ }
+ err := &ConfigCompatError{
+ What: what,
+ StoredTime: storedtime,
+ NewTime: newtime,
+ RewindToTime: 0,
+ }
+ if rew != nil && *rew != 0 {
+ err.RewindToTime = *rew - 1
+ }
+
+ return err
+}
+
func (err *ConfigCompatError) Error() string {
if err.StoredBlock != nil {
return fmt.Sprintf("mismatching %s in database (have block %d, want block %d, rewindto block %d)", err.What, err.StoredBlock, err.NewBlock, err.RewindToBlock)
}
- return fmt.Sprintf("mismatching %s in database (have timestamp %d, want timestamp %d, rewindto timestamp %d)", err.What, err.StoredTime, err.NewTime, err.RewindToTime)
+ if err.StoredTime == nil && err.NewTime == nil {
+ return ""
+ } else if err.StoredTime == nil && err.NewTime != nil {
+ return fmt.Sprintf("mismatching %s in database (have timestamp nil, want timestamp %d, rewindto timestamp %d)", err.What, *err.NewTime, err.RewindToTime)
+ } else if err.StoredTime != nil && err.NewTime == nil {
+ return fmt.Sprintf("mismatching %s in database (have timestamp %d, want timestamp nil, rewindto timestamp %d)", err.What, *err.StoredTime, err.RewindToTime)
+ }
+ return fmt.Sprintf("mismatching %s in database (have timestamp %d, want timestamp %d, rewindto timestamp %d)", err.What, *err.StoredTime, *err.NewTime, err.RewindToTime)
}
// Rules wraps ChainConfig and is merely syntactic sugar or can be used for functions
@@ -1195,6 +1352,7 @@ func (err *ConfigCompatError) Error() string {
type Rules struct {
ChainID *big.Int
IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool
+ IsEIP2929, IsEIP4762 bool
IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool
IsBerlin, IsLondon bool
IsMerge, IsShanghai, IsCancun, IsPrague bool
@@ -1207,7 +1365,9 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules
if chainID == nil {
chainID = new(big.Int)
}
-
+ // disallow setting Merge out of order
+ isMerge = isMerge && c.IsLondon(num)
+ isVerkle := isMerge && c.IsVerkle(num)
return Rules{
ChainID: new(big.Int).Set(chainID),
IsHomestead: c.IsHomestead(num),
@@ -1219,10 +1379,12 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules
IsPetersburg: c.IsPetersburg(num),
IsIstanbul: c.IsIstanbul(num),
IsBerlin: c.IsBerlin(num),
+ IsEIP2929: c.IsBerlin(num) && !isVerkle,
IsLondon: c.IsLondon(num),
IsMerge: isMerge,
IsShanghai: c.IsShanghai(num),
IsCancun: c.IsCancun(num),
IsPrague: c.IsPrague(num),
+ IsVerkle: c.IsVerkle(num),
}
}
diff --git a/crypto/bls12381/arithmetic_x86_noadx.go b/params/forks/forks.go
similarity index 66%
rename from crypto/bls12381/arithmetic_x86_noadx.go
rename to params/forks/forks.go
index 679b30ec8c..4f50ff5aed 100644
--- a/crypto/bls12381/arithmetic_x86_noadx.go
+++ b/params/forks/forks.go
@@ -1,4 +1,4 @@
-// Copyright 2020 The go-ethereum Authors
+// Copyright 2023 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
@@ -14,12 +14,29 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-//go:build amd64 && blsasm
-// +build amd64,blsasm
+package forks
-package bls12381
+// Fork is a numerical identifier of specific network upgrades (forks).
+type Fork int
-// enableADX is true if the ADX/BMI2 instruction set was requested for the BLS
-// implementation. The system may still fall back to plain ASM if the necessary
-// instructions are unavailable on the CPU.
-const enableADX = false
+const (
+ Frontier = iota
+ FrontierThawing
+ Homestead
+ DAO
+ TangerineWhistle
+ SpuriousDragon
+ Byzantium
+ Constantinople
+ Petersburg
+ Istanbul
+ MuirGlacier
+ Berlin
+ London
+ ArrowGlacier
+ GrayGlacier
+ Paris
+ Shanghai
+ Cancun
+ Prague
+)
diff --git a/params/protocol_params.go b/params/protocol_params.go
index 031e3af0be..ac973a024b 100644
--- a/params/protocol_params.go
+++ b/params/protocol_params.go
@@ -86,6 +86,7 @@ const (
LogTopicGas uint64 = 375 // Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas.
CreateGas uint64 = 32000 // Once per CREATE operation & contract-creation transaction.
Create2Gas uint64 = 32000 // Once per CREATE2 operation
+ CreateNGasEip4762 uint64 = 1000 // Once per CREATEn operations post-verkle
SelfdestructRefundGas uint64 = 24000 // Refunded following a selfdestruct operation.
MemoryGas uint64 = 3 // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL.
@@ -133,8 +134,9 @@ const (
DefaultBaseFeeChangeDenominator = 8 // Bounds the amount the base fee can change between blocks.
DefaultElasticityMultiplier = 2 // Bounds the maximum gas limit an EIP-1559 block may have.
- MaxCodeSize = 24576 // Maximum bytecode to permit for a contract
- MaxInitCodeSize = 2 * MaxCodeSize // Maximum initcode to permit in a creation transaction and create instructions
+ MaxCodeSize = 24576 // Maximum bytecode to permit for a contract
+ MaxCodeSizePostAhmedabad = 32768 // Maximum bytecode to permit for a contract post Ahmedabad hard fork (bor / polygon pos) (32KB)
+ MaxInitCodeSize = 2 * MaxCodeSize // Maximum initcode to permit in a creation transaction and create instructions
// Precompiled contract gas prices
@@ -155,14 +157,14 @@ const (
Bn256PairingPerPointGasByzantium uint64 = 80000 // Byzantium per-point price for an elliptic curve pairing check
Bn256PairingPerPointGasIstanbul uint64 = 34000 // Per-point price for an elliptic curve pairing check
- Bls12381G1AddGas uint64 = 600 // Price for BLS12-381 elliptic curve G1 point addition
- Bls12381G1MulGas uint64 = 12000 // Price for BLS12-381 elliptic curve G1 point scalar multiplication
- Bls12381G2AddGas uint64 = 4500 // Price for BLS12-381 elliptic curve G2 point addition
- Bls12381G2MulGas uint64 = 55000 // Price for BLS12-381 elliptic curve G2 point scalar multiplication
- Bls12381PairingBaseGas uint64 = 115000 // Base gas price for BLS12-381 elliptic curve pairing check
- Bls12381PairingPerPairGas uint64 = 23000 // Per-point pair gas price for BLS12-381 elliptic curve pairing check
- Bls12381MapG1Gas uint64 = 5500 // Gas price for BLS12-381 mapping field element to G1 operation
- Bls12381MapG2Gas uint64 = 110000 // Gas price for BLS12-381 mapping field element to G2 operation
+ Bls12381G1AddGas uint64 = 500 // Price for BLS12-381 elliptic curve G1 point addition
+ Bls12381G1MulGas uint64 = 12000 // Price for BLS12-381 elliptic curve G1 point scalar multiplication
+ Bls12381G2AddGas uint64 = 800 // Price for BLS12-381 elliptic curve G2 point addition
+ Bls12381G2MulGas uint64 = 45000 // Price for BLS12-381 elliptic curve G2 point scalar multiplication
+ Bls12381PairingBaseGas uint64 = 65000 // Base gas price for BLS12-381 elliptic curve pairing check
+ Bls12381PairingPerPairGas uint64 = 43000 // Per-point pair gas price for BLS12-381 elliptic curve pairing check
+ Bls12381MapG1Gas uint64 = 5500 // Gas price for BLS12-381 mapping field element to G1 operation
+ Bls12381MapG2Gas uint64 = 75000 // Gas price for BLS12-381 mapping field element to G2 operation
P256VerifyGas uint64 = 3450 // secp256r1 elliptic curve signature verifier gas price
@@ -173,7 +175,6 @@ const (
BlobTxBytesPerFieldElement = 32 // Size in bytes of a field element
BlobTxFieldElementsPerBlob = 4096 // Number of field elements stored in a single data blob
- BlobTxHashVersion = 0x01 // Version byte of the commitment hash
BlobTxBlobGasPerBlob = 1 << 17 // Gas consumption of a single data blob (== blob byte size)
BlobTxMinBlobGasprice = 1 // Minimum gas price for data blobs
BlobTxBlobGaspriceUpdateFraction = 3338477 // Controls the maximum rate of change for blob gas price
@@ -183,13 +184,13 @@ const (
MaxBlobGasPerBlock = 6 * BlobTxBlobGasPerBlob // Maximum consumable blob gas for data blobs per block
// BorDefaultMinerGasPrice defines the minimum gas price for bor validators to mine a transaction.
- BorDefaultMinerGasPrice = 30 * GWei
+ BorDefaultMinerGasPrice = 25 * GWei
// BorDefaultTxPoolPriceLimit defines the minimum gas price limit for bor to enforce txs acceptance into the pool.
- BorDefaultTxPoolPriceLimit = 30 * GWei
+ BorDefaultTxPoolPriceLimit = 25 * GWei
// BorDefaultGpoIgnorePrice defines the minimum gas price below which bor gpo will ignore transactions.
- BorDefaultGpoIgnorePrice = 30 * GWei
+ BorDefaultGpoIgnorePrice = 25 * GWei
)
// Gas discount table for BLS12-381 G1 and G2 multi exponentiation operations
@@ -201,10 +202,14 @@ var (
MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be.
DurationLimit = big.NewInt(13) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not.
- // BeaconRootsStorageAddress is the address where historical beacon roots are stored as per EIP-4788
- BeaconRootsStorageAddress = common.HexToAddress("0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02")
+ // BeaconRootsAddress is the address where historical beacon roots are stored as per EIP-4788
+ BeaconRootsAddress = common.HexToAddress("0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02")
+
+ // BeaconRootsCode is the code where historical beacon roots are stored as per EIP-4788
+ BeaconRootsCode = common.FromHex("3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500")
+
// SystemAddress is where the system-transaction is sent from as per EIP-4788
- SystemAddress common.Address = common.HexToAddress("0xfffffffffffffffffffffffffffffffffffffffe")
+ SystemAddress = common.HexToAddress("0xfffffffffffffffffffffffffffffffffffffffe")
)
func BaseFeeChangeDenominator(borConfig *BorConfig, number *big.Int) uint64 {
diff --git a/crypto/bls12381/arithmetic_x86_adx.go b/params/verkle_params.go
similarity index 55%
rename from crypto/bls12381/arithmetic_x86_adx.go
rename to params/verkle_params.go
index a40c7384eb..93d4f7cd64 100644
--- a/crypto/bls12381/arithmetic_x86_adx.go
+++ b/params/verkle_params.go
@@ -1,4 +1,4 @@
-// Copyright 2020 The go-ethereum Authors
+// Copyright 2023 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
@@ -14,12 +14,23 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-//go:build amd64 && blsadx
-// +build amd64,blsadx
+package params
-package bls12381
+// Verkle tree EIP: costs associated to witness accesses
+var (
+ WitnessBranchReadCost uint64 = 1900
+ WitnessChunkReadCost uint64 = 200
+ WitnessBranchWriteCost uint64 = 3000
+ WitnessChunkWriteCost uint64 = 500
+ WitnessChunkFillCost uint64 = 6200
+)
-// enableADX is true if the ADX/BMI2 instruction set was requested for the BLS
-// implementation. The system may still fall back to plain ASM if the necessary
-// instructions are unavailable on the CPU.
-const enableADX = true
+// ClearVerkleWitnessCosts sets all witness costs to 0, which is necessary
+// for historical block replay simulations.
+func ClearVerkleWitnessCosts() {
+ WitnessBranchReadCost = 0
+ WitnessChunkReadCost = 0
+ WitnessBranchWriteCost = 0
+ WitnessChunkWriteCost = 0
+ WitnessChunkFillCost = 0
+}
diff --git a/params/version.go b/params/version.go
index 7b836091d3..a6a5e20046 100644
--- a/params/version.go
+++ b/params/version.go
@@ -22,8 +22,8 @@ import (
const (
VersionMajor = 1 // Major version component of the current release
- VersionMinor = 3 // Minor version component of the current release
- VersionPatch = 3 // Patch version component of the current release
+ VersionMinor = 5 // Minor version component of the current release
+ VersionPatch = 2 // Patch version component of the current release
VersionMeta = "" // Version metadata to append to the version string
)
diff --git a/rlp/decode.go b/rlp/decode.go
index dfe488cde0..262d60789a 100644
--- a/rlp/decode.go
+++ b/rlp/decode.go
@@ -166,17 +166,17 @@ func makeDecoder(typ reflect.Type, tags rlpstruct.Tags) (dec decoder, err error)
switch {
case typ == rawValueType:
return decodeRawValue, nil
- case typ.AssignableTo(reflect.PtrTo(bigInt)):
+ case typ.AssignableTo(reflect.PointerTo(bigInt)):
return decodeBigInt, nil
case typ.AssignableTo(bigInt):
return decodeBigIntNoPtr, nil
- case typ == reflect.PtrTo(u256Int):
+ case typ == reflect.PointerTo(u256Int):
return decodeU256, nil
case typ == u256Int:
return decodeU256NoPtr, nil
case kind == reflect.Ptr:
return makePtrDecoder(typ, tags)
- case reflect.PtrTo(typ).Implements(decoderInterface):
+ case reflect.PointerTo(typ).Implements(decoderInterface):
return decodeDecoder, nil
case isUint(kind):
return decodeUint, nil
@@ -281,7 +281,7 @@ func decodeU256(s *Stream, val reflect.Value) error {
func makeListDecoder(typ reflect.Type, tag rlpstruct.Tags) (decoder, error) {
etype := typ.Elem()
- if etype.Kind() == reflect.Uint8 && !reflect.PtrTo(etype).Implements(decoderInterface) {
+ if etype.Kind() == reflect.Uint8 && !reflect.PointerTo(etype).Implements(decoderInterface) {
if typ.Kind() == reflect.Array {
return decodeByteArray, nil
}
@@ -525,7 +525,7 @@ func makeSimplePtrDecoder(etype reflect.Type, etypeinfo *typeinfo) decoder {
//
// This decoder is used for pointer-typed struct fields with struct tag "nil".
func makeNilPtrDecoder(etype reflect.Type, etypeinfo *typeinfo, ts rlpstruct.Tags) decoder {
- typ := reflect.PtrTo(etype)
+ typ := reflect.PointerTo(etype)
nilPtr := reflect.Zero(typ)
// Determine the value kind that results in nil pointer.
@@ -1209,10 +1209,7 @@ func (s *Stream) readUint(size byte) (uint64, error) {
return uint64(b), err
default:
buffer := s.uintbuf[:8]
- for i := range buffer {
- buffer[i] = 0
- }
-
+ clear(buffer)
start := int(8 - size)
if err := s.readFull(buffer[start:]); err != nil {
return 0, err
diff --git a/rlp/encode.go b/rlp/encode.go
index b435b9c928..43e0ae2f39 100644
--- a/rlp/encode.go
+++ b/rlp/encode.go
@@ -149,17 +149,17 @@ func makeWriter(typ reflect.Type, ts rlpstruct.Tags) (writer, error) {
switch {
case typ == rawValueType:
return writeRawValue, nil
- case typ.AssignableTo(reflect.PtrTo(bigInt)):
+ case typ.AssignableTo(reflect.PointerTo(bigInt)):
return writeBigIntPtr, nil
case typ.AssignableTo(bigInt):
return writeBigIntNoPtr, nil
- case typ == reflect.PtrTo(u256Int):
+ case typ == reflect.PointerTo(u256Int):
return writeU256IntPtr, nil
case typ == u256Int:
return writeU256IntNoPtr, nil
case kind == reflect.Ptr:
return makePtrWriter(typ, ts)
- case reflect.PtrTo(typ).Implements(encoderInterface):
+ case reflect.PointerTo(typ).Implements(encoderInterface):
return makeEncoderWriter(typ), nil
case isUint(kind):
return writeUint, nil
diff --git a/rlp/iterator.go b/rlp/iterator.go
index 0d144f0d4d..0e1a325236 100644
--- a/rlp/iterator.go
+++ b/rlp/iterator.go
@@ -23,7 +23,6 @@ type listIterator struct {
}
// NewListIterator creates an iterator for the (list) represented by data
-// TODO: Consider removing this implementation, as it is no longer used.
func NewListIterator(data RawValue) (*listIterator, error) {
k, t, c, err := readKind(data)
if err != nil {
diff --git a/rlp/raw.go b/rlp/raw.go
index a671892e69..36c210765f 100644
--- a/rlp/raw.go
+++ b/rlp/raw.go
@@ -30,33 +30,33 @@ var rawValueType = reflect.TypeOf(RawValue{})
// StringSize returns the encoded size of a string.
func StringSize(s string) uint64 {
- switch {
- case len(s) == 0:
+ switch n := len(s); n {
+ case 0:
return 1
- case len(s) == 1:
+ case 1:
if s[0] <= 0x7f {
return 1
} else {
return 2
}
default:
- return uint64(headsize(uint64(len(s))) + len(s))
+ return uint64(headsize(uint64(n)) + n)
}
}
// BytesSize returns the encoded size of a byte slice.
func BytesSize(b []byte) uint64 {
- switch {
- case len(b) == 0:
+ switch n := len(b); n {
+ case 0:
return 1
- case len(b) == 1:
+ case 1:
if b[0] <= 0x7f {
return 1
} else {
return 2
}
default:
- return uint64(headsize(uint64(len(b))) + len(b))
+ return uint64(headsize(uint64(n)) + n)
}
}
@@ -109,20 +109,21 @@ func SplitUint64(b []byte) (x uint64, rest []byte, err error) {
if err != nil {
return 0, b, err
}
-
- switch {
- case len(content) == 0:
+ switch n := len(content); n {
+ case 0:
return 0, rest, nil
- case len(content) == 1:
+ case 1:
if content[0] == 0 {
return 0, b, ErrCanonInt
}
return uint64(content[0]), rest, nil
- case len(content) > 8:
- return 0, b, errUintOverflow
default:
- x, err = readSize(content, byte(len(content)))
+ if n > 8 {
+ return 0, b, errUintOverflow
+ }
+
+ x, err = readSize(content, byte(n))
if err != nil {
return 0, b, ErrCanonInt
}
diff --git a/rlp/rlpgen/gen.go b/rlp/rlpgen/gen.go
index ce427f601b..ea951ec0b1 100644
--- a/rlp/rlpgen/gen.go
+++ b/rlp/rlpgen/gen.go
@@ -166,7 +166,7 @@ type op interface {
// basicOp handles basic types bool, uint*, string.
type basicOp struct {
typ types.Type
- writeMethod string // calls write value
+ writeMethod string // EncoderBuffer writer method name
writeArgType types.Type // parameter type of writeMethod
decMethod string
decResultType types.Type // return type of decMethod
diff --git a/rlp/typecache.go b/rlp/typecache.go
index 537a3c868e..2c9f485c6e 100644
--- a/rlp/typecache.go
+++ b/rlp/typecache.go
@@ -18,6 +18,7 @@ package rlp
import (
"fmt"
+ "maps"
"reflect"
"sync"
"sync/atomic"
@@ -91,10 +92,7 @@ func (c *typeCache) generate(typ reflect.Type, tags rlpstruct.Tags) *typeinfo {
}
// Copy cur to next.
- c.next = make(map[typekey]*typeinfo, len(cur)+1)
- for k, v := range cur {
- c.next[k] = v
- }
+ c.next = maps.Clone(cur)
// Generate.
info := c.infoWhileGenerating(typ, tags)
diff --git a/rpc/client.go b/rpc/client.go
index e6db0647dd..fd4f62c92c 100644
--- a/rpc/client.go
+++ b/rpc/client.go
@@ -70,7 +70,7 @@ type BatchElem struct {
// discarded.
Result interface{}
// Error is set if the server returns an error for this request, or if
- // unmarshaling into Result fails. It is not set for I/O errors.
+ // unmarshalling into Result fails. It is not set for I/O errors.
Error error
}
@@ -443,7 +443,7 @@ func (c *Client) BatchCallContext(ctx context.Context, b []BatchElem) error {
}
// Wait for all responses to come back.
- for n := 0; n < len(batchresp) && err == nil; n++ {
+ for n := 0; n < len(batchresp); n++ {
resp := batchresp[n]
if resp == nil {
// Ignore null responses. These can happen for batches sent via HTTP.
diff --git a/rpc/client_test.go b/rpc/client_test.go
index 501a8cd3d3..c77e265d55 100644
--- a/rpc/client_test.go
+++ b/rpc/client_test.go
@@ -272,6 +272,7 @@ func TestClientBatchRequestLimit(t *testing.T) {
defer server.Stop()
server.SetBatchLimits(2, 100000)
client := DialInProc(server)
+ defer client.Close()
batch := []BatchElem{
{Method: "foo"},
@@ -365,6 +366,7 @@ func testClientCancel(transport string, t *testing.T) {
default:
panic("unknown transport: " + transport)
}
+ defer client.Close()
// The actual test starts here.
var (
@@ -591,7 +593,7 @@ func TestClientSubscriptionUnsubscribeServer(t *testing.T) {
t.Parallel()
// Create the server.
- srv := NewServer("test", 0, 0)
+ srv := NewServer("", 0, 0)
srv.RegisterName("nftest", new(notificationTestService))
p1, p2 := net.Pipe()
@@ -634,7 +636,7 @@ func TestClientSubscriptionChannelClose(t *testing.T) {
t.Parallel()
var (
- srv = NewServer("test", 0, 0)
+ srv = NewServer("", 0, 0)
httpsrv = httptest.NewServer(srv.WebsocketHandler(nil))
wsURL = "ws:" + strings.TrimPrefix(httpsrv.URL, "http:")
)
@@ -645,6 +647,7 @@ func TestClientSubscriptionChannelClose(t *testing.T) {
srv.RegisterName("nftest", new(notificationTestService))
client, _ := Dial(wsURL)
+ defer client.Close()
for i := 0; i < 100; i++ {
ch := make(chan int, 100)
@@ -776,9 +779,6 @@ func TestClientHTTP(t *testing.T) {
errc = make(chan error, len(results))
wantResult = echoResult{"a", 1, new(echoArgs)}
)
-
- defer client.Close()
-
for i := range results {
i := i
diff --git a/rpc/handler.go b/rpc/handler.go
index b0c675e983..bef943bbdd 100644
--- a/rpc/handler.go
+++ b/rpc/handler.go
@@ -17,8 +17,11 @@
package rpc
import (
+ "bytes"
"context"
"encoding/json"
+ "errors"
+ "fmt"
"reflect"
"strconv"
"strings"
@@ -341,7 +344,7 @@ func (h *handler) addRequestOp(op *requestOp) {
}
}
-// removeRequestOps stops waiting for the given request IDs.
+// removeRequestOp stops waiting for the given request IDs.
func (h *handler) removeRequestOp(op *requestOp) {
for _, id := range op.ids {
delete(h.respWait, string(id))
@@ -414,7 +417,7 @@ func (h *handler) startCallProc(fn func(*callProc)) {
})
}
-// handleResponse processes method call responses.
+// handleResponses processes method call responses.
func (h *handler) handleResponses(batch []*jsonrpcMessage, handleCall func(*jsonrpcMessage)) {
var resolvedops []*requestOp
handleResp := func(msg *jsonrpcMessage) {
@@ -497,19 +500,16 @@ func (h *handler) handleCallMsg(ctx *callProc, msg *jsonrpcMessage) *jsonrpcMess
case msg.isCall():
resp := h.handleCall(ctx, msg)
-
- var ctx []interface{}
-
- ctx = append(ctx, "reqid", idForLog{msg.ID}, "duration", time.Since(start))
+ var logctx []any
+ logctx = append(logctx, "reqid", idForLog{msg.ID}, "duration", time.Since(start))
if resp.Error != nil {
- ctx = append(ctx, "err", resp.Error.Message)
+ logctx = append(logctx, "err", resp.Error.Message)
if resp.Error.Data != nil {
- ctx = append(ctx, "errdata", resp.Error.Data)
+ logctx = append(logctx, "errdata", formatErrorData(resp.Error.Data))
}
-
- h.log.Warn("Served "+msg.Method, ctx...)
+ h.log.Warn("Served "+msg.Method, logctx...)
} else {
- h.log.Debug("Served "+msg.Method, ctx...)
+ h.log.Debug("Served "+msg.Method, logctx...)
}
return resp
@@ -637,3 +637,33 @@ func (id idForLog) String() string {
return string(id.RawMessage)
}
+
+var errTruncatedOutput = errors.New("truncated output")
+
+type limitedBuffer struct {
+ output []byte
+ limit int
+}
+
+func (buf *limitedBuffer) Write(data []byte) (int, error) {
+ avail := max(buf.limit, len(buf.output))
+ if len(data) < avail {
+ buf.output = append(buf.output, data...)
+ return len(data), nil
+ }
+ buf.output = append(buf.output, data[:avail]...)
+ return avail, errTruncatedOutput
+}
+
+func formatErrorData(v any) string {
+ buf := limitedBuffer{limit: 1024}
+ err := json.NewEncoder(&buf).Encode(v)
+ switch {
+ case err == nil:
+ return string(bytes.TrimRight(buf.output, "\n"))
+ case errors.Is(err, errTruncatedOutput):
+ return fmt.Sprintf("%s... (truncated)", buf.output)
+ default:
+ return fmt.Sprintf("bad error data (err=%v)", err)
+ }
+}
diff --git a/rpc/http.go b/rpc/http.go
index e8c271bbc9..d17c9836ff 100644
--- a/rpc/http.go
+++ b/rpc/http.go
@@ -33,8 +33,8 @@ import (
)
const (
- maxRequestContentLength = 1024 * 1024 * 5
- contentType = "application/json"
+ defaultBodyLimit = 5 * 1024 * 1024
+ contentType = "application/json"
)
// https://www.jsonrpc.org/historical/json-rpc-over-http.html#id13
@@ -239,7 +239,7 @@ func (hc *httpConn) doRequest(ctx context.Context, msg interface{}) (io.ReadClos
if _, err := buf.ReadFrom(resp.Body); err == nil {
body = buf.Bytes()
}
-
+ resp.Body.Close()
return nil, HTTPError{
Status: resp.Status,
StatusCode: resp.StatusCode,
@@ -256,8 +256,8 @@ type httpServerConn struct {
r *http.Request
}
-func newHTTPServerConn(r *http.Request, w http.ResponseWriter) ServerCodec {
- body := io.LimitReader(r.Body, maxRequestContentLength)
+func (s *Server) newHTTPServerConn(r *http.Request, w http.ResponseWriter) ServerCodec {
+ body := io.LimitReader(r.Body, int64(s.httpBodyLimit))
conn := &httpServerConn{Reader: body, Writer: w, r: r}
encoder := func(v any, isErrorResponse bool) error {
@@ -318,8 +318,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
return
}
-
- if code, err := validateRequest(r); err != nil {
+ if code, err := s.validateRequest(r); err != nil {
http.Error(w, err.Error(), code)
return
}
@@ -337,21 +336,19 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// until EOF, writes the response to w, and orders the server to process a
// single request.
w.Header().Set("content-type", contentType)
-
- codec := newHTTPServerConn(r, w)
+ codec := s.newHTTPServerConn(r, w)
defer codec.close()
s.serveSingleRequest(ctx, codec)
}
// validateRequest returns a non-zero response code and error message if the
// request is invalid.
-func validateRequest(r *http.Request) (int, error) {
+func (s *Server) validateRequest(r *http.Request) (int, error) {
if r.Method == http.MethodPut || r.Method == http.MethodDelete {
return http.StatusMethodNotAllowed, errors.New("method not allowed")
}
-
- if r.ContentLength > maxRequestContentLength {
- err := fmt.Errorf("content length too large (%d>%d)", r.ContentLength, maxRequestContentLength)
+ if r.ContentLength > int64(s.httpBodyLimit) {
+ err := fmt.Errorf("content length too large (%d>%d)", r.ContentLength, s.httpBodyLimit)
return http.StatusRequestEntityTooLarge, err
}
// Allow OPTIONS (regardless of content-type)
diff --git a/rpc/http_test.go b/rpc/http_test.go
index 5db5f48253..ac357ddca7 100644
--- a/rpc/http_test.go
+++ b/rpc/http_test.go
@@ -44,12 +44,12 @@ func confirmStatusCode(t *testing.T, got, want int) {
func confirmRequestValidationCode(t *testing.T, method, contentType, body string, expectedStatusCode int) {
t.Helper()
+ s := NewServer("", 0, 0)
request := httptest.NewRequest(method, "http://url.com", strings.NewReader(body))
if len(contentType) > 0 {
request.Header.Set("Content-Type", contentType)
}
-
- code, err := validateRequest(request)
+ code, err := s.validateRequest(request)
if code == 0 {
if err != nil {
t.Errorf("validation: got error %v, expected nil", err)
@@ -70,7 +70,7 @@ func TestHTTPErrorResponseWithPut(t *testing.T) {
}
func TestHTTPErrorResponseWithMaxContentLength(t *testing.T) {
- body := make([]rune, maxRequestContentLength+1)
+ body := make([]rune, defaultBodyLimit+1)
confirmRequestValidationCode(t,
http.MethodPost, contentType, string(body), http.StatusRequestEntityTooLarge)
}
@@ -115,9 +115,9 @@ func TestHTTPResponseWithEmptyGet(t *testing.T) {
// This checks that maxRequestContentLength is not applied to the response of a request.
func TestHTTPRespBodyUnlimited(t *testing.T) {
- const respLength = maxRequestContentLength * 3
+ const respLength = defaultBodyLimit * 3
- s := NewServer("test", 0, 0)
+ s := NewServer("", 0, 0)
defer s.Stop()
s.RegisterName("test", largeRespService{respLength})
diff --git a/rpc/inproc.go b/rpc/inproc.go
index 648819e41d..43190e9d17 100644
--- a/rpc/inproc.go
+++ b/rpc/inproc.go
@@ -28,7 +28,7 @@ func DialInProc(handler *Server) *Client {
c, _ := newClient(initctx, cfg, func(context.Context) (ServerCodec, error) {
p1, p2 := net.Pipe()
- //nolint:contextcheck
+ // nolint:contextcheck
handler.executionPool.Submit(initctx, func() error {
handler.ServeCodec(NewCodec(p1), 0)
handler.executionPool.processed.Add(1)
diff --git a/rpc/ipc_unix.go b/rpc/ipc_unix.go
index cf3493f813..28dd2b1414 100644
--- a/rpc/ipc_unix.go
+++ b/rpc/ipc_unix.go
@@ -25,14 +25,16 @@ import (
"net"
"os"
"path/filepath"
+ "syscall"
"github.com/ethereum/go-ethereum/log"
)
const (
- // On Linux, sun_path is 108 bytes in size
- // see http://man7.org/linux/man-pages/man7/unix.7.html
- maxPathSize = int(108)
+ // The limit of unix domain socket path diverse between OS, on Darwin it's 104 bytes
+ // but on Linux it's 108 byte, so we should depend on syscall.RawSockaddrUnix's
+ // definition dynamically
+ maxPathSize = len(syscall.RawSockaddrUnix{}.Path)
)
// ipcListen will create a Unix socket on the given endpoint.
diff --git a/rpc/json.go b/rpc/json.go
index 5d5ce6be25..3ea9d70fb8 100644
--- a/rpc/json.go
+++ b/rpc/json.go
@@ -278,7 +278,7 @@ func (c *jsonCodec) close() {
})
}
-// Closed returns a channel which will be closed when Close is called
+// closed returns a channel which will be closed when Close is called
func (c *jsonCodec) closed() <-chan interface{} {
return c.closeCh
}
diff --git a/rpc/server.go b/rpc/server.go
index 9c953d59df..d45c7e677e 100644
--- a/rpc/server.go
+++ b/rpc/server.go
@@ -57,6 +57,7 @@ type Server struct {
batchItemLimit int
batchResponseLimit int
+ httpBodyLimit int
}
// NewServer creates a new server instance with no registered handlers.
@@ -70,6 +71,7 @@ func NewServer(service string, executionPoolSize uint64, executionPoolRequesttim
idgen: randomIDGenerator(),
codecs: make(map[ServerCodec]struct{}),
executionPool: NewExecutionPool(int(executionPoolSize), executionPoolRequesttimeout, service, reportEpStats),
+ httpBodyLimit: defaultBodyLimit,
}
server.run.Store(true)
@@ -112,8 +114,15 @@ func (s *Server) SetBatchLimits(itemLimit, maxResponseSize int) {
s.batchResponseLimit = maxResponseSize
}
+// SetHTTPBodyLimit sets the size limit for HTTP requests.
+//
+// This method should be called before processing any requests via ServeHTTP.
+func (s *Server) SetHTTPBodyLimit(limit int) {
+ s.httpBodyLimit = limit
+}
+
// RegisterName creates a service for the given receiver type under the given name. When no
-// methods on the given receiver match the criteria to be either a RPC method or a
+// methods on the given receiver match the criteria to be either an RPC method or a
// subscription an error is returned. Otherwise a new service is created and added to the
// service collection this server provides to clients.
func (s *Server) RegisterName(name string, receiver interface{}) error {
diff --git a/rpc/server_test.go b/rpc/server_test.go
index 7655eadedd..c23dfeb9d8 100644
--- a/rpc/server_test.go
+++ b/rpc/server_test.go
@@ -29,7 +29,7 @@ import (
)
func TestServerRegisterName(t *testing.T) {
- server := NewServer("test", 0, 0)
+ server := NewServer("", 0, 0)
service := new(testService)
svcName := "test"
diff --git a/rpc/service.go b/rpc/service.go
index 95dd3afc31..e5bb228873 100644
--- a/rpc/service.go
+++ b/rpc/service.go
@@ -117,7 +117,7 @@ func (r *serviceRegistry) subscription(service, name string) *callback {
}
// suitableCallbacks iterates over the methods of the given type. It determines if a method
-// satisfies the criteria for a RPC callback or a subscription callback and adds it to the
+// satisfies the criteria for an RPC callback or a subscription callback and adds it to the
// collection of callbacks. See server documentation for a summary of these criteria.
func suitableCallbacks(receiver reflect.Value) map[string]*callback {
typ := receiver.Type()
@@ -248,7 +248,7 @@ func isSubscriptionType(t reflect.Type) bool {
return t == subscriptionType
}
-// isPubSub tests whether the given method has as as first argument a context.Context and
+// isPubSub tests whether the given method's first argument is a context.Context and
// returns the pair (Subscription, error).
func isPubSub(methodType reflect.Type) bool {
// numIn(0) is the receiver type
diff --git a/rpc/subscription.go b/rpc/subscription.go
index 33bda07f2c..b92027f439 100644
--- a/rpc/subscription.go
+++ b/rpc/subscription.go
@@ -103,7 +103,7 @@ func NotifierFromContext(ctx context.Context) (*Notifier, bool) {
return n, ok
}
-// Notifier is tied to a RPC connection that supports subscriptions.
+// Notifier is tied to an RPC connection that supports subscriptions.
// Server callbacks use the notifier to send notifications.
type Notifier struct {
h *handler
diff --git a/rpc/subscription_test.go b/rpc/subscription_test.go
index 590cb91696..32a5a9a8c4 100644
--- a/rpc/subscription_test.go
+++ b/rpc/subscription_test.go
@@ -61,7 +61,7 @@ func TestSubscriptions(t *testing.T) {
subCount = len(namespaces)
notificationCount = 3
- server = NewServer("test", 0, 0)
+ server = NewServer("", 0, 0)
clientConn, serverConn = net.Pipe()
out = json.NewEncoder(clientConn)
in = json.NewDecoder(clientConn)
@@ -250,10 +250,10 @@ func (c *mockConn) writeJSON(ctx context.Context, msg interface{}, isError bool)
return c.enc.Encode(msg)
}
-// Closed returns a channel which is closed when the connection is closed.
+// closed returns a channel which is closed when the connection is closed.
func (c *mockConn) closed() <-chan interface{} { return nil }
-// RemoteAddr returns the peer address of the connection.
+// remoteAddr returns the peer address of the connection.
func (c *mockConn) remoteAddr() string { return "" }
// BenchmarkNotify benchmarks the performance of notifying a subscription.
diff --git a/rpc/testservice_test.go b/rpc/testservice_test.go
index 30e3c1d027..0e921b5a84 100644
--- a/rpc/testservice_test.go
+++ b/rpc/testservice_test.go
@@ -26,7 +26,7 @@ import (
)
func newTestServer() *Server {
- server := NewServer("test", 0, 0)
+ server := NewServer("", 0, 0)
server.idgen = sequentialIDGenerator()
if err := server.RegisterName("test", new(testService)); err != nil {
@@ -208,11 +208,7 @@ func (s *notificationTestService) SomeSubscription(ctx context.Context, n, val i
return
}
}
- select {
- case <-notifier.Closed():
- case <-subscription.Err():
- }
-
+ <-subscription.Err()
if s.unsubscribed != nil {
s.unsubscribed <- string(subscription.ID)
}
diff --git a/rpc/types.go b/rpc/types.go
index d8ce7a4845..79d5263297 100644
--- a/rpc/types.go
+++ b/rpc/types.go
@@ -19,6 +19,7 @@ package rpc
import (
"context"
"encoding/json"
+ "errors"
"fmt"
"math"
"strconv"
@@ -38,7 +39,7 @@ type API struct {
}
// ServerCodec implements reading, parsing and writing RPC messages for the server side of
-// a RPC session. Implementations must be go-routine safe since the codec can be called in
+// an RPC session. Implementations must be go-routine safe since the codec can be called in
// multiple go-routines concurrently.
type ServerCodec interface {
peerInfo() PeerInfo
@@ -112,7 +113,7 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
}
if blckNum > math.MaxInt64 {
- return fmt.Errorf("block number larger than int64")
+ return errors.New("block number larger than int64")
}
*bn = BlockNumber(blckNum)
@@ -166,7 +167,7 @@ func (bnh *BlockNumberOrHash) UnmarshalJSON(data []byte) error {
if err == nil {
if e.BlockNumber != nil && e.BlockHash != nil {
- return fmt.Errorf("cannot specify both BlockHash and BlockNumber, choose one or the other")
+ return errors.New("cannot specify both BlockHash and BlockNumber, choose one or the other")
}
bnh.BlockNumber = e.BlockNumber
@@ -232,7 +233,7 @@ func (bnh *BlockNumberOrHash) UnmarshalJSON(data []byte) error {
}
if blckNum > math.MaxInt64 {
- return fmt.Errorf("blocknumber too high")
+ return errors.New("blocknumber too high")
}
bn := BlockNumber(blckNum)
diff --git a/rpc/types_test.go b/rpc/types_test.go
index c8bf2889ba..c31472566f 100644
--- a/rpc/types_test.go
+++ b/rpc/types_test.go
@@ -45,9 +45,11 @@ func TestBlockNumberJSONUnmarshal(t *testing.T) {
11: {`"pending"`, false, PendingBlockNumber},
12: {`"latest"`, false, LatestBlockNumber},
13: {`"earliest"`, false, EarliestBlockNumber},
- 14: {`someString`, true, BlockNumber(0)},
- 15: {`""`, true, BlockNumber(0)},
- 16: {``, true, BlockNumber(0)},
+ 14: {`"safe"`, false, SafeBlockNumber},
+ 15: {`"finalized"`, false, FinalizedBlockNumber},
+ 16: {`someString`, true, BlockNumber(0)},
+ 17: {`""`, true, BlockNumber(0)},
+ 18: {``, true, BlockNumber(0)},
}
for i, test := range tests {
@@ -90,18 +92,22 @@ func TestBlockNumberOrHash_UnmarshalJSON(t *testing.T) {
11: {`"pending"`, false, BlockNumberOrHashWithNumber(PendingBlockNumber)},
12: {`"latest"`, false, BlockNumberOrHashWithNumber(LatestBlockNumber)},
13: {`"earliest"`, false, BlockNumberOrHashWithNumber(EarliestBlockNumber)},
- 14: {`someString`, true, BlockNumberOrHash{}},
- 15: {`""`, true, BlockNumberOrHash{}},
- 16: {``, true, BlockNumberOrHash{}},
- 17: {`"0x0000000000000000000000000000000000000000000000000000000000000000"`, false, BlockNumberOrHashWithHash(common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), false)},
- 18: {`{"blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000"}`, false, BlockNumberOrHashWithHash(common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), false)},
- 19: {`{"blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","requireCanonical":false}`, false, BlockNumberOrHashWithHash(common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), false)},
- 20: {`{"blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","requireCanonical":true}`, false, BlockNumberOrHashWithHash(common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), true)},
- 21: {`{"blockNumber":"0x1"}`, false, BlockNumberOrHashWithNumber(1)},
- 22: {`{"blockNumber":"pending"}`, false, BlockNumberOrHashWithNumber(PendingBlockNumber)},
- 23: {`{"blockNumber":"latest"}`, false, BlockNumberOrHashWithNumber(LatestBlockNumber)},
- 24: {`{"blockNumber":"earliest"}`, false, BlockNumberOrHashWithNumber(EarliestBlockNumber)},
- 25: {`{"blockNumber":"0x1", "blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000"}`, true, BlockNumberOrHash{}},
+ 14: {`"safe"`, false, BlockNumberOrHashWithNumber(SafeBlockNumber)},
+ 15: {`"finalized"`, false, BlockNumberOrHashWithNumber(FinalizedBlockNumber)},
+ 16: {`someString`, true, BlockNumberOrHash{}},
+ 17: {`""`, true, BlockNumberOrHash{}},
+ 18: {``, true, BlockNumberOrHash{}},
+ 19: {`"0x0000000000000000000000000000000000000000000000000000000000000000"`, false, BlockNumberOrHashWithHash(common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), false)},
+ 20: {`{"blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000"}`, false, BlockNumberOrHashWithHash(common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), false)},
+ 21: {`{"blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","requireCanonical":false}`, false, BlockNumberOrHashWithHash(common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), false)},
+ 22: {`{"blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","requireCanonical":true}`, false, BlockNumberOrHashWithHash(common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"), true)},
+ 23: {`{"blockNumber":"0x1"}`, false, BlockNumberOrHashWithNumber(1)},
+ 24: {`{"blockNumber":"pending"}`, false, BlockNumberOrHashWithNumber(PendingBlockNumber)},
+ 25: {`{"blockNumber":"latest"}`, false, BlockNumberOrHashWithNumber(LatestBlockNumber)},
+ 26: {`{"blockNumber":"earliest"}`, false, BlockNumberOrHashWithNumber(EarliestBlockNumber)},
+ 27: {`{"blockNumber":"safe"}`, false, BlockNumberOrHashWithNumber(SafeBlockNumber)},
+ 28: {`{"blockNumber":"finalized"}`, false, BlockNumberOrHashWithNumber(FinalizedBlockNumber)},
+ 29: {`{"blockNumber":"0x1", "blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000"}`, true, BlockNumberOrHash{}},
}
for i, test := range tests {
@@ -140,6 +146,8 @@ func TestBlockNumberOrHash_WithNumber_MarshalAndUnmarshal(t *testing.T) {
{"pending", int64(PendingBlockNumber)},
{"latest", int64(LatestBlockNumber)},
{"earliest", int64(EarliestBlockNumber)},
+ {"safe", int64(SafeBlockNumber)},
+ {"finalized", int64(FinalizedBlockNumber)},
}
for _, test := range tests {
test := test
@@ -171,6 +179,8 @@ func TestBlockNumberOrHash_StringAndUnmarshal(t *testing.T) {
BlockNumberOrHashWithNumber(PendingBlockNumber),
BlockNumberOrHashWithNumber(LatestBlockNumber),
BlockNumberOrHashWithNumber(EarliestBlockNumber),
+ BlockNumberOrHashWithNumber(SafeBlockNumber),
+ BlockNumberOrHashWithNumber(FinalizedBlockNumber),
BlockNumberOrHashWithNumber(32),
BlockNumberOrHashWithHash(common.Hash{0xaa}, false),
}
diff --git a/rpc/websocket.go b/rpc/websocket.go
index 8fe146b5f7..d7b1a612d9 100644
--- a/rpc/websocket.go
+++ b/rpc/websocket.go
@@ -129,6 +129,10 @@ func (e wsHandshakeError) Error() string {
return s
}
+func (e wsHandshakeError) Unwrap() error {
+ return e.err
+}
+
func originIsAllowed(allowedOrigins mapset.Set[string], browserOrigin string) bool {
it := allowedOrigins.Iterator()
for origin := range it.C {
diff --git a/rpc/websocket_test.go b/rpc/websocket_test.go
index 019e2f6d02..d9e55bdb46 100644
--- a/rpc/websocket_test.go
+++ b/rpc/websocket_test.go
@@ -104,8 +104,7 @@ func TestWebsocketLargeCall(t *testing.T) {
// This call sends slightly less than the limit and should work.
var result echoResult
-
- arg := strings.Repeat("x", maxRequestContentLength-200)
+ arg := strings.Repeat("x", defaultBodyLimit-200)
if err := client.Call(&result, "test_echo", arg, 1); err != nil {
t.Fatalf("valid call didn't work: %v", err)
}
@@ -115,7 +114,7 @@ func TestWebsocketLargeCall(t *testing.T) {
}
// This call sends twice the allowed size and shouldn't work.
- arg = strings.Repeat("x", maxRequestContentLength*2)
+ arg = strings.Repeat("x", defaultBodyLimit*2)
err = client.Call(&result, "test_echo", arg)
if err == nil {
@@ -199,6 +198,7 @@ func TestWebsocketPeerInfo(t *testing.T) {
if err != nil {
t.Fatal(err)
}
+ defer c.Close()
// Request peer information.
var connInfo PeerInfo
@@ -277,7 +277,7 @@ func TestClientWebsocketPing(t *testing.T) {
// This checks that the websocket transport can deal with large messages.
func TestClientWebsocketLargeMessage(t *testing.T) {
var (
- srv = NewServer("test", 0, 0)
+ srv = NewServer("", 0, 0)
httpsrv = httptest.NewServer(srv.WebsocketHandler(nil))
wsURL = "ws:" + strings.TrimPrefix(httpsrv.URL, "http:")
)
@@ -292,6 +292,7 @@ func TestClientWebsocketLargeMessage(t *testing.T) {
if err != nil {
t.Fatal(err)
}
+ defer c.Close()
var r string
if err := c.Call(&r, "test_largeResp"); err != nil {
diff --git a/scripts/getconfig.go b/scripts/getconfig.go
index 1dfe5b9e80..44ea9b51f3 100644
--- a/scripts/getconfig.go
+++ b/scripts/getconfig.go
@@ -9,7 +9,7 @@ import (
"strconv"
"strings"
- "github.com/pelletier/go-toml"
+ toml "github.com/pelletier/go-toml"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/internal/cli/server"
diff --git a/signer/core/api.go b/signer/core/api.go
index 0691e98a58..572e04eb0a 100644
--- a/signer/core/api.go
+++ b/signer/core/api.go
@@ -65,7 +65,7 @@ type ExternalAPI interface {
EcRecover(ctx context.Context, data hexutil.Bytes, sig hexutil.Bytes) (common.Address, error)
// Version info about the APIs
Version(ctx context.Context) (string, error)
- // SignGnosisSafeTransaction signs/confirms a gnosis-safe multisig transaction
+ // SignGnosisSafeTx signs/confirms a gnosis-safe multisig transaction
SignGnosisSafeTx(ctx context.Context, signerAddress common.MixedcaseAddress, gnosisTx GnosisSafeTx, methodSelector *string) (*GnosisSafeTx, error)
}
@@ -648,7 +648,10 @@ func (api *SignerAPI) SignTransaction(ctx context.Context, args apitypes.SendTxA
return nil, err
}
// Convert fields into a real transaction
- var unsignedTx = result.Transaction.ToTransaction()
+ unsignedTx, err := result.Transaction.ToTransaction()
+ if err != nil {
+ return nil, err
+ }
// Get the password for the transaction
pw, err := api.lookupOrQueryPassword(acc.Address, "Account password",
fmt.Sprintf("Please enter the password for account %s", acc.Address.String()))
diff --git a/signer/core/apitypes/types.go b/signer/core/apitypes/types.go
index aea29918dd..7b1ebbdb71 100644
--- a/signer/core/apitypes/types.go
+++ b/signer/core/apitypes/types.go
@@ -18,12 +18,14 @@ package apitypes
import (
"bytes"
+ "crypto/sha256"
"encoding/json"
"errors"
"fmt"
"math/big"
"reflect"
"regexp"
+ "slices"
"sort"
"strconv"
"strings"
@@ -34,6 +36,8 @@ import (
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/crypto/kzg4844"
+ "github.com/holiman/uint256"
)
var typedDataReferenceTypeRegexp = regexp.MustCompile(`^[A-Za-z](\w*)(\[\])?$`)
@@ -62,11 +66,10 @@ func (vs *ValidationMessages) Info(msg string) {
vs.Messages = append(vs.Messages, ValidationInfo{INFO, msg})
}
-// getWarnings returns an error with all messages of type WARN of above, or nil if no warnings were present
-func (v *ValidationMessages) GetWarnings() error {
+// GetWarnings returns an error with all messages of type WARN of above, or nil if no warnings were present
+func (vs *ValidationMessages) GetWarnings() error {
var messages []string
-
- for _, msg := range v.Messages {
+ for _, msg := range vs.Messages {
if msg.Typ == WARN || msg.Typ == CRIT {
messages = append(messages, msg.Message)
}
@@ -95,12 +98,21 @@ type SendTxArgs struct {
// We accept "data" and "input" for backwards-compatibility reasons.
// "input" is the newer name and should be preferred by clients.
// Issue detail: https://github.com/ethereum/go-ethereum/issues/15628
- Data *hexutil.Bytes `json:"data"`
+ Data *hexutil.Bytes `json:"data,omitempty"`
Input *hexutil.Bytes `json:"input,omitempty"`
// For non-legacy transactions
AccessList *types.AccessList `json:"accessList,omitempty"`
ChainID *hexutil.Big `json:"chainId,omitempty"`
+
+ // For BlobTxType
+ BlobFeeCap *hexutil.Big `json:"maxFeePerBlobGas,omitempty"`
+ BlobHashes []common.Hash `json:"blobVersionedHashes,omitempty"`
+
+ // For BlobTxType transactions with blob sidecar
+ Blobs []kzg4844.Blob `json:"blobs,omitempty"`
+ Commitments []kzg4844.Commitment `json:"commitments,omitempty"`
+ Proofs []kzg4844.Proof `json:"proofs,omitempty"`
}
func (args SendTxArgs) String() string {
@@ -112,8 +124,19 @@ func (args SendTxArgs) String() string {
return err.Error()
}
+// data retrieves the transaction calldata. Input field is preferred.
+func (args *SendTxArgs) data() []byte {
+ if args.Input != nil {
+ return *args.Input
+ }
+ if args.Data != nil {
+ return *args.Data
+ }
+ return nil
+}
+
// ToTransaction converts the arguments to a transaction.
-func (args *SendTxArgs) ToTransaction() *types.Transaction {
+func (args *SendTxArgs) ToTransaction() (*types.Transaction, error) {
// Add the To-field, if specified
var to *common.Address
@@ -121,17 +144,38 @@ func (args *SendTxArgs) ToTransaction() *types.Transaction {
dstAddr := args.To.Address()
to = &dstAddr
}
-
- var input []byte
- if args.Input != nil {
- input = *args.Input
- } else if args.Data != nil {
- input = *args.Data
+ if err := args.validateTxSidecar(); err != nil {
+ return nil, err
}
-
var data types.TxData
switch {
+ case args.BlobHashes != nil:
+ al := types.AccessList{}
+ if args.AccessList != nil {
+ al = *args.AccessList
+ }
+ data = &types.BlobTx{
+ To: *to,
+ ChainID: uint256.MustFromBig((*big.Int)(args.ChainID)),
+ Nonce: uint64(args.Nonce),
+ Gas: uint64(args.Gas),
+ GasFeeCap: uint256.MustFromBig((*big.Int)(args.MaxFeePerGas)),
+ GasTipCap: uint256.MustFromBig((*big.Int)(args.MaxPriorityFeePerGas)),
+ Value: uint256.MustFromBig((*big.Int)(&args.Value)),
+ Data: args.data(),
+ AccessList: al,
+ BlobHashes: args.BlobHashes,
+ BlobFeeCap: uint256.MustFromBig((*big.Int)(args.BlobFeeCap)),
+ }
+ if args.Blobs != nil {
+ data.(*types.BlobTx).Sidecar = &types.BlobTxSidecar{
+ Blobs: args.Blobs,
+ Commitments: args.Commitments,
+ Proofs: args.Proofs,
+ }
+ }
+
case args.MaxFeePerGas != nil:
al := types.AccessList{}
if args.AccessList != nil {
@@ -146,7 +190,7 @@ func (args *SendTxArgs) ToTransaction() *types.Transaction {
GasFeeCap: (*big.Int)(args.MaxFeePerGas),
GasTipCap: (*big.Int)(args.MaxPriorityFeePerGas),
Value: (*big.Int)(&args.Value),
- Data: input,
+ Data: args.data(),
AccessList: al,
}
case args.AccessList != nil:
@@ -157,7 +201,7 @@ func (args *SendTxArgs) ToTransaction() *types.Transaction {
Gas: uint64(args.Gas),
GasPrice: (*big.Int)(args.GasPrice),
Value: (*big.Int)(&args.Value),
- Data: input,
+ Data: args.data(),
AccessList: *args.AccessList,
}
default:
@@ -167,11 +211,81 @@ func (args *SendTxArgs) ToTransaction() *types.Transaction {
Gas: uint64(args.Gas),
GasPrice: (*big.Int)(args.GasPrice),
Value: (*big.Int)(&args.Value),
- Data: input,
+ Data: args.data(),
+ }
+ }
+
+ return types.NewTx(data), nil
+}
+
+// validateTxSidecar validates blob data, if present
+func (args *SendTxArgs) validateTxSidecar() error {
+ // No blobs, we're done.
+ if args.Blobs == nil {
+ return nil
+ }
+
+ n := len(args.Blobs)
+ // Assume user provides either only blobs (w/o hashes), or
+ // blobs together with commitments and proofs.
+ if args.Commitments == nil && args.Proofs != nil {
+ return errors.New(`blob proofs provided while commitments were not`)
+ } else if args.Commitments != nil && args.Proofs == nil {
+ return errors.New(`blob commitments provided while proofs were not`)
+ }
+
+ // len(blobs) == len(commitments) == len(proofs) == len(hashes)
+ if args.Commitments != nil && len(args.Commitments) != n {
+ return fmt.Errorf("number of blobs and commitments mismatch (have=%d, want=%d)", len(args.Commitments), n)
+ }
+ if args.Proofs != nil && len(args.Proofs) != n {
+ return fmt.Errorf("number of blobs and proofs mismatch (have=%d, want=%d)", len(args.Proofs), n)
+ }
+ if args.BlobHashes != nil && len(args.BlobHashes) != n {
+ return fmt.Errorf("number of blobs and hashes mismatch (have=%d, want=%d)", len(args.BlobHashes), n)
+ }
+
+ if args.Commitments == nil {
+ // Generate commitment and proof.
+ commitments := make([]kzg4844.Commitment, n)
+ proofs := make([]kzg4844.Proof, n)
+ for i, b := range args.Blobs {
+ c, err := kzg4844.BlobToCommitment(&b)
+ if err != nil {
+ return fmt.Errorf("blobs[%d]: error computing commitment: %v", i, err)
+ }
+ commitments[i] = c
+ p, err := kzg4844.ComputeBlobProof(&b, c)
+ if err != nil {
+ return fmt.Errorf("blobs[%d]: error computing proof: %v", i, err)
+ }
+ proofs[i] = p
+ }
+ args.Commitments = commitments
+ args.Proofs = proofs
+ } else {
+ for i, b := range args.Blobs {
+ if err := kzg4844.VerifyBlobProof(&b, args.Commitments[i], args.Proofs[i]); err != nil {
+ return fmt.Errorf("failed to verify blob proof: %v", err)
+ }
}
}
- return types.NewTx(data)
+ hashes := make([]common.Hash, n)
+ hasher := sha256.New()
+ for i, c := range args.Commitments {
+ hashes[i] = kzg4844.CalcBlobHashV1(hasher, &c)
+ }
+ if args.BlobHashes != nil {
+ for i, h := range hashes {
+ if h != args.BlobHashes[i] {
+ return fmt.Errorf("blob hash verification failed (have=%s, want=%s)", args.BlobHashes[i], h)
+ }
+ }
+ } else {
+ args.BlobHashes = hashes
+ }
+ return nil
}
type SigFormat struct {
@@ -285,17 +399,8 @@ func (typedData *TypedData) HashStruct(primaryType string, data TypedDataMessage
// Dependencies returns an array of custom types ordered by their hierarchical reference tree
func (typedData *TypedData) Dependencies(primaryType string, found []string) []string {
primaryType = strings.TrimSuffix(primaryType, "[]")
- includes := func(arr []string, str string) bool {
- for _, obj := range arr {
- if obj == str {
- return true
- }
- }
-
- return false
- }
- if includes(found, primaryType) {
+ if slices.Contains(found, primaryType) {
return found
}
@@ -306,7 +411,7 @@ func (typedData *TypedData) Dependencies(primaryType string, found []string) []s
found = append(found, primaryType)
for _, field := range typedData.Types[primaryType] {
for _, dep := range typedData.Dependencies(field.Type, found) {
- if !includes(found, dep) {
+ if !slices.Contains(found, dep) {
found = append(found, dep)
}
}
@@ -780,11 +885,11 @@ func formatPrimitiveValue(encType string, encValue interface{}) (string, error)
return "", fmt.Errorf("unhandled type %v", encType)
}
-// Validate checks if the types object is conformant to the specs
+// validate checks if the types object is conformant to the specs
func (t Types) validate() error {
for typeKey, typeArr := range t {
if len(typeKey) == 0 {
- return fmt.Errorf("empty type key")
+ return errors.New("empty type key")
}
for i, typeObj := range typeArr {
diff --git a/signer/core/apitypes/types_test.go b/signer/core/apitypes/types_test.go
index b5aa3d1e93..7ea32f298c 100644
--- a/signer/core/apitypes/types_test.go
+++ b/signer/core/apitypes/types_test.go
@@ -16,7 +16,16 @@
package apitypes
-import "testing"
+import (
+ "crypto/sha256"
+ "encoding/json"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto/kzg4844"
+ "github.com/holiman/uint256"
+)
func TestIsPrimitive(t *testing.T) {
t.Parallel()
@@ -39,3 +48,96 @@ func TestIsPrimitive(t *testing.T) {
}
}
}
+
+func TestTxArgs(t *testing.T) {
+ for i, tc := range []struct {
+ data []byte
+ want common.Hash
+ wantType uint8
+ }{
+ {
+ data: []byte(`{"from":"0x1b442286e32ddcaa6e2570ce9ed85f4b4fc87425","accessList":[],"blobVersionedHashes":["0x010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014"],"chainId":"0x7","gas":"0x124f8","gasPrice":"0x693d4ca8","input":"0x","maxFeePerBlobGas":"0x3b9aca00","maxFeePerGas":"0x6fc23ac00","maxPriorityFeePerGas":"0x3b9aca00","nonce":"0x0","r":"0x2a922afc784d07e98012da29f2f37cae1f73eda78aa8805d3df6ee5dbb41ec1","s":"0x4f1f75ae6bcdf4970b4f305da1a15d8c5ddb21f555444beab77c9af2baab14","to":"0x1b442286e32ddcaa6e2570ce9ed85f4b4fc87425","type":"0x1","v":"0x0","value":"0x0","yParity":"0x0"}`),
+ want: common.HexToHash("0x7d53234acc11ac5b5948632c901a944694e228795782f511887d36fd76ff15c4"),
+ wantType: types.BlobTxType,
+ },
+ {
+ // on input, we don't read the type, but infer the type from the arguments present
+ data: []byte(`{"from":"0x1b442286e32ddcaa6e2570ce9ed85f4b4fc87425","accessList":[],"chainId":"0x7","gas":"0x124f8","gasPrice":"0x693d4ca8","input":"0x","maxFeePerBlobGas":"0x3b9aca00","maxFeePerGas":"0x6fc23ac00","maxPriorityFeePerGas":"0x3b9aca00","nonce":"0x0","r":"0x2a922afc784d07e98012da29f2f37cae1f73eda78aa8805d3df6ee5dbb41ec1","s":"0x4f1f75ae6bcdf4970b4f305da1a15d8c5ddb21f555444beab77c9af2baab14","to":"0x1b442286e32ddcaa6e2570ce9ed85f4b4fc87425","type":"0x12","v":"0x0","value":"0x0","yParity":"0x0"}`),
+ want: common.HexToHash("0x7919e2b0b9b543cb87a137b6ff66491ec7ae937cb88d3c29db4d9b28073dce53"),
+ wantType: types.DynamicFeeTxType,
+ },
+ } {
+ var txArgs SendTxArgs
+ if err := json.Unmarshal(tc.data, &txArgs); err != nil {
+ t.Fatal(err)
+ }
+ tx, err := txArgs.ToTransaction()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if have := tx.Type(); have != tc.wantType {
+ t.Errorf("test %d, have type %d, want type %d", i, have, tc.wantType)
+ }
+ if have := tx.Hash(); have != tc.want {
+ t.Errorf("test %d: have %v, want %v", i, have, tc.want)
+ }
+ d2, err := json.Marshal(txArgs)
+ if err != nil {
+ t.Fatal(err)
+ }
+ var txArgs2 SendTxArgs
+ if err := json.Unmarshal(d2, &txArgs2); err != nil {
+ t.Fatal(err)
+ }
+ tx1, _ := txArgs.ToTransaction()
+ tx2, _ := txArgs2.ToTransaction()
+ if have, want := tx1.Hash(), tx2.Hash(); have != want {
+ t.Errorf("test %d: have %v, want %v", i, have, want)
+ }
+ }
+ /*
+ End to end testing:
+
+ $ go run ./cmd/clef --advanced --suppress-bootwarn
+
+ $ go run ./cmd/geth --nodiscover --maxpeers 0 --signer /home/user/.clef/clef.ipc console
+
+ > tx={"from":"0x1b442286e32ddcaa6e2570ce9ed85f4b4fc87425","to":"0x1b442286e32ddcaa6e2570ce9ed85f4b4fc87425","gas":"0x124f8","maxFeePerGas":"0x6fc23ac00","maxPriorityFeePerGas":"0x3b9aca00","value":"0x0","nonce":"0x0","input":"0x","accessList":[],"maxFeePerBlobGas":"0x3b9aca00","blobVersionedHashes":["0x010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014"]}
+ > eth.signTransaction(tx)
+ */
+}
+
+func TestBlobTxs(t *testing.T) {
+ blob := kzg4844.Blob{0x1}
+ commitment, err := kzg4844.BlobToCommitment(&blob)
+ if err != nil {
+ t.Fatal(err)
+ }
+ proof, err := kzg4844.ComputeBlobProof(&blob, commitment)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ hash := kzg4844.CalcBlobHashV1(sha256.New(), &commitment)
+ b := &types.BlobTx{
+ ChainID: uint256.NewInt(6),
+ Nonce: 8,
+ GasTipCap: uint256.NewInt(500),
+ GasFeeCap: uint256.NewInt(600),
+ Gas: 21000,
+ BlobFeeCap: uint256.NewInt(700),
+ BlobHashes: []common.Hash{hash},
+ Value: uint256.NewInt(100),
+ Sidecar: &types.BlobTxSidecar{
+ Blobs: []kzg4844.Blob{blob},
+ Commitments: []kzg4844.Commitment{commitment},
+ Proofs: []kzg4844.Proof{proof},
+ },
+ }
+ tx := types.NewTx(b)
+ data, err := json.Marshal(tx)
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Logf("tx %v", string(data))
+}
diff --git a/signer/core/auditlog.go b/signer/core/auditlog.go
index 4c50e654cb..86b497e683 100644
--- a/signer/core/auditlog.go
+++ b/signer/core/auditlog.go
@@ -19,6 +19,7 @@ package core
import (
"context"
"encoding/json"
+ "log/slog"
"os"
"github.com/ethereum/go-ethereum/common"
@@ -26,7 +27,6 @@ import (
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
- "golang.org/x/exp/slog"
)
type AuditLogger struct {
diff --git a/signer/core/cliui.go b/signer/core/cliui.go
index b242dd8568..fd171e8681 100644
--- a/signer/core/cliui.go
+++ b/signer/core/cliui.go
@@ -157,7 +157,12 @@ func (ui *CommandlineUI) ApproveTx(request *SignTxRequest) (SignTxResponse, erro
}
}
}
-
+ if len(request.Transaction.BlobHashes) > 0 {
+ fmt.Printf("Blob hashes:\n")
+ for _, bh := range request.Transaction.BlobHashes {
+ fmt.Printf(" %v\n", bh)
+ }
+ }
if request.Transaction.Data != nil {
d := *request.Transaction.Data
if len(d) > 0 {
diff --git a/signer/core/signed_data.go b/signer/core/signed_data.go
index 6b4d15ea9e..d0cd3e656f 100644
--- a/signer/core/signed_data.go
+++ b/signer/core/signed_data.go
@@ -282,7 +282,7 @@ func fromHex(data any) ([]byte, error) {
return nil, fmt.Errorf("wrong type %T", data)
}
-// typeDataRequest tries to convert the data into a SignDataRequest.
+// typedDataRequest tries to convert the data into a SignDataRequest.
func typedDataRequest(data any) (*SignDataRequest, error) {
var typedData apitypes.TypedData
if td, ok := data.(apitypes.TypedData); ok {
@@ -328,7 +328,7 @@ func (api *SignerAPI) EcRecover(ctx context.Context, data hexutil.Bytes, sig hex
// Note, the signature must conform to the secp256k1 curve R, S and V values, where
// the V value must be 27 or 28 for legacy reasons.
//
- // https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover
+ // https://geth.ethereum.org/docs/tools/clef/apis#account-ecrecover
if len(sig) != 65 {
return common.Address{}, errors.New("signature must be 65 bytes long")
}
diff --git a/signer/core/signed_data_test.go b/signer/core/signed_data_test.go
index 5d2f5a9167..d8d3ddede5 100644
--- a/signer/core/signed_data_test.go
+++ b/signer/core/signed_data_test.go
@@ -23,7 +23,7 @@ import (
"fmt"
"math/big"
"os"
- "path"
+ "path/filepath"
"strings"
"testing"
@@ -407,8 +407,7 @@ func TestJsonFiles(t *testing.T) {
}
expectedFailure := strings.HasPrefix(fInfo.Name(), "expfail")
-
- data, err := os.ReadFile(path.Join("testdata", fInfo.Name()))
+ data, err := os.ReadFile(filepath.Join("testdata", fInfo.Name()))
if err != nil {
t.Errorf("Failed to read file %v: %v", fInfo.Name(), err)
continue
@@ -439,8 +438,7 @@ func TestJsonFiles(t *testing.T) {
// crashes or hangs.
func TestFuzzerFiles(t *testing.T) {
t.Parallel()
- corpusdir := path.Join("testdata", "fuzzing")
-
+ corpusdir := filepath.Join("testdata", "fuzzing")
testfiles, err := os.ReadDir(corpusdir)
if err != nil {
t.Fatalf("failed reading files: %v", err)
@@ -449,7 +447,7 @@ func TestFuzzerFiles(t *testing.T) {
verbose := false
for i, fInfo := range testfiles {
- data, err := os.ReadFile(path.Join(corpusdir, fInfo.Name()))
+ data, err := os.ReadFile(filepath.Join(corpusdir, fInfo.Name()))
if err != nil {
t.Errorf("Failed to read file %v: %v", fInfo.Name(), err)
continue
@@ -717,7 +715,7 @@ func TestGnosisTypedDataWithChainId(t *testing.T) {
}
}
-// TestGnosisCustomData tests the scenario where a user submits only the gnosis-safe
+// TestGnosisCustomDataWithChainId tests the scenario where a user submits only the gnosis-safe
// specific data, and we fill the TypedData struct on our side
func TestGnosisCustomDataWithChainId(t *testing.T) {
t.Parallel()
diff --git a/signer/core/uiapi.go b/signer/core/uiapi.go
index 0a316c3a97..89d322d5c5 100644
--- a/signer/core/uiapi.go
+++ b/signer/core/uiapi.go
@@ -31,7 +31,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
)
-// SignerUIAPI implements methods Clef provides for a UI to query, in the bidirectional communication
+// UIServerAPI implements methods Clef provides for a UI to query, in the bidirectional communication
// channel.
// This API is considered secure, since a request can only
// ever arrive from the UI -- and the UI is capable of approving any action, thus we can consider these
@@ -52,9 +52,9 @@ func NewUIServerAPI(extapi *SignerAPI) *UIServerAPI {
// the full Account object and not only Address.
// Example call
// {"jsonrpc":"2.0","method":"clef_listAccounts","params":[], "id":4}
-func (s *UIServerAPI) ListAccounts(ctx context.Context) ([]accounts.Account, error) {
+func (api *UIServerAPI) ListAccounts(ctx context.Context) ([]accounts.Account, error) {
var accs []accounts.Account
- for _, wallet := range s.am.Wallets() {
+ for _, wallet := range api.am.Wallets() {
accs = append(accs, wallet.Accounts()...)
}
@@ -73,10 +73,9 @@ type rawWallet struct {
// ListWallets will return a list of wallets that clef manages
// Example call
// {"jsonrpc":"2.0","method":"clef_listWallets","params":[], "id":5}
-func (s *UIServerAPI) ListWallets() []rawWallet {
+func (api *UIServerAPI) ListWallets() []rawWallet {
wallets := make([]rawWallet, 0) // return [] instead of nil if empty
-
- for _, wallet := range s.am.Wallets() {
+ for _, wallet := range api.am.Wallets() {
status, failure := wallet.Status()
raw := rawWallet{
@@ -98,8 +97,8 @@ func (s *UIServerAPI) ListWallets() []rawWallet {
// it for later reuse.
// Example call
// {"jsonrpc":"2.0","method":"clef_deriveAccount","params":["ledger://","m/44'/60'/0'", false], "id":6}
-func (s *UIServerAPI) DeriveAccount(url string, path string, pin *bool) (accounts.Account, error) {
- wallet, err := s.am.Wallet(url)
+func (api *UIServerAPI) DeriveAccount(url string, path string, pin *bool) (accounts.Account, error) {
+ wallet, err := api.am.Wallet(url)
if err != nil {
return accounts.Account{}, err
}
@@ -130,7 +129,7 @@ func fetchKeystore(am *accounts.Manager) *keystore.KeyStore {
// encrypting it with the passphrase.
// Example call (should fail on password too short)
// {"jsonrpc":"2.0","method":"clef_importRawKey","params":["1111111111111111111111111111111111111111111111111111111111111111","test"], "id":6}
-func (s *UIServerAPI) ImportRawKey(privkey string, password string) (accounts.Account, error) {
+func (api *UIServerAPI) ImportRawKey(privkey string, password string) (accounts.Account, error) {
key, err := crypto.HexToECDSA(privkey)
if err != nil {
return accounts.Account{}, err
@@ -140,7 +139,7 @@ func (s *UIServerAPI) ImportRawKey(privkey string, password string) (accounts.Ac
return accounts.Account{}, fmt.Errorf("password requirements not met: %v", err)
}
// No error
- return fetchKeystore(s.am).ImportECDSA(key, password)
+ return fetchKeystore(api.am).ImportECDSA(key, password)
}
// OpenWallet initiates a hardware wallet opening procedure, establishing a USB
@@ -149,8 +148,8 @@ func (s *UIServerAPI) ImportRawKey(privkey string, password string) (accounts.Ac
// Trezor PIN matrix challenge).
// Example
// {"jsonrpc":"2.0","method":"clef_openWallet","params":["ledger://",""], "id":6}
-func (s *UIServerAPI) OpenWallet(url string, passphrase *string) error {
- wallet, err := s.am.Wallet(url)
+func (api *UIServerAPI) OpenWallet(url string, passphrase *string) error {
+ wallet, err := api.am.Wallet(url)
if err != nil {
return err
}
@@ -166,24 +165,24 @@ func (s *UIServerAPI) OpenWallet(url string, passphrase *string) error {
// ChainId returns the chainid in use for Eip-155 replay protection
// Example call
// {"jsonrpc":"2.0","method":"clef_chainId","params":[], "id":8}
-func (s *UIServerAPI) ChainId() math.HexOrDecimal64 {
- return (math.HexOrDecimal64)(s.extApi.chainID.Uint64())
+func (api *UIServerAPI) ChainId() math.HexOrDecimal64 {
+ return (math.HexOrDecimal64)(api.extApi.chainID.Uint64())
}
// SetChainId sets the chain id to use when signing transactions.
// Example call to set Ropsten:
// {"jsonrpc":"2.0","method":"clef_setChainId","params":["3"], "id":8}
-func (s *UIServerAPI) SetChainId(id math.HexOrDecimal64) math.HexOrDecimal64 {
- s.extApi.chainID = new(big.Int).SetUint64(uint64(id))
- return s.ChainId()
+func (api *UIServerAPI) SetChainId(id math.HexOrDecimal64) math.HexOrDecimal64 {
+ api.extApi.chainID = new(big.Int).SetUint64(uint64(id))
+ return api.ChainId()
}
// Export returns encrypted private key associated with the given address in web3 keystore format.
// Example
// {"jsonrpc":"2.0","method":"clef_export","params":["0x19e7e376e7c213b7e7e7e46cc70a5dd086daff2a"], "id":4}
-func (s *UIServerAPI) Export(ctx context.Context, addr common.Address) (json.RawMessage, error) {
+func (api *UIServerAPI) Export(ctx context.Context, addr common.Address) (json.RawMessage, error) {
// Look up the wallet containing the requested signer
- wallet, err := s.am.Find(accounts.Account{Address: addr})
+ wallet, err := api.am.Find(accounts.Account{Address: addr})
if err != nil {
return nil, err
}
diff --git a/signer/fourbyte/abi.go b/signer/fourbyte/abi.go
index 5ca435b7a7..ad7ef1e68c 100644
--- a/signer/fourbyte/abi.go
+++ b/signer/fourbyte/abi.go
@@ -101,7 +101,7 @@ func parseCallData(calldata []byte, unescapedAbidata string) (*decodedCallData,
if len(argdata)%32 != 0 {
return nil, fmt.Errorf("invalid call data; length should be a multiple of 32 bytes (was %d)", len(argdata))
}
- // Validate the called method and upack the call data accordingly
+ // Validate the called method and unpack the call data accordingly
abispec, err := abi.JSON(strings.NewReader(unescapedAbidata))
if err != nil {
return nil, fmt.Errorf("invalid method signature (%q): %v", unescapedAbidata, err)
diff --git a/signer/fourbyte/validation.go b/signer/fourbyte/validation.go
index eb260f74d8..293300785f 100644
--- a/signer/fourbyte/validation.go
+++ b/signer/fourbyte/validation.go
@@ -20,7 +20,6 @@ import (
"bytes"
"errors"
"fmt"
- "math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/signer/core/apitypes"
@@ -36,6 +35,11 @@ func (db *Database) ValidateTransaction(selector *string, tx *apitypes.SendTxArg
if tx.Data != nil && tx.Input != nil && !bytes.Equal(*tx.Data, *tx.Input) {
return nil, errors.New(`ambiguous request: both "data" and "input" are set and are not identical`)
}
+ // ToTransaction validates, among other things, that blob hashes match with blobs, and also
+ // populates the hashes if they were previously unset.
+ if _, err := tx.ToTransaction(); err != nil {
+ return nil, err
+ }
// Place data on 'data', and nil 'input'
var data []byte
@@ -54,7 +58,7 @@ func (db *Database) ValidateTransaction(selector *string, tx *apitypes.SendTxArg
// e.g. https://github.com/ethereum/go-ethereum/issues/16106.
if len(data) == 0 {
// Prevent sending ether into black hole (show stopper)
- if tx.Value.ToInt().Cmp(big.NewInt(0)) > 0 {
+ if tx.Value.ToInt().Sign() > 0 {
return nil, errors.New("transaction will create a contract with value but empty code")
}
// No value submitted at least, critically Warn, but don't blow up
diff --git a/signer/storage/aes_gcm_storage_test.go b/signer/storage/aes_gcm_storage_test.go
index 08fbf2e9d8..f02349b662 100644
--- a/signer/storage/aes_gcm_storage_test.go
+++ b/signer/storage/aes_gcm_storage_test.go
@@ -20,13 +20,13 @@ import (
"bytes"
"encoding/json"
"fmt"
+ "log/slog"
"os"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/mattn/go-colorable"
- "golang.org/x/exp/slog"
)
func TestEncryption(t *testing.T) {
diff --git a/tests/block_test.go b/tests/block_test.go
index dd2ba4dbd3..4a713b36a5 100644
--- a/tests/block_test.go
+++ b/tests/block_test.go
@@ -21,7 +21,6 @@ package tests
import (
"math/rand"
- "runtime"
"testing"
"github.com/ethereum/go-ethereum/common"
@@ -30,11 +29,11 @@ import (
func TestBlockchain(t *testing.T) {
bt := new(testMatcher)
- // General state tests are 'exported' as blockchain tests, but we can run them natively.
- // For speedier CI-runs, the line below can be uncommented, so those are skipped.
- // For now, in hardfork-times (Berlin), we run the tests both as StateTests and
- // as blockchain tests, since the latter also covers things like receipt root
- bt.skipLoad(`^GeneralStateTests/`)
+
+ // We are running most of GeneralStatetests to tests witness support, even
+ // though they are ran as state tests too. Still, the performance tests are
+ // less about state andmore about EVM number crunching, so skip those.
+ bt.skipLoad(`^GeneralStateTests/VMTests/vmPerformance`)
// Skip random failures due to selfish mining test
bt.skipLoad(`.*bcForgedTest/bcForkUncle\.json`)
@@ -59,9 +58,6 @@ func TestBlockchain(t *testing.T) {
bt.skipLoad(`.*TransitionTests*`)
bt.walk(t, blockTestDir, func(t *testing.T, name string, test *BlockTest) {
- if runtime.GOARCH == "386" && runtime.GOOS == "windows" && rand.Int63()%2 == 0 {
- t.Skip("test (randomly) skipped on 32-bit windows")
- }
execBlockTest(t, bt, test)
})
// There is also a LegacyTests folder, containing blockchain tests generated
@@ -69,33 +65,38 @@ func TestBlockchain(t *testing.T) {
// which run natively, so there's no reason to run them here.
}
-// TestExecutionSpec runs the test fixtures from execution-spec-tests.
-func TestExecutionSpec(t *testing.T) {
- if !common.FileExist(executionSpecDir) {
- t.Skipf("directory %s does not exist", executionSpecDir)
+// TestExecutionSpecBlocktests runs the test fixtures from execution-spec-tests.
+func TestExecutionSpecBlocktests(t *testing.T) {
+ if !common.FileExist(executionSpecBlockchainTestDir) {
+ t.Skipf("directory %s does not exist", executionSpecBlockchainTestDir)
}
bt := new(testMatcher)
- bt.walk(t, executionSpecDir, func(t *testing.T, name string, test *BlockTest) {
+ bt.walk(t, executionSpecBlockchainTestDir, func(t *testing.T, name string, test *BlockTest) {
execBlockTest(t, bt, test)
})
}
func execBlockTest(t *testing.T, bt *testMatcher, test *BlockTest) {
- if err := bt.checkFailure(t, test.Run(false, rawdb.HashScheme, nil, nil)); err != nil {
- t.Errorf("test in hash mode without snapshotter failed: %v", err)
- return
- }
- if err := bt.checkFailure(t, test.Run(true, rawdb.HashScheme, nil, nil)); err != nil {
- t.Errorf("test in hash mode with snapshotter failed: %v", err)
- return
+ // Define all the different flag combinations we should run the tests with,
+ // picking only one for short tests.
+ //
+ // Note, witness building and self-testing is always enabled as it's a very
+ // good test to ensure that we don't break it.
+ var (
+ snapshotConf = []bool{false, true}
+ dbschemeConf = []string{rawdb.HashScheme, rawdb.PathScheme}
+ )
+ if testing.Short() {
+ snapshotConf = []bool{snapshotConf[rand.Int()%2]}
+ dbschemeConf = []string{dbschemeConf[rand.Int()%2]}
}
- if err := bt.checkFailure(t, test.Run(false, rawdb.PathScheme, nil, nil)); err != nil {
- t.Errorf("test in path mode without snapshotter failed: %v", err)
- return
- }
- if err := bt.checkFailure(t, test.Run(true, rawdb.PathScheme, nil, nil)); err != nil {
- t.Errorf("test in path mode with snapshotter failed: %v", err)
- return
+ for _, snapshot := range snapshotConf {
+ for _, dbscheme := range dbschemeConf {
+ if err := bt.checkFailure(t, test.Run(snapshot, dbscheme, true, nil, nil)); err != nil {
+ t.Errorf("test with config {snapshotter:%v, scheme:%v} failed: %v", snapshot, dbscheme, err)
+ return
+ }
+ }
}
}
diff --git a/tests/block_test_util.go b/tests/block_test_util.go
index 0bf2e00d9a..2e0074053f 100644
--- a/tests/block_test_util.go
+++ b/tests/block_test_util.go
@@ -34,13 +34,15 @@ import (
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
+ "github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/trie"
- "github.com/ethereum/go-ethereum/trie/triedb/hashdb"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/ethereum/go-ethereum/triedb/hashdb"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
)
// A BlockTest checks handling of entire blocks.
@@ -56,8 +58,8 @@ func (t *BlockTest) UnmarshalJSON(in []byte) error {
type btJSON struct {
Blocks []btBlock `json:"blocks"`
Genesis btHeader `json:"genesisBlockHeader"`
- Pre core.GenesisAlloc `json:"pre"`
- Post core.GenesisAlloc `json:"postState"`
+ Pre types.GenesisAlloc `json:"pre"`
+ Post types.GenesisAlloc `json:"postState"`
BestBlock common.UnprefixedHash `json:"lastblockhash"`
Network string `json:"network"`
SealEngine string `json:"sealEngine"`
@@ -108,7 +110,7 @@ type btHeaderMarshaling struct {
ExcessBlobGas *math.HexOrDecimal64
}
-func (t *BlockTest) Run(snapshotter bool, scheme string, tracer vm.EVMLogger, postCheck func(error, *core.BlockChain)) (result error) {
+func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *tracing.Hooks, postCheck func(error, *core.BlockChain)) (result error) {
config, ok := Forks[t.json.Network]
if !ok {
return UnsupportedForkError{t.json.Network}
@@ -116,7 +118,7 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, tracer vm.EVMLogger, po
// import pre accounts & construct test genesis block & state root
var (
db = rawdb.NewMemoryDatabase()
- tconf = &trie.Config{
+ tconf = &triedb.Config{
Preimages: true,
}
)
@@ -127,7 +129,7 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, tracer vm.EVMLogger, po
}
// Commit genesis state
gspec := t.genesis(config)
- triedb := trie.NewDatabase(db, tconf)
+ triedb := triedb.NewDatabase(db, tconf)
gblock, err := gspec.Commit(db, triedb)
if err != nil {
return err
@@ -150,7 +152,8 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, tracer vm.EVMLogger, po
cache.SnapshotWait = true
}
chain, err := core.NewBlockChain(db, cache, gspec, nil, engine, vm.Config{
- Tracer: tracer,
+ Tracer: tracer,
+ EnableWitnessCollection: witness,
}, nil, nil, nil)
if err != nil {
return err
@@ -228,6 +231,7 @@ func (t *BlockTest) insertBlocks(blockchain *core.BlockChain) ([]btBlock, error)
cb, err := b.decode()
if err != nil {
if b.BlockHeader == nil {
+ log.Info("Block decoding failed", "index", bi, "err", err)
continue // OK - block is supposed to be invalid, continue with next block
} else {
return nil, fmt.Errorf("block RLP decoding failed when expected to succeed: %v", err)
@@ -351,7 +355,7 @@ func (t *BlockTest) validatePostState(statedb *state.StateDB) error {
for addr, acct := range t.json.Post {
// address is indirectly verified by the other fields, as it's the db key
code2 := statedb.GetCode(addr)
- balance2 := statedb.GetBalance(addr)
+ balance2 := statedb.GetBalance(addr).ToBig()
nonce2 := statedb.GetNonce(addr)
if !bytes.Equal(code2, acct.Code) {
diff --git a/tests/bor/bor_api_test.go b/tests/bor/bor_api_test.go
index 8d314193a7..c0d16e3ceb 100644
--- a/tests/bor/bor_api_test.go
+++ b/tests/bor/bor_api_test.go
@@ -24,16 +24,13 @@ import (
)
var (
- key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
- addrr = crypto.PubkeyToAddress(key1.PublicKey)
- stack, _ = node.New(&node.DefaultConfig)
- backend, _ = eth.New(stack, ðconfig.Defaults)
- db = backend.ChainDb()
- hash1 = common.BytesToHash([]byte("topic1"))
- hash2 = common.BytesToHash([]byte("topic2"))
- hash3 = common.BytesToHash([]byte("topic3"))
- hash4 = common.BytesToHash([]byte("topic4"))
- hash5 = common.BytesToHash([]byte("topic5"))
+ key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+ addrr = crypto.PubkeyToAddress(key1.PublicKey)
+ hash1 = common.BytesToHash([]byte("topic1"))
+ hash2 = common.BytesToHash([]byte("topic2"))
+ hash3 = common.BytesToHash([]byte("topic3"))
+ hash4 = common.BytesToHash([]byte("topic4"))
+ hash5 = common.BytesToHash([]byte("topic5"))
)
func duplicateInArray(arr []common.Hash) bool {
@@ -139,12 +136,9 @@ func testGetTransactionByBlockNumberAndIndex(t *testing.T, publicTransactionPool
// This Testcase tests functions for RPC API calls.
// NOTE : Changes to this function might affect the child testcases.
func TestAPIs(t *testing.T) {
-
- defer func() {
- if err := stack.Close(); err != nil {
- t.Error(err)
- }
- }()
+ stack, _ := node.New(&node.DefaultConfig)
+ backend, _ := eth.New(stack, ðconfig.Defaults)
+ db := backend.ChainDb()
genesis := core.GenesisBlockForTesting(db, addrr, big.NewInt(1000000))
testBorConfig := params.TestChainConfig.Bor
diff --git a/tests/bor/bor_sprint_length_change_test.go b/tests/bor/bor_sprint_length_change_test.go
index a031388779..16d5c73722 100644
--- a/tests/bor/bor_sprint_length_change_test.go
+++ b/tests/bor/bor_sprint_length_change_test.go
@@ -96,6 +96,12 @@ func TestValidatorsBlockProduction(t *testing.T) {
// Iterate over all the nodes and start mining
time.Sleep(3 * time.Second)
+ for _, node := range nodes {
+ if node.PeerCount() == 0 {
+ panic("Node is not connected to any peers")
+ }
+ }
+
for _, node := range nodes {
if err := node.StartMining(); err != nil {
panic(err)
@@ -117,6 +123,7 @@ func TestValidatorsBlockProduction(t *testing.T) {
// check block 7 miner ; expected author is node0 signer
blockHeaderVal0 := nodes[0].BlockChain().GetHeaderByNumber(7)
blockHeaderVal1 := nodes[1].BlockChain().GetHeaderByNumber(7)
+
authorVal0, err := nodes[0].Engine().Author(blockHeaderVal0)
if err != nil {
diff --git a/tests/bor/bor_test.go b/tests/bor/bor_test.go
index f6500fd5f2..b3ac2e58c3 100644
--- a/tests/bor/bor_test.go
+++ b/tests/bor/bor_test.go
@@ -41,7 +41,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/tests/bor/mocks"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
var (
@@ -227,12 +227,12 @@ func TestForkWithBlockTime(t *testing.T) {
{
name: "No fork after 2 sprints with producer delay = max block time",
sprint: map[string]uint64{
- "0": 128,
+ "0": 16,
},
blockTime: map[string]uint64{
- "0": 5,
- "128": 2,
- "256": 8,
+ "0": 5,
+ "16": 2,
+ "32": 8,
},
change: 2,
producerDelay: map[string]uint64{
@@ -243,11 +243,11 @@ func TestForkWithBlockTime(t *testing.T) {
{
name: "No Fork after 1 sprint producer delay = max block time",
sprint: map[string]uint64{
- "0": 64,
+ "0": 16,
},
blockTime: map[string]uint64{
"0": 5,
- "64": 2,
+ "16": 2,
},
change: 1,
producerDelay: map[string]uint64{
@@ -272,17 +272,20 @@ func TestForkWithBlockTime(t *testing.T) {
},
}
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
+ fdlimit.Raise(2048)
+
// Create an Ethash network based off of the Ropsten config
// Generate a batch of accounts to seal and fund with
faucets := make([]*ecdsa.PrivateKey, 128)
for i := 0; i < len(faucets); i++ {
faucets[i], _ = crypto.GenerateKey()
}
- genesis := InitGenesis(t, faucets, "./testdata/genesis_2val.json", 8)
for _, test := range cases {
t.Run(test.name, func(t *testing.T) {
-
+ t.Parallel()
+ genesis := InitGenesis(t, faucets, "./testdata/genesis_2val.json", 8)
genesis.Config.Bor.Sprint = test.sprint
genesis.Config.Bor.Period = test.blockTime
genesis.Config.Bor.BackupMultiplier = test.blockTime
@@ -314,6 +317,7 @@ func TestForkWithBlockTime(t *testing.T) {
defer wg.Done()
for range ticker.C {
+ log.Info("Fetching header", "node", i, "sprint", test.sprint["0"], "change", test.change, "number", test.sprint["0"]*test.change+10)
blockHeaders[i] = nodes[i].BlockChain().GetHeaderByNumber(test.sprint["0"]*test.change + 10)
if blockHeaders[i] != nil {
break
@@ -367,6 +371,10 @@ func TestForkWithBlockTime(t *testing.T) {
}
func TestInsertingSpanSizeBlocks(t *testing.T) {
+ t.Parallel()
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
+ fdlimit.Raise(2048)
+
init := buildEthereumInstance(t, rawdb.NewMemoryDatabase())
chain := init.ethereum.BlockChain()
engine := init.ethereum.Engine()
@@ -430,6 +438,10 @@ func TestInsertingSpanSizeBlocks(t *testing.T) {
}
func TestFetchStateSyncEvents(t *testing.T) {
+ t.Parallel()
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
+ fdlimit.Raise(2048)
+
init := buildEthereumInstance(t, rawdb.NewMemoryDatabase())
chain := init.ethereum.BlockChain()
engine := init.ethereum.Engine()
@@ -505,6 +517,10 @@ func validateStateSyncEvents(t *testing.T, expected []*clerk.EventRecordWithTime
}
func TestFetchStateSyncEvents_2(t *testing.T) {
+ t.Parallel()
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
+ fdlimit.Raise(2048)
+
init := buildEthereumInstance(t, rawdb.NewMemoryDatabase())
chain := init.ethereum.BlockChain()
engine := init.ethereum.Engine()
@@ -607,6 +623,10 @@ func TestFetchStateSyncEvents_2(t *testing.T) {
}
func TestOutOfTurnSigning(t *testing.T) {
+ t.Parallel()
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
+ fdlimit.Raise(2048)
+
init := buildEthereumInstance(t, rawdb.NewMemoryDatabase())
chain := init.ethereum.BlockChain()
engine := init.ethereum.Engine()
@@ -701,6 +721,9 @@ func TestOutOfTurnSigning(t *testing.T) {
}
func TestSignerNotFound(t *testing.T) {
+ t.Parallel()
+ log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelInfo, true)))
+ fdlimit.Raise(2048)
init := buildEthereumInstance(t, rawdb.NewMemoryDatabase())
chain := init.ethereum.BlockChain()
engine := init.ethereum.Engine()
@@ -772,7 +795,7 @@ func TestEIP1559Transition(t *testing.T) {
funds = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether))
gspec = &core.Genesis{
Config: params.BorUnittestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
addr1: {Balance: funds},
addr2: {Balance: funds},
addr3: {Balance: funds},
@@ -793,7 +816,7 @@ func TestEIP1559Transition(t *testing.T) {
gspec.Config.BerlinBlock = common.Big0
gspec.Config.LondonBlock = common.Big0
- genesis := gspec.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults))
+ genesis := gspec.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
signer := types.LatestSigner(gspec.Config)
blocks, _ := core.GenerateChain(gspec.Config, genesis, engine, db, 1, func(i int, b *core.BlockGen) {
@@ -821,7 +844,7 @@ func TestEIP1559Transition(t *testing.T) {
})
diskdb := rawdb.NewMemoryDatabase()
- gspec.MustCommit(diskdb, trie.NewDatabase(diskdb, trie.HashDefaults))
+ gspec.MustCommit(diskdb, triedb.NewDatabase(diskdb, triedb.HashDefaults))
chain, err := core.NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{}, nil, nil, nil)
if err != nil {
@@ -843,17 +866,17 @@ func TestEIP1559Transition(t *testing.T) {
state, _ := chain.State()
// 3: Ensure that miner received only the tx's tip.
- actual := state.GetBalance(block.Coinbase())
+ actual := state.GetBalance(block.Coinbase()).ToBig()
expected := new(big.Int).Add(
new(big.Int).SetUint64(block.GasUsed()*block.Transactions()[0].GasTipCap().Uint64()),
- ethash.ConstantinopleBlockReward,
+ ethash.ConstantinopleBlockReward.ToBig(),
)
if actual.Cmp(expected) != 0 {
t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual)
}
// check burnt contract balance
- actual = state.GetBalance(common.HexToAddress(params.BorUnittestChainConfig.Bor.CalculateBurntContract(block.NumberU64())))
+ actual = state.GetBalance(common.HexToAddress(params.BorUnittestChainConfig.Bor.CalculateBurntContract(block.NumberU64()))).ToBig()
expected = new(big.Int).Mul(new(big.Int).SetUint64(block.GasUsed()), block.BaseFee())
burntContractBalance := expected
if actual.Cmp(expected) != 0 {
@@ -861,7 +884,7 @@ func TestEIP1559Transition(t *testing.T) {
}
// 4: Ensure the tx sender paid for the gasUsed * (tip + block baseFee).
- actual = new(big.Int).Sub(funds, state.GetBalance(addr1))
+ actual = new(big.Int).Sub(funds, state.GetBalance(addr1).ToBig())
expected = new(big.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GasTipCap().Uint64() + block.BaseFee().Uint64()))
if actual.Cmp(expected) != 0 {
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
@@ -891,17 +914,17 @@ func TestEIP1559Transition(t *testing.T) {
effectiveTip := block.Transactions()[0].GasTipCap().Uint64() - block.BaseFee().Uint64()
// 6+5: Ensure that miner received only the tx's effective tip.
- actual = state.GetBalance(block.Coinbase())
+ actual = state.GetBalance(block.Coinbase()).ToBig()
expected = new(big.Int).Add(
new(big.Int).SetUint64(block.GasUsed()*effectiveTip),
- ethash.ConstantinopleBlockReward,
+ ethash.ConstantinopleBlockReward.ToBig(),
)
if actual.Cmp(expected) != 0 {
t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual)
}
// check burnt contract balance
- actual = state.GetBalance(common.HexToAddress(params.BorUnittestChainConfig.Bor.CalculateBurntContract(block.NumberU64())))
+ actual = state.GetBalance(common.HexToAddress(params.BorUnittestChainConfig.Bor.CalculateBurntContract(block.NumberU64()))).ToBig()
expected = new(big.Int).Add(burntContractBalance, new(big.Int).Mul(new(big.Int).SetUint64(block.GasUsed()), block.BaseFee()))
burntContractBalance = expected
if actual.Cmp(expected) != 0 {
@@ -909,7 +932,7 @@ func TestEIP1559Transition(t *testing.T) {
}
// 4: Ensure the tx sender paid for the gasUsed * (effectiveTip + block baseFee).
- actual = new(big.Int).Sub(funds, state.GetBalance(addr2))
+ actual = new(big.Int).Sub(funds, state.GetBalance(addr2).ToBig())
expected = new(big.Int).SetUint64(block.GasUsed() * (effectiveTip + block.BaseFee().Uint64()))
if actual.Cmp(expected) != 0 {
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
@@ -959,7 +982,7 @@ func TestEIP1559Transition(t *testing.T) {
state, _ = chain.State()
// check burnt contract balance
- actual = state.GetBalance(common.HexToAddress(params.BorUnittestChainConfig.Bor.CalculateBurntContract(block.NumberU64())))
+ actual = state.GetBalance(common.HexToAddress(params.BorUnittestChainConfig.Bor.CalculateBurntContract(block.NumberU64()))).ToBig()
burntAmount := new(big.Int).Mul(
block.BaseFee(),
big.NewInt(int64(block.GasUsed())),
@@ -971,6 +994,7 @@ func TestEIP1559Transition(t *testing.T) {
}
func TestBurnContract(t *testing.T) {
+ t.Parallel()
var (
aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa")
@@ -989,7 +1013,7 @@ func TestBurnContract(t *testing.T) {
funds = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether))
gspec = &core.Genesis{
Config: params.BorUnittestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
addr1: {Balance: funds},
addr2: {Balance: funds},
addr3: {Balance: funds},
@@ -1016,7 +1040,7 @@ func TestBurnContract(t *testing.T) {
"2": "0x000000000000000000000000000000000000aaad",
"3": "0x000000000000000000000000000000000000aaae",
}
- genesis := gspec.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults))
+ genesis := gspec.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
signer := types.LatestSigner(gspec.Config)
blocks, _ := core.GenerateChain(gspec.Config, genesis, engine, db, 1, func(i int, b *core.BlockGen) {
@@ -1044,7 +1068,7 @@ func TestBurnContract(t *testing.T) {
})
diskdb := rawdb.NewMemoryDatabase()
- gspec.MustCommit(diskdb, trie.NewDatabase(diskdb, trie.HashDefaults))
+ gspec.MustCommit(diskdb, triedb.NewDatabase(diskdb, triedb.HashDefaults))
chain, err := core.NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{}, nil, nil, nil)
if err != nil {
@@ -1066,24 +1090,24 @@ func TestBurnContract(t *testing.T) {
state, _ := chain.State()
// 3: Ensure that miner received only the tx's tip.
- actual := state.GetBalance(block.Coinbase())
+ actual := state.GetBalance(block.Coinbase()).ToBig()
expected := new(big.Int).Add(
new(big.Int).SetUint64(block.GasUsed()*block.Transactions()[0].GasTipCap().Uint64()),
- ethash.ConstantinopleBlockReward,
+ ethash.ConstantinopleBlockReward.ToBig(),
)
if actual.Cmp(expected) != 0 {
t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual)
}
// check burnt contract balance
- actual = state.GetBalance(common.HexToAddress(gspec.Config.Bor.CalculateBurntContract(block.NumberU64())))
+ actual = state.GetBalance(common.HexToAddress(gspec.Config.Bor.CalculateBurntContract(block.NumberU64()))).ToBig()
expected = new(big.Int).Mul(new(big.Int).SetUint64(block.GasUsed()), block.BaseFee())
if actual.Cmp(expected) != 0 {
t.Fatalf("burnt contract balance incorrect: expected %d, got %d", expected, actual)
}
// 4: Ensure the tx sender paid for the gasUsed * (tip + block baseFee).
- actual = new(big.Int).Sub(funds, state.GetBalance(addr1))
+ actual = new(big.Int).Sub(funds, state.GetBalance(addr1).ToBig())
expected = new(big.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GasTipCap().Uint64() + block.BaseFee().Uint64()))
if actual.Cmp(expected) != 0 {
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
@@ -1113,24 +1137,24 @@ func TestBurnContract(t *testing.T) {
effectiveTip := block.Transactions()[0].GasTipCap().Uint64() - block.BaseFee().Uint64()
// 6+5: Ensure that miner received only the tx's effective tip.
- actual = state.GetBalance(block.Coinbase())
+ actual = state.GetBalance(block.Coinbase()).ToBig()
expected = new(big.Int).Add(
new(big.Int).SetUint64(block.GasUsed()*effectiveTip),
- ethash.ConstantinopleBlockReward,
+ ethash.ConstantinopleBlockReward.ToBig(),
)
if actual.Cmp(expected) != 0 {
t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual)
}
// check burnt contract balance
- actual = state.GetBalance(common.HexToAddress(gspec.Config.Bor.CalculateBurntContract(block.NumberU64())))
+ actual = state.GetBalance(common.HexToAddress(gspec.Config.Bor.CalculateBurntContract(block.NumberU64()))).ToBig()
expected = new(big.Int).Mul(new(big.Int).SetUint64(block.GasUsed()), block.BaseFee())
if actual.Cmp(expected) != 0 {
t.Fatalf("burnt contract balance incorrect: expected %d, got %d", expected, actual)
}
// 4: Ensure the tx sender paid for the gasUsed * (effectiveTip + block baseFee).
- actual = new(big.Int).Sub(funds, state.GetBalance(addr2))
+ actual = new(big.Int).Sub(funds, state.GetBalance(addr2).ToBig())
expected = new(big.Int).SetUint64(block.GasUsed() * (effectiveTip + block.BaseFee().Uint64()))
if actual.Cmp(expected) != 0 {
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
@@ -1160,24 +1184,24 @@ func TestBurnContract(t *testing.T) {
effectiveTip = block.Transactions()[0].GasTipCap().Uint64() - block.BaseFee().Uint64()
// 6+5: Ensure that miner received only the tx's effective tip.
- actual = state.GetBalance(block.Coinbase())
+ actual = state.GetBalance(block.Coinbase()).ToBig()
expected = new(big.Int).Add(
new(big.Int).SetUint64(block.GasUsed()*effectiveTip),
- ethash.ConstantinopleBlockReward,
+ ethash.ConstantinopleBlockReward.ToBig(),
)
if actual.Cmp(expected) != 0 {
t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual)
}
// check burnt contract balance
- actual = state.GetBalance(common.HexToAddress(gspec.Config.Bor.CalculateBurntContract(block.NumberU64())))
+ actual = state.GetBalance(common.HexToAddress(gspec.Config.Bor.CalculateBurntContract(block.NumberU64()))).ToBig()
expected = new(big.Int).Mul(new(big.Int).SetUint64(block.GasUsed()), block.BaseFee())
if actual.Cmp(expected) != 0 {
t.Fatalf("burnt contract balance incorrect: expected %d, got %d", expected, actual)
}
// 4: Ensure the tx sender paid for the gasUsed * (effectiveTip + block baseFee).
- actual = new(big.Int).Sub(funds, state.GetBalance(addr3))
+ actual = new(big.Int).Sub(funds, state.GetBalance(addr3).ToBig())
expected = new(big.Int).SetUint64(block.GasUsed() * (effectiveTip + block.BaseFee().Uint64()))
if actual.Cmp(expected) != 0 {
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
@@ -1185,6 +1209,7 @@ func TestBurnContract(t *testing.T) {
}
func TestBurnContractContractFetch(t *testing.T) {
+ t.Parallel()
config := params.BorUnittestChainConfig
config.Bor.BurntContract = map[string]string{
"10": "0x000000000000000000000000000000000000aaab",
@@ -1274,7 +1299,7 @@ func TestEIP1559TransitionWithEIP155(t *testing.T) {
funds = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether))
gspec = &core.Genesis{
Config: params.BorUnittestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
addr1: {Balance: funds},
addr2: {Balance: funds},
addr3: {Balance: funds},
@@ -1293,7 +1318,7 @@ func TestEIP1559TransitionWithEIP155(t *testing.T) {
}
)
- genesis := gspec.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults))
+ genesis := gspec.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
// Use signer without chain ID
signer := types.HomesteadSigner{}
@@ -1347,7 +1372,7 @@ func TestTransitionWithoutEIP155(t *testing.T) {
funds = new(big.Int).Mul(common.Big1, big.NewInt(params.Ether))
gspec = &core.Genesis{
Config: params.BorUnittestChainConfig,
- Alloc: core.GenesisAlloc{
+ Alloc: types.GenesisAlloc{
addr1: {Balance: funds},
addr2: {Balance: funds},
addr3: {Balance: funds},
@@ -1366,7 +1391,7 @@ func TestTransitionWithoutEIP155(t *testing.T) {
}
)
- genesis := gspec.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults))
+ genesis := gspec.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
// Use signer without chain ID
signer := types.HomesteadSigner{}
@@ -1398,7 +1423,7 @@ func TestTransitionWithoutEIP155(t *testing.T) {
})
diskdb := rawdb.NewMemoryDatabase()
- gspec.MustCommit(diskdb, trie.NewDatabase(diskdb, trie.HashDefaults))
+ gspec.MustCommit(diskdb, triedb.NewDatabase(diskdb, triedb.HashDefaults))
chain, err := core.NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{}, nil, nil, nil)
if err != nil {
@@ -1414,6 +1439,7 @@ func TestTransitionWithoutEIP155(t *testing.T) {
}
func TestJaipurFork(t *testing.T) {
+ t.Parallel()
init := buildEthereumInstance(t, rawdb.NewMemoryDatabase())
chain := init.ethereum.BlockChain()
engine := init.ethereum.Engine()
diff --git a/tests/bor/helper.go b/tests/bor/helper.go
index add2a44831..73775401d6 100644
--- a/tests/bor/helper.go
+++ b/tests/bor/helper.go
@@ -44,7 +44,7 @@ import (
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/tests/bor/mocks"
- "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/triedb"
)
var (
@@ -124,18 +124,19 @@ func buildEthereumInstance(t *testing.T, db ethdb.Database) *initializeData {
}
ethConf := ð.Config{
- Genesis: gen,
- BorLogs: true,
+ Genesis: gen,
+ BorLogs: true,
+ StateScheme: "hash",
}
- ethConf.Genesis.MustCommit(db, trie.NewDatabase(db, trie.HashDefaults))
+ ethConf.Genesis.MustCommit(db, triedb.NewDatabase(db, triedb.HashDefaults))
ethereum := utils.CreateBorEthereum(ethConf)
if err != nil {
t.Fatalf("failed to register Ethereum protocol: %v", err)
}
- ethConf.Genesis.MustCommit(ethereum.ChainDb(), trie.NewDatabase(ethereum.ChainDb(), trie.HashDefaults))
+ ethConf.Genesis.MustCommit(ethereum.ChainDb(), triedb.NewDatabase(ethereum.ChainDb(), triedb.HashDefaults))
ethereum.Engine().(*bor.Bor).Authorize(addr, func(account accounts.Account, s string, data []byte) ([]byte, error) {
return crypto.Sign(crypto.Keccak256(data), key)
@@ -221,7 +222,9 @@ func buildNextBlock(t *testing.T, _bor consensus.Engine, chain *core.BlockChain,
ctx := context.Background()
// Finalize and seal the block
- block, err := _bor.FinalizeAndAssemble(ctx, chain, b.header, state, b.txs, nil, b.receipts, nil)
+ block, err := _bor.FinalizeAndAssemble(chain, b.header, state, &types.Body{
+ Transactions: b.txs,
+ }, b.receipts)
if err != nil {
panic(fmt.Sprintf("error finalizing block: %v", err))
diff --git a/tests/fuzzers/bls12381/bls12381_fuzz.go b/tests/fuzzers/bls12381/bls12381_fuzz.go
index 9a5c566540..4efc749b6f 100644
--- a/tests/fuzzers/bls12381/bls12381_fuzz.go
+++ b/tests/fuzzers/bls12381/bls12381_fuzz.go
@@ -31,10 +31,46 @@ import (
"github.com/consensys/gnark-crypto/ecc/bls12-381/fp"
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/crypto/bls12381"
+ bls12381 "github.com/kilic/bls12-381"
blst "github.com/supranational/blst/bindings/go"
)
+func fuzzG1SubgroupChecks(data []byte) int {
+ input := bytes.NewReader(data)
+ kpG1, cpG1, blG1, err := getG1Points(input)
+ if err != nil {
+ return 0
+ }
+ inSubGroupKilic := bls12381.NewG1().InCorrectSubgroup(kpG1)
+ inSubGroupGnark := cpG1.IsInSubGroup()
+ inSubGroupBLST := blG1.InG1()
+ if inSubGroupKilic != inSubGroupGnark {
+ panic(fmt.Sprintf("differing subgroup check, kilic %v, gnark %v", inSubGroupKilic, inSubGroupGnark))
+ }
+ if inSubGroupKilic != inSubGroupBLST {
+ panic(fmt.Sprintf("differing subgroup check, kilic %v, blst %v", inSubGroupKilic, inSubGroupBLST))
+ }
+ return 1
+}
+
+func fuzzG2SubgroupChecks(data []byte) int {
+ input := bytes.NewReader(data)
+ kpG2, cpG2, blG2, err := getG2Points(input)
+ if err != nil {
+ return 0
+ }
+ inSubGroupKilic := bls12381.NewG2().InCorrectSubgroup(kpG2)
+ inSubGroupGnark := cpG2.IsInSubGroup()
+ inSubGroupBLST := blG2.InG2()
+ if inSubGroupKilic != inSubGroupGnark {
+ panic(fmt.Sprintf("differing subgroup check, kilic %v, gnark %v", inSubGroupKilic, inSubGroupGnark))
+ }
+ if inSubGroupKilic != inSubGroupBLST {
+ panic(fmt.Sprintf("differing subgroup check, kilic %v, blst %v", inSubGroupKilic, inSubGroupBLST))
+ }
+ return 1
+}
+
func fuzzCrossPairing(data []byte) int {
input := bytes.NewReader(data)
@@ -51,7 +87,7 @@ func fuzzCrossPairing(data []byte) int {
}
// compute pairing using geth
- engine := bls12381.NewPairingEngine()
+ engine := bls12381.NewEngine()
engine.AddPair(kpG1, kpG2)
kResult := engine.Result()
@@ -180,7 +216,7 @@ func fuzzCrossG2Add(data []byte) int {
func fuzzCrossG1MultiExp(data []byte) int {
var (
input = bytes.NewReader(data)
- gethScalars []*big.Int
+ gethScalars []*bls12381.Fr
gnarkScalars []fr.Element
gethPoints []*bls12381.PointG1
gnarkPoints []gnark.G1Affine
@@ -197,7 +233,7 @@ func fuzzCrossG1MultiExp(data []byte) int {
if err != nil {
break
}
- gethScalars = append(gethScalars, s)
+ gethScalars = append(gethScalars, bls12381.NewFr().FromBytes(s.Bytes()))
var gnarkScalar = &fr.Element{}
gnarkScalar = gnarkScalar.SetBigInt(s)
gnarkScalars = append(gnarkScalars, *gnarkScalar)
diff --git a/tests/fuzzers/bls12381/bls12381_test.go b/tests/fuzzers/bls12381/bls12381_test.go
index 3e88979d16..fd782f7813 100644
--- a/tests/fuzzers/bls12381/bls12381_test.go
+++ b/tests/fuzzers/bls12381/bls12381_test.go
@@ -98,3 +98,15 @@ func FuzzMapG2(f *testing.F) {
fuzz(blsMapG2, data)
})
}
+
+func FuzzG1SubgroupChecks(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzzG1SubgroupChecks(data)
+ })
+}
+
+func FuzzG2SubgroupChecks(f *testing.F) {
+ f.Fuzz(func(t *testing.T, data []byte) {
+ fuzzG2SubgroupChecks(data)
+ })
+}
diff --git a/tests/fuzzers/bls12381/precompile_fuzzer.go b/tests/fuzzers/bls12381/precompile_fuzzer.go
index b2fb7f54b5..96c9ff1552 100644
--- a/tests/fuzzers/bls12381/precompile_fuzzer.go
+++ b/tests/fuzzers/bls12381/precompile_fuzzer.go
@@ -25,15 +25,15 @@ import (
)
const (
- blsG1Add = byte(10)
- blsG1Mul = byte(11)
- blsG1MultiExp = byte(12)
- blsG2Add = byte(13)
- blsG2Mul = byte(14)
- blsG2MultiExp = byte(15)
- blsPairing = byte(16)
- blsMapG1 = byte(17)
- blsMapG2 = byte(18)
+ blsG1Add = byte(11)
+ blsG1Mul = byte(12)
+ blsG1MultiExp = byte(13)
+ blsG2Add = byte(14)
+ blsG2Mul = byte(15)
+ blsG2MultiExp = byte(16)
+ blsPairing = byte(17)
+ blsMapG1 = byte(18)
+ blsMapG2 = byte(19)
)
func checkInput(id byte, inputLen int) bool {
diff --git a/tests/fuzzers/rangeproof/rangeproof-fuzzer.go b/tests/fuzzers/rangeproof/rangeproof-fuzzer.go
index ef69a4bac9..a0f3a77209 100644
--- a/tests/fuzzers/rangeproof/rangeproof-fuzzer.go
+++ b/tests/fuzzers/rangeproof/rangeproof-fuzzer.go
@@ -21,12 +21,13 @@ import (
"encoding/binary"
"fmt"
"io"
+ "slices"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb/memorydb"
"github.com/ethereum/go-ethereum/trie"
- "golang.org/x/exp/slices"
+ "github.com/ethereum/go-ethereum/triedb"
)
type kv struct {
@@ -58,7 +59,7 @@ func (f *fuzzer) readInt() uint64 {
}
func (f *fuzzer) randomTrie(n int) (*trie.Trie, map[string]*kv) {
- trie := trie.NewEmpty(trie.NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := trie.NewEmpty(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil))
vals := make(map[string]*kv)
size := f.readInt()
// Fill it with some fluff
diff --git a/tests/fuzzers/txfetcher/txfetcher_fuzzer.go b/tests/fuzzers/txfetcher/txfetcher_fuzzer.go
index 563cd52795..431c2f64e0 100644
--- a/tests/fuzzers/txfetcher/txfetcher_fuzzer.go
+++ b/tests/fuzzers/txfetcher/txfetcher_fuzzer.go
@@ -30,9 +30,8 @@ import (
)
var (
- peers []string
- txs []*types.Transaction
- testTxArrivalWait = 500 * time.Millisecond
+ peers []string
+ txs []*types.Transaction
)
func init() {
@@ -87,7 +86,6 @@ func fuzz(input []byte) int {
return make([]error, len(txs))
},
func(string, []common.Hash) error { return nil },
- testTxArrivalWait,
nil,
clock, rand,
)
diff --git a/tests/gen_stenv.go b/tests/gen_stenv.go
index 5d4208bf25..5fd3f7fbf4 100644
--- a/tests/gen_stenv.go
+++ b/tests/gen_stenv.go
@@ -16,13 +16,14 @@ var _ = (*stEnvMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (s stEnv) MarshalJSON() ([]byte, error) {
type stEnv struct {
- Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
- Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"optional"`
- Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"`
- GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
- Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
- Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
- BaseFee *math.HexOrDecimal256 `json:"currentBaseFee" gencodec:"optional"`
+ Coinbase common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
+ Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"optional"`
+ Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"`
+ GasLimit math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
+ Number math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
+ Timestamp math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
+ BaseFee *math.HexOrDecimal256 `json:"currentBaseFee" gencodec:"optional"`
+ ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas" gencodec:"optional"`
}
var enc stEnv
@@ -33,20 +34,21 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
enc.Number = math.HexOrDecimal64(s.Number)
enc.Timestamp = math.HexOrDecimal64(s.Timestamp)
enc.BaseFee = (*math.HexOrDecimal256)(s.BaseFee)
-
+ enc.ExcessBlobGas = (*math.HexOrDecimal64)(s.ExcessBlobGas)
return json.Marshal(&enc)
}
// UnmarshalJSON unmarshals from JSON.
func (s *stEnv) UnmarshalJSON(input []byte) error {
type stEnv struct {
- Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
- Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"optional"`
- Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"`
- GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
- Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
- Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
- BaseFee *math.HexOrDecimal256 `json:"currentBaseFee" gencodec:"optional"`
+ Coinbase *common.UnprefixedAddress `json:"currentCoinbase" gencodec:"required"`
+ Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"optional"`
+ Random *math.HexOrDecimal256 `json:"currentRandom" gencodec:"optional"`
+ GasLimit *math.HexOrDecimal64 `json:"currentGasLimit" gencodec:"required"`
+ Number *math.HexOrDecimal64 `json:"currentNumber" gencodec:"required"`
+ Timestamp *math.HexOrDecimal64 `json:"currentTimestamp" gencodec:"required"`
+ BaseFee *math.HexOrDecimal256 `json:"currentBaseFee" gencodec:"optional"`
+ ExcessBlobGas *math.HexOrDecimal64 `json:"currentExcessBlobGas" gencodec:"optional"`
}
var dec stEnv
@@ -87,6 +89,8 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
if dec.BaseFee != nil {
s.BaseFee = (*big.Int)(dec.BaseFee)
}
-
+ if dec.ExcessBlobGas != nil {
+ s.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
+ }
return nil
}
diff --git a/tests/init.go b/tests/init.go
index 71ab35dc9a..6be877b910 100644
--- a/tests/init.go
+++ b/tests/init.go
@@ -230,7 +230,7 @@ var Forks = map[string]*params.ChainConfig{
ArrowGlacierBlock: big.NewInt(0),
Bor: params.BorUnittestChainConfig.Bor,
},
- "ArrowGlacierToMergeAtDiffC0000": {
+ "ArrowGlacierToParisAtDiffC0000": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
@@ -266,6 +266,23 @@ var Forks = map[string]*params.ChainConfig{
GrayGlacierBlock: big.NewInt(0),
Bor: params.BorUnittestChainConfig.Bor,
},
+ "Paris": {
+ ChainID: big.NewInt(1),
+ HomesteadBlock: big.NewInt(0),
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ MuirGlacierBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ ArrowGlacierBlock: big.NewInt(0),
+ MergeNetsplitBlock: big.NewInt(0),
+ TerminalTotalDifficulty: big.NewInt(0),
+ },
"Merge": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
@@ -303,7 +320,7 @@ var Forks = map[string]*params.ChainConfig{
ShanghaiBlock: big.NewInt(0),
Bor: params.BorUnittestChainConfig.Bor,
},
- "MergeToShanghaiAtTime15k": {
+ "ParisToShanghaiAtTime15k": {
ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0),
@@ -358,6 +375,46 @@ var Forks = map[string]*params.ChainConfig{
MergeNetsplitBlock: big.NewInt(0),
TerminalTotalDifficulty: big.NewInt(0),
},
+ "Prague": {
+ ChainID: big.NewInt(1),
+ HomesteadBlock: big.NewInt(0),
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ MuirGlacierBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ ArrowGlacierBlock: big.NewInt(0),
+ MergeNetsplitBlock: big.NewInt(0),
+ TerminalTotalDifficulty: big.NewInt(0),
+ ShanghaiBlock: big.NewInt(0),
+ CancunBlock: big.NewInt(0),
+ PragueBlock: big.NewInt(0),
+ },
+ "CancunToPragueAtTime15k": {
+ ChainID: big.NewInt(1),
+ HomesteadBlock: big.NewInt(0),
+ EIP150Block: big.NewInt(0),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(0),
+ MuirGlacierBlock: big.NewInt(0),
+ BerlinBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ ArrowGlacierBlock: big.NewInt(0),
+ MergeNetsplitBlock: big.NewInt(0),
+ TerminalTotalDifficulty: big.NewInt(0),
+ ShanghaiBlock: big.NewInt(0),
+ CancunBlock: big.NewInt(0),
+ PragueBlock: big.NewInt(0),
+ },
}
// AvailableForks returns the set of defined fork names
diff --git a/tests/init_test.go b/tests/init_test.go
index 6cc0427b1d..ed4c9c1c56 100644
--- a/tests/init_test.go
+++ b/tests/init_test.go
@@ -37,15 +37,16 @@ import (
)
var (
- baseDir = filepath.Join(".", "testdata")
- blockTestDir = filepath.Join(baseDir, "BlockchainTests")
- stateTestDir = filepath.Join(baseDir, "GeneralStateTests")
- legacyStateTestDir = filepath.Join(baseDir, "LegacyTests", "Constantinople", "GeneralStateTests")
- transactionTestDir = filepath.Join(baseDir, "TransactionTests")
- rlpTestDir = filepath.Join(baseDir, "RLPTests")
- difficultyTestDir = filepath.Join(baseDir, "BasicTests")
- executionSpecDir = filepath.Join(".", "spec-tests", "fixtures")
- benchmarksDir = filepath.Join(".", "evm-benchmarks", "benchmarks")
+ baseDir = filepath.Join(".", "testdata")
+ blockTestDir = filepath.Join(baseDir, "BlockchainTests")
+ stateTestDir = filepath.Join(baseDir, "GeneralStateTests")
+ legacyStateTestDir = filepath.Join(baseDir, "LegacyTests", "Constantinople", "GeneralStateTests")
+ transactionTestDir = filepath.Join(baseDir, "TransactionTests")
+ rlpTestDir = filepath.Join(baseDir, "RLPTests")
+ difficultyTestDir = filepath.Join(baseDir, "BasicTests")
+ executionSpecBlockchainTestDir = filepath.Join(".", "spec-tests", "fixtures", "blockchain_tests")
+ executionSpecStateTestDir = filepath.Join(".", "spec-tests", "fixtures", "state_tests")
+ benchmarksDir = filepath.Join(".", "evm-benchmarks", "benchmarks")
)
func readJSON(reader io.Reader, value interface{}) error {
@@ -110,7 +111,7 @@ type testFailure struct {
reason string
}
-// skipShortMode skips tests matching when the -short flag is used.
+// slow adds expected slow tests matching the pattern.
func (tm *testMatcher) slow(pattern string) {
tm.slowpat = append(tm.slowpat, regexp.MustCompile(pattern))
}
diff --git a/tests/state_test.go b/tests/state_test.go
index 575f322007..01760eeb08 100644
--- a/tests/state_test.go
+++ b/tests/state_test.go
@@ -28,24 +28,20 @@ import (
"os"
"path/filepath"
"reflect"
- "runtime"
"strings"
"testing"
"time"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/core/state"
- "github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers/logger"
+ "github.com/holiman/uint256"
)
-func TestState(t *testing.T) {
- t.Parallel()
-
- st := new(testMatcher)
+func initMatcher(st *testMatcher) {
// Long tests:
st.slow(`^stAttackTest/ContractCreationSpam`)
st.slow(`^stBadOpcode/badOpcodes`)
@@ -122,79 +118,120 @@ func TestState(t *testing.T) {
// EOF is not part of cancun
st.skipLoad(`^stEOF/`)
- // EIP-4844 tests need to be regenerated due to the data-to-blob rename
- st.skipLoad(`^stEIP4844-blobtransactions/`)
+ // The tests under Pyspecs are the ones that are published as execution-spec tests.
+ // We run these tests separately, no need to _also_ run them as part of the
+ // reference tests.
+ st.skipLoad(`^Pyspecs/`)
+}
- // Expected failures:
- // These EIP-4844 tests need to be regenerated.
- st.fails(`stEIP4844-blobtransactions/opcodeBlobhashOutOfRange.json`, "test has incorrect state root")
- st.fails(`stEIP4844-blobtransactions/opcodeBlobhBounds.json`, "test has incorrect state root")
+func TestState(t *testing.T) {
+ t.Parallel()
- // For Istanbul, older tests were moved into LegacyTests
+ st := new(testMatcher)
+ initMatcher(st)
for _, dir := range []string{
filepath.Join(baseDir, "EIPTests", "StateTests"),
stateTestDir,
- legacyStateTestDir,
benchmarksDir,
} {
st.walk(t, dir, func(t *testing.T, name string, test *StateTest) {
- if runtime.GOARCH == "386" && runtime.GOOS == "windows" && rand.Int63()%2 == 0 {
- t.Skip("test (randomly) skipped on 32-bit windows")
- return
+ execStateTest(t, st, test)
+ })
+ }
+}
+
+// TestLegacyState tests some older tests, which were moved to the folder
+// 'LegacyTests' for the Istanbul fork.
+func TestLegacyState(t *testing.T) {
+ st := new(testMatcher)
+ initMatcher(st)
+ st.walk(t, legacyStateTestDir, func(t *testing.T, name string, test *StateTest) {
+ execStateTest(t, st, test)
+ })
+}
+
+// TestExecutionSpecState runs the test fixtures from execution-spec-tests.
+func TestExecutionSpecState(t *testing.T) {
+ if !common.FileExist(executionSpecStateTestDir) {
+ t.Skipf("directory %s does not exist", executionSpecStateTestDir)
+ }
+ st := new(testMatcher)
+
+ st.walk(t, executionSpecStateTestDir, func(t *testing.T, name string, test *StateTest) {
+ execStateTest(t, st, test)
+ })
+}
+
+func execStateTest(t *testing.T, st *testMatcher, test *StateTest) {
+ for _, subtest := range test.Subtests() {
+ subtest := subtest
+ key := fmt.Sprintf("%s/%d", subtest.Fork, subtest.Index)
+
+ // If -short flag is used, we don't execute all four permutations, only
+ // one.
+ executionMask := 0xf
+ if testing.Short() {
+ executionMask = (1 << (rand.Int63() & 4))
+ }
+ t.Run(key+"/hash/trie", func(t *testing.T) {
+ if executionMask&0x1 == 0 {
+ t.Skip("test (randomly) skipped due to short-tag")
}
- for _, subtest := range test.Subtests() {
- subtest := subtest
- key := fmt.Sprintf("%s/%d", subtest.Fork, subtest.Index)
-
- t.Run(key+"/hash/trie", func(t *testing.T) {
- withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
- var result error
- test.Run(subtest, vmconfig, false, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
- result = st.checkFailure(t, err)
- })
- return result
- })
- })
- t.Run(key+"/hash/snap", func(t *testing.T) {
- withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
- var result error
- test.Run(subtest, vmconfig, true, rawdb.HashScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
- if snaps != nil && state != nil {
- if _, err := snaps.Journal(state.IntermediateRoot(false)); err != nil {
- result = err
- return
- }
- }
- result = st.checkFailure(t, err)
- })
- return result
- })
+ withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
+ var result error
+ test.Run(subtest, vmconfig, false, rawdb.HashScheme, func(err error, state *StateTestState) {
+ result = st.checkFailure(t, err)
})
- t.Run(key+"/path/trie", func(t *testing.T) {
- withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
- var result error
- test.Run(subtest, vmconfig, false, rawdb.PathScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
- result = st.checkFailure(t, err)
- })
- return result
- })
+ return result
+ })
+ })
+ t.Run(key+"/hash/snap", func(t *testing.T) {
+ if executionMask&0x2 == 0 {
+ t.Skip("test (randomly) skipped due to short-tag")
+ }
+ withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
+ var result error
+ test.Run(subtest, vmconfig, true, rawdb.HashScheme, func(err error, state *StateTestState) {
+ if state.Snapshots != nil && state.StateDB != nil {
+ if _, err := state.Snapshots.Journal(state.StateDB.IntermediateRoot(false)); err != nil {
+ result = err
+ return
+ }
+ }
+ result = st.checkFailure(t, err)
})
- t.Run(key+"/path/snap", func(t *testing.T) {
- withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
- var result error
- test.Run(subtest, vmconfig, true, rawdb.PathScheme, func(err error, snaps *snapshot.Tree, state *state.StateDB) {
- if snaps != nil && state != nil {
- if _, err := snaps.Journal(state.IntermediateRoot(false)); err != nil {
- result = err
- return
- }
- }
- result = st.checkFailure(t, err)
- })
- return result
- })
+ return result
+ })
+ })
+ t.Run(key+"/path/trie", func(t *testing.T) {
+ if executionMask&0x4 == 0 {
+ t.Skip("test (randomly) skipped due to short-tag")
+ }
+ withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
+ var result error
+ test.Run(subtest, vmconfig, false, rawdb.PathScheme, func(err error, state *StateTestState) {
+ result = st.checkFailure(t, err)
})
+ return result
+ })
+ })
+ t.Run(key+"/path/snap", func(t *testing.T) {
+ if executionMask&0x8 == 0 {
+ t.Skip("test (randomly) skipped due to short-tag")
}
+ withTrace(t, test.gasLimit(subtest), func(vmconfig vm.Config) error {
+ var result error
+ test.Run(subtest, vmconfig, true, rawdb.PathScheme, func(err error, state *StateTestState) {
+ if state.Snapshots != nil && state.StateDB != nil {
+ if _, err := state.Snapshots.Journal(state.StateDB.IntermediateRoot(false)); err != nil {
+ result = err
+ return
+ }
+ }
+ result = st.checkFailure(t, err)
+ })
+ return result
+ })
})
}
}
@@ -289,8 +326,8 @@ func runBenchmark(b *testing.B, t *StateTest) {
vmconfig.ExtraEips = eips
block := t.genesis(config).ToBlock()
- triedb, _, statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, false, rawdb.HashScheme)
- defer triedb.Close()
+ state := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, false, rawdb.HashScheme)
+ defer state.Close()
var baseFee *big.Int
if rules.IsLondon {
@@ -328,7 +365,7 @@ func runBenchmark(b *testing.B, t *StateTest) {
context := core.NewEVMBlockContext(block.Header(), nil, &t.json.Env.Coinbase)
context.GetHash = vmTestBlockHash
context.BaseFee = baseFee
- evm := vm.NewEVM(context, txContext, statedb, config, vmconfig)
+ evm := vm.NewEVM(context, txContext, state.StateDB, config, vmconfig)
// Create "contract" for sender to cache code analysis.
sender := vm.NewContract(vm.AccountRef(msg.From), vm.AccountRef(msg.From),
@@ -341,13 +378,13 @@ func runBenchmark(b *testing.B, t *StateTest) {
)
b.ResetTimer()
for n := 0; n < b.N; n++ {
- snapshot := statedb.Snapshot()
- statedb.Prepare(rules, msg.From, context.Coinbase, msg.To, vm.ActivePrecompiles(rules), msg.AccessList)
+ snapshot := state.StateDB.Snapshot()
+ state.StateDB.Prepare(rules, msg.From, context.Coinbase, msg.To, vm.ActivePrecompiles(rules), msg.AccessList)
b.StartTimer()
start := time.Now()
// Execute the message.
- _, leftOverGas, err := evm.Call(sender, *msg.To, msg.Data, msg.GasLimit, msg.Value, nil)
+ _, leftOverGas, err := evm.Call(sender, *msg.To, msg.Data, msg.GasLimit, uint256.MustFromBig(msg.Value), nil)
if err != nil {
b.Error(err)
return
@@ -355,10 +392,10 @@ func runBenchmark(b *testing.B, t *StateTest) {
b.StopTimer()
elapsed += uint64(time.Since(start))
- refund += statedb.GetRefund()
+ refund += state.StateDB.GetRefund()
gasUsed += msg.GasLimit - leftOverGas
- statedb.RevertToSnapshot(snapshot)
+ state.StateDB.RevertToSnapshot(snapshot)
}
if elapsed < 1 {
elapsed = 1
diff --git a/tests/state_test_util.go b/tests/state_test_util.go
index fbb35a2fbb..d6154227d1 100644
--- a/tests/state_test_util.go
+++ b/tests/state_test_util.go
@@ -25,24 +25,26 @@ import (
"strconv"
"strings"
- "golang.org/x/crypto/sha3"
-
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/state/snapshot"
+ "github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/trie"
- "github.com/ethereum/go-ethereum/trie/triedb/hashdb"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/ethereum/go-ethereum/triedb"
+ "github.com/ethereum/go-ethereum/triedb/hashdb"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
+ "github.com/holiman/uint256"
+ "golang.org/x/crypto/sha3"
)
// StateTest checks transaction processing without block context.
@@ -63,7 +65,7 @@ func (t *StateTest) UnmarshalJSON(in []byte) error {
type stJSON struct {
Env stEnv `json:"env"`
- Pre core.GenesisAlloc `json:"pre"`
+ Pre types.GenesisAlloc `json:"pre"`
Tx stTransaction `json:"transaction"`
Out hexutil.Bytes `json:"out"`
Post map[string][]stPostState `json:"post"`
@@ -84,23 +86,25 @@ type stPostState struct {
//go:generate go run github.com/fjl/gencodec -type stEnv -field-override stEnvMarshaling -out gen_stenv.go
type stEnv struct {
- Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
- Difficulty *big.Int `json:"currentDifficulty" gencodec:"optional"`
- Random *big.Int `json:"currentRandom" gencodec:"optional"`
- GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
- Number uint64 `json:"currentNumber" gencodec:"required"`
- Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
- BaseFee *big.Int `json:"currentBaseFee" gencodec:"optional"`
+ Coinbase common.Address `json:"currentCoinbase" gencodec:"required"`
+ Difficulty *big.Int `json:"currentDifficulty" gencodec:"optional"`
+ Random *big.Int `json:"currentRandom" gencodec:"optional"`
+ GasLimit uint64 `json:"currentGasLimit" gencodec:"required"`
+ Number uint64 `json:"currentNumber" gencodec:"required"`
+ Timestamp uint64 `json:"currentTimestamp" gencodec:"required"`
+ BaseFee *big.Int `json:"currentBaseFee" gencodec:"optional"`
+ ExcessBlobGas *uint64 `json:"currentExcessBlobGas" gencodec:"optional"`
}
type stEnvMarshaling struct {
- Coinbase common.UnprefixedAddress
- Difficulty *math.HexOrDecimal256
- Random *math.HexOrDecimal256
- GasLimit math.HexOrDecimal64
- Number math.HexOrDecimal64
- Timestamp math.HexOrDecimal64
- BaseFee *math.HexOrDecimal256
+ Coinbase common.UnprefixedAddress
+ Difficulty *math.HexOrDecimal256
+ Random *math.HexOrDecimal256
+ GasLimit math.HexOrDecimal64
+ Number math.HexOrDecimal64
+ Timestamp math.HexOrDecimal64
+ BaseFee *math.HexOrDecimal256
+ ExcessBlobGas *math.HexOrDecimal64
}
//go:generate go run github.com/fjl/gencodec -type stTransaction -field-override stTransactionMarshaling -out gen_sttransaction.go
@@ -201,20 +205,14 @@ func (t *StateTest) checkError(subtest StateSubtest, err error) error {
}
// Run executes a specific subtest and verifies the post-state and logs
-func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string, postCheck func(err error, snaps *snapshot.Tree, state *state.StateDB)) (result error) {
- triedb, snaps, statedb, root, err := t.RunNoVerify(subtest, vmconfig, snapshotter, scheme)
-
+func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string, postCheck func(err error, st *StateTestState)) (result error) {
+ st, root, err := t.RunNoVerify(subtest, vmconfig, snapshotter, scheme)
// Invoke the callback at the end of function for further analysis.
defer func() {
- postCheck(result, snaps, statedb)
-
- if triedb != nil {
- triedb.Close()
- }
- if snaps != nil {
- snaps.Release()
- }
+ postCheck(result, &st)
+ st.Close()
}()
+
checkedErr := t.checkError(subtest, err)
if checkedErr != nil {
return checkedErr
@@ -232,25 +230,25 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bo
if root != common.Hash(post.Root) {
return fmt.Errorf("post state root mismatch: got %x, want %x", root, post.Root)
}
-
- if logs := rlpHash(statedb.Logs()); logs != common.Hash(post.Logs) {
+ if logs := rlpHash(st.StateDB.Logs()); logs != common.Hash(post.Logs) {
return fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, post.Logs)
}
- statedb, _ = state.New(root, statedb.Database(), snaps)
+ st.StateDB, _ = state.New(root, st.StateDB.Database(), st.Snapshots)
return nil
}
-// RunNoVerify runs a specific subtest and returns the statedb and post-state root
-func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string) (*trie.Database, *snapshot.Tree, *state.StateDB, common.Hash, error) {
+// RunNoVerify runs a specific subtest and returns the statedb and post-state root.
+// Remember to call state.Close after verifying the test result!
+func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapshotter bool, scheme string) (st StateTestState, root common.Hash, err error) {
config, eips, err := GetChainConfig(subtest.Fork)
if err != nil {
- return nil, nil, nil, common.Hash{}, UnsupportedForkError{subtest.Fork}
+ return st, common.Hash{}, UnsupportedForkError{subtest.Fork}
}
vmconfig.ExtraEips = eips
block := t.genesis(config).ToBlock()
- triedb, snaps, statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, snapshotter, scheme)
+ st = MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, snapshotter, scheme)
var baseFee *big.Int
if config.IsLondon(new(big.Int)) {
@@ -266,8 +264,18 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
msg, err := t.json.Tx.toMessage(post, baseFee)
if err != nil {
- triedb.Close()
- return nil, nil, nil, common.Hash{}, err
+ return st, common.Hash{}, err
+ }
+
+ { // Blob transactions may be present after the Cancun fork.
+ // In production,
+ // - the header is verified against the max in eip4844.go:VerifyEIP4844Header
+ // - the block body is verified against the header in block_validator.go:ValidateBody
+ // Here, we just do this shortcut smaller fix, since state tests do not
+ // utilize those codepaths
+ if len(msg.BlobHashes)*params.BlobTxBlobGasPerBlob > params.MaxBlobGasPerBlock {
+ return st, common.Hash{}, errors.New("blob gas exceeds maximum")
+ }
}
// Try to recover tx with current signer
@@ -276,13 +284,10 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
err := ttx.UnmarshalBinary(post.TxBytes)
if err != nil {
- triedb.Close()
- return nil, nil, nil, common.Hash{}, err
+ return st, common.Hash{}, err
}
-
if _, err := types.Sender(types.LatestSigner(config), &ttx); err != nil {
- triedb.Close()
- return nil, nil, nil, common.Hash{}, err
+ return st, common.Hash{}, err
}
}
@@ -302,28 +307,38 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
context.Random = &rnd
context.Difficulty = big.NewInt(0)
}
+ if config.IsCancun(block.Number()) && t.json.Env.ExcessBlobGas != nil {
+ context.BlobBaseFee = eip4844.CalcBlobFee(*t.json.Env.ExcessBlobGas)
+ }
+ evm := vm.NewEVM(context, txContext, st.StateDB, config, vmconfig)
- evm := vm.NewEVM(context, txContext, statedb, config, vmconfig)
-
+ if tracer := vmconfig.Tracer; tracer != nil && tracer.OnTxStart != nil {
+ tracer.OnTxStart(evm.GetVMContext(), nil, msg.From)
+ if evm.Config.Tracer.OnTxEnd != nil {
+ defer func() {
+ evm.Config.Tracer.OnTxEnd(nil, err)
+ }()
+ }
+ }
// Execute the message.
- snapshot := statedb.Snapshot()
+ snapshot := st.StateDB.Snapshot()
gaspool := new(core.GasPool)
gaspool.AddGas(block.GasLimit())
_, err = core.ApplyMessage(evm, msg, gaspool, nil)
if err != nil {
- statedb.RevertToSnapshot(snapshot)
+ st.StateDB.RevertToSnapshot(snapshot)
}
// Add 0-value mining reward. This only makes a difference in the cases
// where
// - the coinbase self-destructed, or
// - there are only 'bad' transactions, which aren't executed. In those cases,
// the coinbase gets no txfee, so isn't created, and thus needs to be touched
- statedb.AddBalance(block.Coinbase(), new(big.Int))
+ st.StateDB.AddBalance(block.Coinbase(), new(uint256.Int), tracing.BalanceChangeUnspecified)
// Commit state mutations into database.
- root, _ := statedb.Commit(block.NumberU64(), config.IsEIP158(block.Number()))
- return triedb, snaps, statedb, root, err
+ root, _ = st.StateDB.Commit(block.NumberU64(), config.IsEIP158(block.Number()))
+ return st, root, err
}
// nolint:unused
@@ -331,44 +346,6 @@ func (t *StateTest) gasLimit(subtest StateSubtest) uint64 {
return t.json.Tx.GasLimit[t.json.Post[subtest.Fork][subtest.Index].Indexes.Gas]
}
-func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter bool, scheme string) (*trie.Database, *snapshot.Tree, *state.StateDB) {
- tconf := &trie.Config{Preimages: true}
- if scheme == rawdb.HashScheme {
- tconf.HashDB = hashdb.Defaults
- } else {
- tconf.PathDB = pathdb.Defaults
- }
- triedb := trie.NewDatabase(db, tconf)
- sdb := state.NewDatabaseWithNodeDB(db, triedb)
- statedb, _ := state.New(types.EmptyRootHash, sdb, nil)
- for addr, a := range accounts {
- statedb.SetCode(addr, a.Code)
- statedb.SetNonce(addr, a.Nonce)
- statedb.SetBalance(addr, a.Balance)
-
- for k, v := range a.Storage {
- statedb.SetState(addr, k, v)
- }
- }
- // Commit and re-open to start with a clean state.
- root, _ := statedb.Commit(0, false)
-
- var snaps *snapshot.Tree
-
- if snapshotter {
- snapconfig := snapshot.Config{
- CacheSize: 1,
- Recovery: false,
- NoBuild: false,
- AsyncBuild: false,
- }
- snaps, _ = snapshot.New(snapconfig, db, triedb, root)
- }
-
- statedb, _ = state.New(root, sdb, snaps)
- return triedb, snaps, statedb
-}
-
func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis {
genesis := &core.Genesis{
Config: config,
@@ -501,3 +478,61 @@ func rlpHash(x interface{}) (h common.Hash) {
func vmTestBlockHash(n uint64) common.Hash {
return common.BytesToHash(crypto.Keccak256([]byte(big.NewInt(int64(n)).String())))
}
+
+// StateTestState groups all the state database objects together for use in tests.
+type StateTestState struct {
+ StateDB *state.StateDB
+ TrieDB *triedb.Database
+ Snapshots *snapshot.Tree
+}
+
+// MakePreState creates a state containing the given allocation.
+func MakePreState(db ethdb.Database, accounts types.GenesisAlloc, snapshotter bool, scheme string) StateTestState {
+ tconf := &triedb.Config{Preimages: true}
+ if scheme == rawdb.HashScheme {
+ tconf.HashDB = hashdb.Defaults
+ } else {
+ tconf.PathDB = pathdb.Defaults
+ }
+ triedb := triedb.NewDatabase(db, tconf)
+ sdb := state.NewDatabaseWithNodeDB(db, triedb)
+ statedb, _ := state.New(types.EmptyRootHash, sdb, nil)
+ for addr, a := range accounts {
+ statedb.SetCode(addr, a.Code)
+ statedb.SetNonce(addr, a.Nonce)
+ statedb.SetBalance(addr, uint256.MustFromBig(a.Balance), tracing.BalanceChangeUnspecified)
+ for k, v := range a.Storage {
+ statedb.SetState(addr, k, v)
+ }
+ }
+ // Commit and re-open to start with a clean state.
+ root, _ := statedb.Commit(0, false)
+
+ // If snapshot is requested, initialize the snapshotter and use it in state.
+ var snaps *snapshot.Tree
+ if snapshotter {
+ snapconfig := snapshot.Config{
+ CacheSize: 1,
+ Recovery: false,
+ NoBuild: false,
+ AsyncBuild: false,
+ }
+ snaps, _ = snapshot.New(snapconfig, db, triedb, root)
+ }
+ statedb, _ = state.New(root, sdb, snaps)
+ return StateTestState{statedb, triedb, snaps}
+}
+
+// Close should be called when the state is no longer needed, ie. after running the test.
+func (st *StateTestState) Close() {
+ if st.TrieDB != nil {
+ st.TrieDB.Close()
+ st.TrieDB = nil
+ }
+ if st.Snapshots != nil {
+ // Need to call Disable here to quit the snapshot generator goroutine.
+ st.Snapshots.Disable()
+ st.Snapshots.Release()
+ st.Snapshots = nil
+ }
+}
diff --git a/trie/committer.go b/trie/committer.go
index 0c5dfb922e..6a50791e67 100644
--- a/trie/committer.go
+++ b/trie/committer.go
@@ -161,12 +161,12 @@ func (c *committer) store(path []byte, n node) node {
return hash
}
-// mptResolver the children resolver in merkle-patricia-tree.
-type mptResolver struct{}
+// MerkleResolver the children resolver in merkle-patricia-tree.
+type MerkleResolver struct{}
// ForEach implements childResolver, decodes the provided node and
// traverses the children inside.
-func (resolver mptResolver) ForEach(node []byte, onChild func(common.Hash)) {
+func (resolver MerkleResolver) ForEach(node []byte, onChild func(common.Hash)) {
forGatherChildren(mustDecodeNodeUnsafe(nil, node), onChild)
}
diff --git a/trie/database_test.go b/trie/database_test.go
index d508c65533..aed508b368 100644
--- a/trie/database_test.go
+++ b/trie/database_test.go
@@ -17,24 +17,136 @@
package trie
import (
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
- "github.com/ethereum/go-ethereum/trie/triedb/hashdb"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/ethereum/go-ethereum/triedb/database"
)
-// newTestDatabase initializes the trie database with specified scheme.
-func newTestDatabase(diskdb ethdb.Database, scheme string) *Database {
- config := &Config{Preimages: false}
- if scheme == rawdb.HashScheme {
- config.HashDB = &hashdb.Config{
- CleanCacheSize: 0,
- } // disable clean cache
- } else {
- config.PathDB = &pathdb.Config{
- CleanCacheSize: 0,
- DirtyCacheSize: 0,
- } // disable clean/dirty cache
- }
- return NewDatabase(diskdb, config)
+// testReader implements database.Reader interface, providing function to
+// access trie nodes.
+type testReader struct {
+ db ethdb.Database
+ scheme string
+ nodes []*trienode.MergedNodeSet // sorted from new to old
+}
+
+// Node implements database.Reader interface, retrieving trie node with
+// all available cached layers.
+func (r *testReader) Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, error) {
+ // Check the node presence with the cached layer, from latest to oldest.
+ for _, nodes := range r.nodes {
+ if _, ok := nodes.Sets[owner]; !ok {
+ continue
+ }
+ n, ok := nodes.Sets[owner].Nodes[string(path)]
+ if !ok {
+ continue
+ }
+ if n.IsDeleted() || n.Hash != hash {
+ return nil, &MissingNodeError{Owner: owner, Path: path, NodeHash: hash}
+ }
+ return n.Blob, nil
+ }
+ // Check the node presence in database.
+ return rawdb.ReadTrieNode(r.db, owner, path, hash, r.scheme), nil
+}
+
+// testDb implements database.Database interface, using for testing purpose.
+type testDb struct {
+ disk ethdb.Database
+ root common.Hash
+ scheme string
+ nodes map[common.Hash]*trienode.MergedNodeSet
+ parents map[common.Hash]common.Hash
+}
+
+func newTestDatabase(diskdb ethdb.Database, scheme string) *testDb {
+ return &testDb{
+ disk: diskdb,
+ root: types.EmptyRootHash,
+ scheme: scheme,
+ nodes: make(map[common.Hash]*trienode.MergedNodeSet),
+ parents: make(map[common.Hash]common.Hash),
+ }
+}
+
+func (db *testDb) Reader(stateRoot common.Hash) (database.Reader, error) {
+ nodes, _ := db.dirties(stateRoot, true)
+ return &testReader{db: db.disk, scheme: db.scheme, nodes: nodes}, nil
+}
+
+func (db *testDb) Preimage(hash common.Hash) []byte {
+ return rawdb.ReadPreimage(db.disk, hash)
+}
+
+func (db *testDb) InsertPreimage(preimages map[common.Hash][]byte) {
+ rawdb.WritePreimages(db.disk, preimages)
+}
+
+func (db *testDb) Scheme() string { return db.scheme }
+
+func (db *testDb) Update(root common.Hash, parent common.Hash, nodes *trienode.MergedNodeSet) error {
+ if root == parent {
+ return nil
+ }
+ if _, ok := db.nodes[root]; ok {
+ return nil
+ }
+ db.parents[root] = parent
+ db.nodes[root] = nodes
+ return nil
+}
+
+func (db *testDb) dirties(root common.Hash, topToBottom bool) ([]*trienode.MergedNodeSet, []common.Hash) {
+ var (
+ pending []*trienode.MergedNodeSet
+ roots []common.Hash
+ )
+ for {
+ if root == db.root {
+ break
+ }
+ nodes, ok := db.nodes[root]
+ if !ok {
+ break
+ }
+ if topToBottom {
+ pending = append(pending, nodes)
+ roots = append(roots, root)
+ } else {
+ pending = append([]*trienode.MergedNodeSet{nodes}, pending...)
+ roots = append([]common.Hash{root}, roots...)
+ }
+ root = db.parents[root]
+ }
+ return pending, roots
+}
+
+func (db *testDb) Commit(root common.Hash) error {
+ if root == db.root {
+ return nil
+ }
+ pending, roots := db.dirties(root, false)
+ for i, nodes := range pending {
+ for owner, set := range nodes.Sets {
+ if owner == (common.Hash{}) {
+ continue
+ }
+ set.ForEachWithOrder(func(path string, n *trienode.Node) {
+ rawdb.WriteTrieNode(db.disk, owner, []byte(path), n.Hash, n.Blob, db.scheme)
+ })
+ }
+ nodes.Sets[common.Hash{}].ForEachWithOrder(func(path string, n *trienode.Node) {
+ rawdb.WriteTrieNode(db.disk, common.Hash{}, []byte(path), n.Hash, n.Blob, db.scheme)
+ })
+ db.root = roots[i]
+ }
+ for _, root := range roots {
+ delete(db.nodes, root)
+ delete(db.parents, root)
+ }
+ return nil
}
diff --git a/trie/errors.go b/trie/errors.go
index 82066b6faf..f683cd7ee1 100644
--- a/trie/errors.go
+++ b/trie/errors.go
@@ -23,7 +23,7 @@ import (
"github.com/ethereum/go-ethereum/common"
)
-// ErrCommitted is returned when a already committed trie is requested for usage.
+// ErrCommitted is returned when an already committed trie is requested for usage.
// The potential usages can be `Get`, `Update`, `Delete`, `NodeIterator`, `Prove`
// and so on.
var ErrCommitted = errors.New("trie is already committed")
diff --git a/trie/hasher.go b/trie/hasher.go
index 097c62680c..38de12ce9d 100644
--- a/trie/hasher.go
+++ b/trie/hasher.go
@@ -19,8 +19,6 @@ package trie
import (
"sync"
- "golang.org/x/crypto/sha3"
-
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -39,7 +37,7 @@ var hasherPool = sync.Pool{
New: func() interface{} {
return &hasher{
tmp: make([]byte, 0, 550), // cap is as large as a full fullNode.
- sha: sha3.NewLegacyKeccak256().(crypto.KeccakState),
+ sha: crypto.NewKeccakState(),
encbuf: rlp.NewEncoderBuffer(nil),
}
},
diff --git a/trie/iterator.go b/trie/iterator.go
index be32aaa028..be8a0eba69 100644
--- a/trie/iterator.go
+++ b/trie/iterator.go
@@ -138,7 +138,7 @@ type nodeIteratorState struct {
node node // Trie node being iterated
parent common.Hash // Hash of the first full ancestor node (nil if current is the root)
index int // Child to be processed next
- pathlen int // Length of the path to this node
+ pathlen int // Length of the path to the parent node
}
type nodeIterator struct {
@@ -148,7 +148,7 @@ type nodeIterator struct {
err error // Failure set in case of an internal error in the iterator
resolver NodeResolver // optional node resolver for avoiding disk hits
- pool []*nodeIteratorState // local pool for iteratorstates
+ pool []*nodeIteratorState // local pool for iterator states
}
// errIteratorEnd is stored in nodeIterator.err when iteration is done.
@@ -324,6 +324,7 @@ func (it *nodeIterator) seek(prefix []byte) error {
// The path we're looking for is the hex encoded key without terminator.
key := keybytesToHex(prefix)
key = key[:len(key)-1]
+
// Move forward until we're just before the closest match to key.
for {
state, parentIndex, path, err := it.peekSeek(key)
@@ -331,7 +332,7 @@ func (it *nodeIterator) seek(prefix []byte) error {
return errIteratorEnd
} else if err != nil {
return seekError{prefix, err}
- } else if bytes.Compare(path, key) >= 0 {
+ } else if reachedPath(path, key) {
return nil
}
@@ -363,7 +364,6 @@ func (it *nodeIterator) peek(descend bool) (*nodeIteratorState, *int, []byte, er
// If we're skipping children, pop the current node first
it.pop()
}
-
// Continue iteration to the next child
for len(it.stack) > 0 {
parent := it.stack[len(it.stack)-1]
@@ -401,7 +401,6 @@ func (it *nodeIterator) peekSeek(seekKey []byte) (*nodeIteratorState, *int, []by
// If we're skipping children, pop the current node first
it.pop()
}
-
// Continue iteration to the next child
for len(it.stack) > 0 {
parent := it.stack[len(it.stack)-1]
@@ -484,17 +483,18 @@ func (it *nodeIterator) findChild(n *fullNode, index int, ancestor common.Hash)
state *nodeIteratorState
childPath []byte
)
-
- for ; index < len(n.Children); index++ {
+ for ; index < len(n.Children); index = nextChildIndex(index) {
if n.Children[index] != nil {
child = n.Children[index]
hash, _ := child.cache()
+
state = it.getFromPool()
state.hash = common.BytesToHash(hash)
state.node = child
state.parent = ancestor
state.index = -1
state.pathlen = len(path)
+
childPath = append(childPath, path...)
childPath = append(childPath, byte(index))
@@ -509,8 +509,8 @@ func (it *nodeIterator) nextChild(parent *nodeIteratorState, ancestor common.Has
switch node := parent.node.(type) {
case *fullNode:
// Full node, move to the first non-nil child.
- if child, state, path, index := it.findChild(node, parent.index+1, ancestor); child != nil {
- parent.index = index - 1
+ if child, state, path, index := it.findChild(node, nextChildIndex(parent.index), ancestor); child != nil {
+ parent.index = prevChildIndex(index)
return state, path, true
}
case *shortNode:
@@ -538,23 +538,23 @@ func (it *nodeIterator) nextChildAt(parent *nodeIteratorState, ancestor common.H
switch n := parent.node.(type) {
case *fullNode:
// Full node, move to the first non-nil child before the desired key position
- child, state, path, index := it.findChild(n, parent.index+1, ancestor)
+ child, state, path, index := it.findChild(n, nextChildIndex(parent.index), ancestor)
if child == nil {
// No more children in this fullnode
return parent, it.path, false
}
// If the child we found is already past the seek position, just return it.
- if bytes.Compare(path, key) >= 0 {
- parent.index = index - 1
+ if reachedPath(path, key) {
+ parent.index = prevChildIndex(index)
return state, path, true
}
// The child is before the seek position. Try advancing
for {
- nextChild, nextState, nextPath, nextIndex := it.findChild(n, index+1, ancestor)
+ nextChild, nextState, nextPath, nextIndex := it.findChild(n, nextChildIndex(index), ancestor)
// If we run out of children, or skipped past the target, return the
// previous one
- if nextChild == nil || bytes.Compare(nextPath, key) >= 0 {
- parent.index = index - 1
+ if nextChild == nil || reachedPath(nextPath, key) {
+ parent.index = prevChildIndex(index)
return state, path, true
}
// We found a better child closer to the target
@@ -584,7 +584,7 @@ func (it *nodeIterator) push(state *nodeIteratorState, parentIndex *int, path []
it.stack = append(it.stack, state)
if parentIndex != nil {
- *parentIndex++
+ *parentIndex = nextChildIndex(*parentIndex)
}
}
@@ -593,8 +593,54 @@ func (it *nodeIterator) pop() {
it.path = it.path[:last.pathlen]
it.stack[len(it.stack)-1] = nil
it.stack = it.stack[:len(it.stack)-1]
- // last is now unused
- it.putInPool(last)
+
+ it.putInPool(last) // last is now unused
+}
+
+// reachedPath normalizes a path by truncating a terminator if present, and
+// returns true if it is greater than or equal to the target. Using this,
+// the path of a value node embedded a full node will compare less than the
+// full node's children.
+func reachedPath(path, target []byte) bool {
+ if hasTerm(path) {
+ path = path[:len(path)-1]
+ }
+ return bytes.Compare(path, target) >= 0
+}
+
+// A value embedded in a full node occupies the last slot (16) of the array of
+// children. In order to produce a pre-order traversal when iterating children,
+// we jump to this last slot first, then go back iterate the child nodes (and
+// skip the last slot at the end):
+
+// prevChildIndex returns the index of a child in a full node which precedes
+// the given index when performing a pre-order traversal.
+func prevChildIndex(index int) int {
+ switch index {
+ case 0: // We jumped back to iterate the children, from the value slot
+ return 16
+ case 16: // We jumped to the embedded value slot at the end, from the placeholder index
+ return -1
+ case 17: // We skipped the value slot after iterating all the children
+ return 15
+ default: // We are iterating the children in sequence
+ return index - 1
+ }
+}
+
+// nextChildIndex returns the index of a child in a full node which follows
+// the given index when performing a pre-order traversal.
+func nextChildIndex(index int) int {
+ switch index {
+ case -1: // Jump from the placeholder index to the embedded value slot
+ return 16
+ case 15: // Skip the value slot after iterating the children
+ return 17
+ case 16: // From the embedded value slot, jump back to iterate the children
+ return 0
+ default: // Iterate children in sequence
+ return index + 1
+ }
}
func compareNodes(a, b NodeIterator) int {
diff --git a/trie/iterator_test.go b/trie/iterator_test.go
index e3ecbd1fdf..7f438aeca3 100644
--- a/trie/iterator_test.go
+++ b/trie/iterator_test.go
@@ -30,7 +30,7 @@ import (
)
func TestEmptyIterator(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
iter := trie.MustNodeIterator(nil)
seen := make(map[string]struct{})
@@ -44,7 +44,7 @@ func TestEmptyIterator(t *testing.T) {
}
func TestIterator(t *testing.T) {
- db := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trie := NewEmpty(db)
vals := []struct{ k, v string }{
{"do", "verb"},
@@ -61,8 +61,8 @@ func TestIterator(t *testing.T) {
all[val.k] = val.v
trie.MustUpdate([]byte(val.k), []byte(val.v))
}
- root, nodes, _ := trie.Commit(false)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ root, nodes := trie.Commit(false)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
trie, _ = New(TrieID(root), db)
found := make(map[string]string)
@@ -88,7 +88,7 @@ func (k *kv) cmp(other *kv) int {
}
func TestIteratorLargeData(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
vals := make(map[string]*kv)
for i := byte(0); i < 255; i++ {
@@ -189,14 +189,14 @@ func testNodeIteratorCoverage(t *testing.T, scheme string) {
type kvs struct{ k, v string }
var testdata1 = []kvs{
+ {"bar", "b"},
{"barb", "ba"},
{"bard", "bc"},
{"bars", "bb"},
- {"bar", "b"},
{"fab", "z"},
+ {"foo", "a"},
{"food", "ab"},
{"foos", "aa"},
- {"foo", "a"},
}
var testdata2 = []kvs{
@@ -212,7 +212,7 @@ var testdata2 = []kvs{
}
func TestIteratorSeek(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
for _, val := range testdata1 {
trie.MustUpdate([]byte(val.k), []byte(val.v))
}
@@ -225,7 +225,7 @@ func TestIteratorSeek(t *testing.T) {
// Seek to a non-existent key.
it = NewIterator(trie.MustNodeIterator([]byte("barc")))
- if err := checkIteratorOrder(testdata1[1:], it); err != nil {
+ if err := checkIteratorOrder(testdata1[2:], it); err != nil {
t.Fatal(err)
}
@@ -234,6 +234,12 @@ func TestIteratorSeek(t *testing.T) {
if err := checkIteratorOrder(nil, it); err != nil {
t.Fatal(err)
}
+
+ // Seek to a key for which a prefixing key exists.
+ it = NewIterator(trie.MustNodeIterator([]byte("food")))
+ if err := checkIteratorOrder(testdata1[6:], it); err != nil {
+ t.Fatal(err)
+ }
}
func checkIteratorOrder(want []kvs, it *Iterator) error {
@@ -257,22 +263,22 @@ func checkIteratorOrder(want []kvs, it *Iterator) error {
}
func TestDifferenceIterator(t *testing.T) {
- dba := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ dba := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
triea := NewEmpty(dba)
for _, val := range testdata1 {
triea.MustUpdate([]byte(val.k), []byte(val.v))
}
- rootA, nodesA, _ := triea.Commit(false)
- dba.Update(rootA, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesA), nil)
+ rootA, nodesA := triea.Commit(false)
+ dba.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA))
triea, _ = New(TrieID(rootA), dba)
- dbb := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ dbb := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trieb := NewEmpty(dbb)
for _, val := range testdata2 {
trieb.MustUpdate([]byte(val.k), []byte(val.v))
}
- rootB, nodesB, _ := trieb.Commit(false)
- dbb.Update(rootB, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesB), nil)
+ rootB, nodesB := trieb.Commit(false)
+ dbb.Update(rootB, types.EmptyRootHash, trienode.NewWithNodeSet(nodesB))
trieb, _ = New(TrieID(rootB), dbb)
found := make(map[string]string)
@@ -300,22 +306,22 @@ func TestDifferenceIterator(t *testing.T) {
}
func TestUnionIterator(t *testing.T) {
- dba := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ dba := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
triea := NewEmpty(dba)
for _, val := range testdata1 {
triea.MustUpdate([]byte(val.k), []byte(val.v))
}
- rootA, nodesA, _ := triea.Commit(false)
- dba.Update(rootA, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesA), nil)
+ rootA, nodesA := triea.Commit(false)
+ dba.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA))
triea, _ = New(TrieID(rootA), dba)
- dbb := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ dbb := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trieb := NewEmpty(dbb)
for _, val := range testdata2 {
trieb.MustUpdate([]byte(val.k), []byte(val.v))
}
- rootB, nodesB, _ := trieb.Commit(false)
- dbb.Update(rootB, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesB), nil)
+ rootB, nodesB := trieb.Commit(false)
+ dbb.Update(rootB, types.EmptyRootHash, trienode.NewWithNodeSet(nodesB))
trieb, _ = New(TrieID(rootB), dbb)
di, _ := NewUnionIterator([]NodeIterator{triea.MustNodeIterator(nil), trieb.MustNodeIterator(nil)})
@@ -323,16 +329,16 @@ func TestUnionIterator(t *testing.T) {
all := []struct{ k, v string }{
{"aardvark", "c"},
+ {"bar", "b"},
{"barb", "ba"},
{"barb", "bd"},
{"bard", "bc"},
{"bars", "bb"},
{"bars", "be"},
- {"bar", "b"},
{"fab", "z"},
+ {"foo", "a"},
{"food", "ab"},
{"foos", "aa"},
- {"foo", "a"},
{"jars", "d"},
}
@@ -356,7 +362,8 @@ func TestUnionIterator(t *testing.T) {
}
func TestIteratorNoDups(t *testing.T) {
- tr := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
+ tr := NewEmpty(db)
for _, val := range testdata1 {
tr.MustUpdate([]byte(val.k), []byte(val.v))
}
@@ -379,10 +386,10 @@ func testIteratorContinueAfterError(t *testing.T, memonly bool, scheme string) {
for _, val := range testdata1 {
tr.MustUpdate([]byte(val.k), []byte(val.v))
}
- root, nodes, _ := tr.Commit(false)
- tdb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ root, nodes := tr.Commit(false)
+ tdb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
if !memonly {
- tdb.Commit(root, false)
+ tdb.Commit(root)
}
tr, _ = New(TrieID(root), tdb)
wantNodeCount := checkIteratorNoDups(t, tr.MustNodeIterator(nil), nil)
@@ -498,16 +505,16 @@ func testIteratorContinueAfterSeekError(t *testing.T, memonly bool, scheme strin
for _, val := range testdata1 {
ctr.MustUpdate([]byte(val.k), []byte(val.v))
}
- root, nodes, _ := ctr.Commit(false)
+ root, nodes := ctr.Commit(false)
for path, n := range nodes.Nodes {
if n.Hash == barNodeHash {
barNodePath = []byte(path)
break
}
}
- triedb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
if !memonly {
- _ = triedb.Commit(root, false)
+ _ = triedb.Commit(root)
}
var (
barNodeBlob []byte
@@ -536,7 +543,7 @@ func testIteratorContinueAfterSeekError(t *testing.T, memonly bool, scheme strin
rawdb.WriteTrieNode(diskdb, common.Hash{}, barNodePath, barNodeHash, barNodeBlob, triedb.Scheme())
}
// Check that iteration produces the right set of values.
- if err := checkIteratorOrder(testdata1[2:], NewIterator(it)); err != nil {
+ if err := checkIteratorOrder(testdata1[3:], NewIterator(it)); err != nil {
t.Fatal(err)
}
}
@@ -585,9 +592,9 @@ func testIteratorNodeBlob(t *testing.T, scheme string) {
all[val.k] = val.v
trie.MustUpdate([]byte(val.k), []byte(val.v))
}
- root, nodes, _ := trie.Commit(false)
- triedb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
- triedb.Commit(root, false)
+ root, nodes := trie.Commit(false)
+ triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
+ triedb.Commit(root)
var found = make(map[common.Hash][]byte)
trie, _ = New(TrieID(root), triedb)
diff --git a/trie/proof.go b/trie/proof.go
index c43a022248..52e04ab8ca 100644
--- a/trie/proof.go
+++ b/trie/proof.go
@@ -411,7 +411,7 @@ func unset(parent node, child node, key []byte, pos int, removeLeft bool) error
return unset(cld, cld.Children[key[pos]], key, pos+1, removeLeft)
case *shortNode:
if len(key[pos:]) < len(cld.Key) || !bytes.Equal(cld.Key, key[pos:pos+len(cld.Key)]) {
- // Find the fork point, it's an non-existent branch.
+ // Find the fork point, it's a non-existent branch.
if removeLeft {
if bytes.Compare(cld.Key, key[pos:]) < 0 {
// The key of fork shortnode is less than the path
@@ -428,7 +428,7 @@ func unset(parent node, child node, key []byte, pos int, removeLeft bool) error
} else {
if bytes.Compare(cld.Key, key[pos:]) > 0 {
// The key of fork shortnode is greater than the
- // path(it belongs to the range), unset the entire
+ // path(it belongs to the range), unset the entries
// branch. The parent must be a fullnode.
fn := parent.(*fullNode)
fn.Children[key[pos-1]] = nil
diff --git a/trie/proof_test.go b/trie/proof_test.go
index 08557940f9..de18c9371f 100644
--- a/trie/proof_test.go
+++ b/trie/proof_test.go
@@ -22,13 +22,13 @@ import (
"encoding/binary"
"fmt"
mrand "math/rand"
+ "slices"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb/memorydb"
- "golang.org/x/exp/slices"
)
// Prng is a pseudo random number generator seeded by strong randomness.
@@ -102,7 +102,7 @@ func TestProof(t *testing.T) {
}
func TestOneElementProof(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
updateString(trie, "k", "v")
for i, prover := range makeProvers(trie) {
@@ -160,7 +160,7 @@ func TestBadProof(t *testing.T) {
// Tests that missing keys can also be proven. The test explicitly uses a single
// entry trie and checks for missing keys both before and after the single entry.
func TestMissingKeyProof(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
updateString(trie, "k", "v")
for i, key := range []string{"a", "j", "l", "z"} {
@@ -218,7 +218,7 @@ func TestRangeProof(t *testing.T) {
}
}
-// TestRangeProof tests normal range proof with two non-existent proofs.
+// TestRangeProofWithNonExistentProof tests normal range proof with two non-existent proofs.
// The test cases are generated randomly.
func TestRangeProofWithNonExistentProof(t *testing.T) {
trie, vals := randomTrie(4096)
@@ -369,7 +369,7 @@ func TestOneElementRangeProof(t *testing.T) {
}
// Test the mini trie with only a single element.
- tinyTrie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ tinyTrie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
entry := &kv{randBytes(32), randBytes(20), false}
tinyTrie.MustUpdate(entry.k, entry.v)
@@ -443,7 +443,7 @@ func TestAllElementsProof(t *testing.T) {
// TestSingleSideRangeProof tests the range starts from zero.
func TestSingleSideRangeProof(t *testing.T) {
for i := 0; i < 64; i++ {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
var entries []*kv
for i := 0; i < 4096; i++ {
value := &kv{randBytes(32), randBytes(20), false}
@@ -560,7 +560,7 @@ func TestBadRangeProof(t *testing.T) {
// TestGappedRangeProof focuses on the small trie with embedded nodes.
// If the gapped node is embedded in the trie, it should be detected too.
func TestGappedRangeProof(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
var entries []*kv // Sorted entries
for i := byte(0); i < 10; i++ {
@@ -638,7 +638,7 @@ func TestSameSideProofs(t *testing.T) {
}
func TestHasRightElement(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
var entries []*kv
for i := 0; i < 4096; i++ {
value := &kv{randBytes(32), randBytes(20), false}
@@ -1015,7 +1015,7 @@ func benchmarkVerifyRangeNoProof(b *testing.B, size int) {
}
func randomTrie(n int) (*Trie, map[string]*kv) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
vals := make(map[string]*kv)
for i := byte(0); i < 100; i++ {
@@ -1039,7 +1039,7 @@ func randomTrie(n int) (*Trie, map[string]*kv) {
}
func nonRandomTrie(n int) (*Trie, map[string]*kv) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
vals := make(map[string]*kv)
max := uint64(0xffffffffffffffff)
@@ -1066,7 +1066,7 @@ func TestRangeProofKeysWithSharedPrefix(t *testing.T) {
common.Hex2Bytes("02"),
common.Hex2Bytes("03"),
}
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
for i, key := range keys {
trie.MustUpdate(key, vals[i])
}
diff --git a/trie/secure_trie.go b/trie/secure_trie.go
index 99cdfac576..23a771fef2 100644
--- a/trie/secure_trie.go
+++ b/trie/secure_trie.go
@@ -21,15 +21,26 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/ethereum/go-ethereum/triedb/database"
)
+// preimageStore wraps the methods of a backing store for reading and writing
+// trie node preimages.
+type preimageStore interface {
+ // Preimage retrieves the preimage of the specified hash.
+ Preimage(hash common.Hash) []byte
+
+ // InsertPreimage commits a set of preimages along with their hashes.
+ InsertPreimage(preimages map[common.Hash][]byte)
+}
+
// SecureTrie is the old name of StateTrie.
// Deprecated: use StateTrie.
type SecureTrie = StateTrie
// NewSecure creates a new StateTrie.
// Deprecated: use NewStateTrie.
-func NewSecure(stateRoot common.Hash, owner common.Hash, root common.Hash, db *Database) (*SecureTrie, error) {
+func NewSecure(stateRoot common.Hash, owner common.Hash, root common.Hash, db database.Database) (*SecureTrie, error) {
id := &ID{
StateRoot: stateRoot,
Owner: owner,
@@ -50,7 +61,8 @@ func NewSecure(stateRoot common.Hash, owner common.Hash, root common.Hash, db *D
// StateTrie is not safe for concurrent use.
type StateTrie struct {
trie Trie
- preimages *preimageStore
+ db database.Database
+ preimages preimageStore
hashKeyBuf [common.HashLength]byte
secKeyCache map[string][]byte
secKeyCacheOwner *StateTrie // Pointer to self, replace the key cache on mismatch
@@ -61,7 +73,7 @@ type StateTrie struct {
// If root is the zero hash or the sha3 hash of an empty string, the
// trie is initially empty. Otherwise, New will panic if db is nil
// and returns MissingNodeError if the root node cannot be found.
-func NewStateTrie(id *ID, db *Database) (*StateTrie, error) {
+func NewStateTrie(id *ID, db database.Database) (*StateTrie, error) {
if db == nil {
panic("trie.NewStateTrie called without a database")
}
@@ -69,8 +81,16 @@ func NewStateTrie(id *ID, db *Database) (*StateTrie, error) {
if err != nil {
return nil, err
}
+
// nolint
- return &StateTrie{trie: *trie, preimages: db.preimages}, nil
+ tr := &StateTrie{trie: *trie, db: db}
+
+ // link the preimage store if it's supported
+ preimages, ok := db.(preimageStore)
+ if ok {
+ tr.preimages = preimages
+ }
+ return tr, nil
}
// MustGet returns the value for key stored in the trie.
@@ -214,7 +234,12 @@ func (t *StateTrie) GetKey(shaKey []byte) []byte {
if t.preimages == nil {
return nil
}
- return t.preimages.preimage(common.BytesToHash(shaKey))
+ return t.preimages.Preimage(common.BytesToHash(shaKey))
+}
+
+// Witness returns a set containing all trie nodes that have been accessed.
+func (t *StateTrie) Witness() map[string]struct{} {
+ return t.trie.Witness()
}
// Commit collects all dirty nodes in the trie and replaces them with the
@@ -224,15 +249,15 @@ func (t *StateTrie) GetKey(shaKey []byte) []byte {
// All cached preimages will be also flushed if preimages recording is enabled.
// Once the trie is committed, it's not usable anymore. A new trie must
// be created with new root and updated trie database for following usage
-func (t *StateTrie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error) {
+func (t *StateTrie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet) {
// Write all the pre-images to the actual disk database
if len(t.getSecKeyCache()) > 0 {
+ preimages := make(map[common.Hash][]byte, len(t.secKeyCache))
+ for hk, key := range t.secKeyCache {
+ preimages[common.BytesToHash([]byte(hk))] = key
+ }
if t.preimages != nil {
- preimages := make(map[common.Hash][]byte)
- for hk, key := range t.secKeyCache {
- preimages[common.BytesToHash([]byte(hk))] = key
- }
- t.preimages.insertPreimage(preimages)
+ t.preimages.InsertPreimage(preimages)
}
t.secKeyCache = make(map[string][]byte)
}
@@ -250,7 +275,7 @@ func (t *StateTrie) Hash() common.Hash {
func (t *StateTrie) Copy() *StateTrie {
return &StateTrie{
trie: *t.trie.Copy(),
- preimages: t.preimages,
+ db: t.db,
secKeyCache: t.secKeyCache,
}
}
@@ -289,3 +314,7 @@ func (t *StateTrie) getSecKeyCache() map[string][]byte {
}
return t.secKeyCache
}
+
+func (t *StateTrie) IsVerkle() bool {
+ return false
+}
diff --git a/trie/secure_trie_test.go b/trie/secure_trie_test.go
index 0fa003f8ce..c3decf293d 100644
--- a/trie/secure_trie_test.go
+++ b/trie/secure_trie_test.go
@@ -31,14 +31,14 @@ import (
)
func newEmptySecure() *StateTrie {
- trie, _ := NewStateTrie(TrieID(types.EmptyRootHash), NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie, _ := NewStateTrie(TrieID(types.EmptyRootHash), newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
return trie
}
// makeTestStateTrie creates a large enough secure trie for testing.
-func makeTestStateTrie() (*Database, *StateTrie, map[string][]byte) {
+func makeTestStateTrie() (*testDb, *StateTrie, map[string][]byte) {
// Create an empty trie
- triedb := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ triedb := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trie, _ := NewStateTrie(TrieID(types.EmptyRootHash), triedb)
// Fill it with some arbitrary data
@@ -61,8 +61,8 @@ func makeTestStateTrie() (*Database, *StateTrie, map[string][]byte) {
trie.MustUpdate(key, val)
}
}
- root, nodes, _ := trie.Commit(false)
- if err := triedb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil); err != nil {
+ root, nodes := trie.Commit(false)
+ if err := triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)); err != nil {
panic(fmt.Errorf("failed to commit db %v", err))
}
// Re-create the trie based on the new state
diff --git a/trie/stacktrie.go b/trie/stacktrie.go
index 3724712166..6aea3e1f27 100644
--- a/trie/stacktrie.go
+++ b/trie/stacktrie.go
@@ -23,8 +23,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/metrics"
)
var (
@@ -32,62 +30,32 @@ var (
_ = types.TrieHasher((*StackTrie)(nil))
)
-// StackTrieOptions contains the configured options for manipulating the stackTrie.
-type StackTrieOptions struct {
- Writer func(path []byte, hash common.Hash, blob []byte) // The function to commit the dirty nodes
- Cleaner func(path []byte) // The function to clean up dangling nodes
-
- SkipLeftBoundary bool // Flag whether the nodes on the left boundary are skipped for committing
- SkipRightBoundary bool // Flag whether the nodes on the right boundary are skipped for committing
- boundaryGauge metrics.Gauge // Gauge to track how many boundary nodes are met
-}
-
-// NewStackTrieOptions initializes an empty options for stackTrie.
-func NewStackTrieOptions() *StackTrieOptions { return &StackTrieOptions{} }
-
-// WithWriter configures trie node writer within the options.
-func (o *StackTrieOptions) WithWriter(writer func(path []byte, hash common.Hash, blob []byte)) *StackTrieOptions {
- o.Writer = writer
- return o
-}
-
-// WithCleaner configures the cleaner in the option for removing dangling nodes.
-func (o *StackTrieOptions) WithCleaner(cleaner func(path []byte)) *StackTrieOptions {
- o.Cleaner = cleaner
- return o
-}
-
-// WithSkipBoundary configures whether the left and right boundary nodes are
-// filtered for committing, along with a gauge metrics to track how many
-// boundary nodes are met.
-func (o *StackTrieOptions) WithSkipBoundary(skipLeft, skipRight bool, gauge metrics.Gauge) *StackTrieOptions {
- o.SkipLeftBoundary = skipLeft
- o.SkipRightBoundary = skipRight
- o.boundaryGauge = gauge
- return o
-}
+// OnTrieNode is a callback method invoked when a trie node is committed
+// by the stack trie. The node is only committed if it's considered complete.
+//
+// The caller should not modify the contents of the returned path and blob
+// slice, and their contents may be changed after the call. It is up to the
+// `onTrieNode` receiver function to deep-copy the data if it wants to retain
+// it after the call ends.
+type OnTrieNode func(path []byte, hash common.Hash, blob []byte)
// StackTrie is a trie implementation that expects keys to be inserted
// in order. Once it determines that a subtree will no longer be inserted
// into, it will hash it and free up the memory it uses.
type StackTrie struct {
- options *StackTrieOptions
- root *stNode
- h *hasher
-
- first []byte // The (hex-encoded without terminator) key of first inserted entry, tracked as left boundary.
- last []byte // The (hex-encoded without terminator) key of last inserted entry, tracked as right boundary.
+ root *stNode
+ h *hasher
+ last []byte
+ onTrieNode OnTrieNode
}
-// NewStackTrie allocates and initializes an empty trie.
-func NewStackTrie(options *StackTrieOptions) *StackTrie {
- if options == nil {
- options = NewStackTrieOptions()
- }
+// NewStackTrie allocates and initializes an empty trie. The committed nodes
+// will be discarded immediately if no callback is configured.
+func NewStackTrie(onTrieNode OnTrieNode) *StackTrie {
return &StackTrie{
- options: options,
- root: stPool.Get().(*stNode),
- h: newHasher(false),
+ root: stPool.Get().(*stNode),
+ h: newHasher(false),
+ onTrieNode: onTrieNode,
}
}
@@ -101,10 +69,6 @@ func (t *StackTrie) Update(key, value []byte) error {
if bytes.Compare(t.last, k) >= 0 {
return errors.New("non-ascending key order")
}
- // track the first and last inserted entries.
- if t.first == nil {
- t.first = append([]byte{}, k...)
- }
if t.last == nil {
t.last = append([]byte{}, k...) // allocate key slice
} else {
@@ -114,19 +78,9 @@ func (t *StackTrie) Update(key, value []byte) error {
return nil
}
-// MustUpdate is a wrapper of Update and will omit any encountered error but
-// just print out an error message.
-func (t *StackTrie) MustUpdate(key, value []byte) {
- if err := t.Update(key, value); err != nil {
- log.Error("Unhandled trie error in StackTrie.Update", "err", err)
- }
-}
-
// Reset resets the stack trie object to empty state.
func (t *StackTrie) Reset() {
- t.options = NewStackTrieOptions()
t.root = stPool.Get().(*stNode)
- t.first = nil
t.last = nil
}
@@ -349,10 +303,7 @@ func (t *StackTrie) insert(st *stNode, key, value []byte, path []byte) {
//
// This method also sets 'st.type' to hashedNode, and clears 'st.key'.
func (t *StackTrie) hash(st *stNode, path []byte) {
- var (
- blob []byte // RLP-encoded node blob
- internal [][]byte // List of node paths covered by the extension node
- )
+ var blob []byte // RLP-encoded node blob
switch st.typ {
case hashedNode:
return
@@ -387,15 +338,6 @@ func (t *StackTrie) hash(st *stNode, path []byte) {
// recursively hash and commit child as the first step
t.hash(st.children[0], append(path, st.key...))
- // Collect the path of internal nodes between shortNode and its **in disk**
- // child. This is essential in the case of path mode scheme to avoid leaving
- // danging nodes within the range of this internal path on disk, which would
- // break the guarantee for state healing.
- if len(st.children[0].val) >= 32 && t.options.Cleaner != nil {
- for i := 1; i < len(st.key); i++ {
- internal = append(internal, append(path, st.key[:i]...))
- }
- }
// encode the extension node
n := shortNode{Key: hexToCompactInPlace(st.key)}
if len(st.children[0].val) < 32 {
@@ -419,11 +361,12 @@ func (t *StackTrie) hash(st *stNode, path []byte) {
default:
panic("invalid node type")
}
-
+ // Convert the node type to hashNode and reset the key slice.
st.typ = hashedNode
st.key = st.key[:0]
- // Skip committing the non-root node if the size is smaller than 32 bytes.
+ // Skip committing the non-root node if the size is smaller than 32 bytes
+ // as tiny nodes are always embedded in their parent except root node.
if len(blob) < 32 && len(path) > 0 {
st.val = common.CopyBytes(blob)
return
@@ -432,51 +375,20 @@ func (t *StackTrie) hash(st *stNode, path []byte) {
// input values.
st.val = t.h.hashData(blob)
- // Short circuit if the stack trie is not configured for writing.
- if t.options.Writer == nil {
- return
+ // Invoke the callback it's provided. Notably, the path and blob slices are
+ // volatile, please deep-copy the slices in callback if the contents need
+ // to be retained.
+ if t.onTrieNode != nil {
+ t.onTrieNode(path, common.BytesToHash(st.val), blob)
}
- // Skip committing if the node is on the left boundary and stackTrie is
- // configured to filter the boundary.
- if t.options.SkipLeftBoundary && bytes.HasPrefix(t.first, path) {
- if t.options.boundaryGauge != nil {
- t.options.boundaryGauge.Inc(1)
- }
- return
- }
- // Skip committing if the node is on the right boundary and stackTrie is
- // configured to filter the boundary.
- if t.options.SkipRightBoundary && bytes.HasPrefix(t.last, path) {
- if t.options.boundaryGauge != nil {
- t.options.boundaryGauge.Inc(1)
- }
- return
- }
- // Clean up the internal dangling nodes covered by the extension node.
- // This should be done before writing the node to adhere to the committing
- // order from bottom to top.
- for _, path := range internal {
- t.options.Cleaner(path)
- }
- t.options.Writer(path, common.BytesToHash(st.val), blob)
}
// Hash will firstly hash the entire trie if it's still not hashed and then commit
-// all nodes to the associated database. Actually most of the trie nodes have been
-// committed already. The main purpose here is to commit the nodes on right boundary.
-//
-// For stack trie, Hash and Commit are functionally identical.
+// all leftover nodes to the associated database. Actually most of the trie nodes
+// have been committed already. The main purpose here is to commit the nodes on
+// right boundary.
func (t *StackTrie) Hash() common.Hash {
n := t.root
t.hash(n, nil)
return common.BytesToHash(n.val)
}
-
-// Commit will firstly hash the entire trie if it's still not hashed and then commit
-// all nodes to the associated database. Actually most of the trie nodes have been
-// committed already. The main purpose here is to commit the nodes on right boundary.
-//
-// For stack trie, Hash and Commit are functionally identical.
-func (t *StackTrie) Commit() common.Hash {
- return t.Hash()
-}
diff --git a/trie/stacktrie_fuzzer_test.go b/trie/stacktrie_fuzzer_test.go
index 1b3f9dbe9c..df487d16bf 100644
--- a/trie/stacktrie_fuzzer_test.go
+++ b/trie/stacktrie_fuzzer_test.go
@@ -20,6 +20,7 @@ import (
"bytes"
"encoding/binary"
"fmt"
+ "slices"
"testing"
"github.com/ethereum/go-ethereum/common"
@@ -27,8 +28,6 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/trie/trienode"
- "golang.org/x/crypto/sha3"
- "golang.org/x/exp/slices"
)
func FuzzStackTrie(f *testing.F) {
@@ -41,16 +40,14 @@ func fuzz(data []byte, debugging bool) {
// This spongeDb is used to check the sequence of disk-db-writes
var (
input = bytes.NewReader(data)
- spongeA = &spongeDb{sponge: sha3.NewLegacyKeccak256()}
- dbA = NewDatabase(rawdb.NewDatabase(spongeA), nil)
+ spongeA = &spongeDb{sponge: crypto.NewKeccakState()}
+ dbA = newTestDatabase(rawdb.NewDatabase(spongeA), rawdb.HashScheme)
trieA = NewEmpty(dbA)
- spongeB = &spongeDb{sponge: sha3.NewLegacyKeccak256()}
- dbB = NewDatabase(rawdb.NewDatabase(spongeB), nil)
-
- options = NewStackTrieOptions().WithWriter(func(path []byte, hash common.Hash, blob []byte) {
+ spongeB = &spongeDb{sponge: crypto.NewKeccakState()}
+ dbB = newTestDatabase(rawdb.NewDatabase(spongeB), rawdb.HashScheme)
+ trieB = NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
rawdb.WriteTrieNode(spongeB, common.Hash{}, path, hash, blob, dbB.Scheme())
})
- trieB = NewStackTrie(options)
vals []*kv
maxElements = 10000
// operate on unique keys only
@@ -82,15 +79,12 @@ func fuzz(data []byte, debugging bool) {
return
}
// Flush trie -> database
- rootA, nodes, err := trieA.Commit(false)
- if err != nil {
- panic(err)
- }
+ rootA, nodes := trieA.Commit(false)
if nodes != nil {
- dbA.Update(rootA, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ dbA.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
}
// Flush memdb -> disk (sponge)
- dbA.Commit(rootA, false)
+ dbA.Commit(rootA)
// Stacktrie requires sorted insertion
slices.SortFunc(vals, (*kv).cmp)
@@ -99,10 +93,9 @@ func fuzz(data []byte, debugging bool) {
if debugging {
fmt.Printf("{\"%#x\" , \"%#x\"} // stacktrie.Update\n", kv.k, kv.v)
}
- trieB.MustUpdate(kv.k, kv.v)
+ trieB.Update(kv.k, kv.v)
}
rootB := trieB.Hash()
- trieB.Commit()
if rootA != rootB {
panic(fmt.Sprintf("roots differ: (trie) %x != %x (stacktrie)", rootA, rootB))
}
@@ -114,20 +107,19 @@ func fuzz(data []byte, debugging bool) {
// Ensure all the nodes are persisted correctly
var (
- nodeset = make(map[string][]byte) // path -> blob
- optionsC = NewStackTrieOptions().WithWriter(func(path []byte, hash common.Hash, blob []byte) {
+ nodeset = make(map[string][]byte) // path -> blob
+ trieC = NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
if crypto.Keccak256Hash(blob) != hash {
panic("invalid node blob")
}
nodeset[string(path)] = common.CopyBytes(blob)
})
- trieC = NewStackTrie(optionsC)
checked int
)
for _, kv := range vals {
- trieC.MustUpdate(kv.k, kv.v)
+ trieC.Update(kv.k, kv.v)
}
- rootC := trieC.Commit()
+ rootC := trieC.Hash()
if rootA != rootC {
panic(fmt.Sprintf("roots differ: (trie) %x != %x (stacktrie)", rootA, rootC))
}
diff --git a/trie/stacktrie_test.go b/trie/stacktrie_test.go
index 26b5865c06..4c41b810f2 100644
--- a/trie/stacktrie_test.go
+++ b/trie/stacktrie_test.go
@@ -19,15 +19,12 @@ package trie
import (
"bytes"
"math/big"
- "math/rand"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/trie/testutil"
"github.com/stretchr/testify/assert"
- "golang.org/x/exp/slices"
)
func TestStackTrieInsertAndHash(t *testing.T) {
@@ -225,7 +222,7 @@ func TestStackTrieInsertAndHash(t *testing.T) {
func TestSizeBug(t *testing.T) {
st := NewStackTrie(nil)
- nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ nt := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3")
@@ -240,7 +237,7 @@ func TestSizeBug(t *testing.T) {
func TestEmptyBug(t *testing.T) {
st := NewStackTrie(nil)
- nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ nt := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
//leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
//value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3")
@@ -266,7 +263,7 @@ func TestEmptyBug(t *testing.T) {
func TestValLength56(t *testing.T) {
st := NewStackTrie(nil)
- nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ nt := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
//leaf := common.FromHex("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
//value := common.FromHex("94cf40d0d2b44f2b66e07cace1372ca42b73cf21a3")
@@ -291,7 +288,7 @@ func TestValLength56(t *testing.T) {
// which causes a lot of node-within-node. This case was found via fuzzing.
func TestUpdateSmallNodes(t *testing.T) {
st := NewStackTrie(nil)
- nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ nt := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
kvs := []struct {
K string
V string
@@ -322,7 +319,7 @@ func TestUpdateVariableKeys(t *testing.T) {
t.SkipNow()
st := NewStackTrie(nil)
- nt := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ nt := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
kvs := []struct {
K string
V string
@@ -394,90 +391,6 @@ func TestStacktrieNotModifyValues(t *testing.T) {
}
}
-func buildPartialTree(entries []*kv, t *testing.T) map[string]common.Hash {
- var (
- options = NewStackTrieOptions()
- nodes = make(map[string]common.Hash)
- )
- var (
- first int
- last = len(entries) - 1
-
- noLeft bool
- noRight bool
- )
- // Enter split mode if there are at least two elements
- if rand.Intn(5) != 0 {
- for {
- first = rand.Intn(len(entries))
- last = rand.Intn(len(entries))
- if first <= last {
- break
- }
- }
- if first != 0 {
- noLeft = true
- }
- if last != len(entries)-1 {
- noRight = true
- }
- }
- options = options.WithSkipBoundary(noLeft, noRight, nil)
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
- nodes[string(path)] = hash
- })
- tr := NewStackTrie(options)
-
- for i := first; i <= last; i++ {
- tr.MustUpdate(entries[i].k, entries[i].v)
- }
- tr.Commit()
- return nodes
-}
-
-func TestPartialStackTrie(t *testing.T) {
- for round := 0; round < 100; round++ {
- var (
- n = rand.Intn(100) + 1
- entries []*kv
- )
- for i := 0; i < n; i++ {
- var val []byte
- if rand.Intn(3) == 0 {
- val = testutil.RandBytes(3)
- } else {
- val = testutil.RandBytes(32)
- }
- entries = append(entries, &kv{
- k: testutil.RandBytes(32),
- v: val,
- })
- }
- slices.SortFunc(entries, (*kv).cmp)
-
- var (
- nodes = make(map[string]common.Hash)
- options = NewStackTrieOptions().WithWriter(func(path []byte, hash common.Hash, blob []byte) {
- nodes[string(path)] = hash
- })
- )
- tr := NewStackTrie(options)
-
- for i := 0; i < len(entries); i++ {
- tr.MustUpdate(entries[i].k, entries[i].v)
- }
- tr.Commit()
-
- for j := 0; j < 100; j++ {
- for path, hash := range buildPartialTree(entries, t) {
- if nodes[path] != hash {
- t.Errorf("%v, want %x, got %x", []byte(path), nodes[path], hash)
- }
- }
- }
- }
-}
-
func TestStackTrieErrors(t *testing.T) {
s := NewStackTrie(nil)
// Deletion
diff --git a/trie/sync.go b/trie/sync.go
index 0482b28515..43bce9ae73 100644
--- a/trie/sync.go
+++ b/trie/sync.go
@@ -22,9 +22,11 @@ import (
"sync"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/prque"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
@@ -149,15 +151,42 @@ type CodeSyncResult struct {
// nodeOp represents an operation upon the trie node. It can either represent a
// deletion to the specific node or a node write for persisting retrieved node.
type nodeOp struct {
+ del bool // flag if op stands for a delete operation
owner common.Hash // identifier of the trie (empty for account trie)
path []byte // path from the root to the specified node.
blob []byte // the content of the node (nil for deletion)
hash common.Hash // hash of the node content (empty for node deletion)
}
-// isDelete indicates if the operation is a database deletion.
-func (op *nodeOp) isDelete() bool {
- return len(op.blob) == 0
+// valid checks whether the node operation is valid.
+func (op *nodeOp) valid() bool {
+ if op.del && len(op.blob) != 0 {
+ return false
+ }
+ if !op.del && len(op.blob) == 0 {
+ return false
+ }
+ return true
+}
+
+// string returns the node operation in string representation.
+func (op *nodeOp) string() string {
+ var node string
+ if op.owner == (common.Hash{}) {
+ node = fmt.Sprintf("node: (%v)", op.path)
+ } else {
+ node = fmt.Sprintf("node: (%x-%v)", op.owner, op.path)
+ }
+ var blobHex string
+ if len(op.blob) == 0 {
+ blobHex = "nil"
+ } else {
+ blobHex = hexutil.Encode(op.blob)
+ }
+ if op.del {
+ return fmt.Sprintf("del %s %s %s", node, blobHex, op.hash.Hex())
+ }
+ return fmt.Sprintf("write %s %s %s", node, blobHex, op.hash.Hex())
}
// syncMemBatch is an in-memory buffer of successfully downloaded but not yet
@@ -220,6 +249,7 @@ func (batch *syncMemBatch) delNode(owner common.Hash, path []byte) {
batch.size += common.HashLength + uint64(len(path))
}
batch.nodes = append(batch.nodes, nodeOp{
+ del: true,
owner: owner,
path: path,
})
@@ -446,7 +476,10 @@ func (s *Sync) Commit(dbw ethdb.Batch) error {
storage int
)
for _, op := range s.membatch.nodes {
- if op.isDelete() {
+ if !op.valid() {
+ return fmt.Errorf("invalid op, %s", op.string())
+ }
+ if op.del {
// node deletion is only supported in path mode.
if op.owner == (common.Hash{}) {
rawdb.DeleteAccountTrieNode(dbw, op.path)
@@ -569,9 +602,9 @@ func (s *Sync) children(req *nodeRequest, object node) ([]*nodeRequest, error) {
// the performance impact negligible.
var exists bool
if owner == (common.Hash{}) {
- exists = rawdb.ExistsAccountTrieNode(s.database, append(inner, key[:i]...))
+ exists = rawdb.HasAccountTrieNode(s.database, append(inner, key[:i]...))
} else {
- exists = rawdb.ExistsStorageTrieNode(s.database, owner, append(inner, key[:i]...))
+ exists = rawdb.HasStorageTrieNode(s.database, owner, append(inner, key[:i]...))
}
if exists {
s.membatch.delNode(owner, append(inner, key[:i]...))
@@ -723,13 +756,14 @@ func (s *Sync) hasNode(owner common.Hash, path []byte, hash common.Hash) (exists
}
// If node is running with path scheme, check the presence with node path.
var blob []byte
- var dbHash common.Hash
if owner == (common.Hash{}) {
- blob, dbHash = rawdb.ReadAccountTrieNode(s.database, path)
+ blob = rawdb.ReadAccountTrieNode(s.database, path)
} else {
- blob, dbHash = rawdb.ReadStorageTrieNode(s.database, owner, path)
+ blob = rawdb.ReadStorageTrieNode(s.database, owner, path)
}
- exists = hash == dbHash
+ h := newBlobHasher()
+ defer h.release()
+ exists = hash == h.hash(blob)
inconsistent = !exists && len(blob) != 0
return exists, inconsistent
}
@@ -745,3 +779,23 @@ func ResolvePath(path []byte) (common.Hash, []byte) {
return owner, path
}
+
+// blobHasher is used to compute the sha256 hash of the provided data.
+type blobHasher struct{ state crypto.KeccakState }
+
+// blobHasherPool is the pool for reusing pre-allocated hash state.
+var blobHasherPool = sync.Pool{
+ New: func() interface{} { return &blobHasher{state: crypto.NewKeccakState()} },
+}
+
+func newBlobHasher() *blobHasher {
+ return blobHasherPool.Get().(*blobHasher)
+}
+
+func (h *blobHasher) hash(data []byte) common.Hash {
+ return crypto.HashData(h.state, data)
+}
+
+func (h *blobHasher) release() {
+ blobHasherPool.Put(h)
+}
diff --git a/trie/sync_test.go b/trie/sync_test.go
index 823fb385de..213e8dc6bf 100644
--- a/trie/sync_test.go
+++ b/trie/sync_test.go
@@ -19,6 +19,7 @@ package trie
import (
"bytes"
"fmt"
+ "maps"
"math/rand"
"testing"
@@ -32,7 +33,7 @@ import (
)
// makeTestTrie create a sample test trie to test node-wise reconstruction.
-func makeTestTrie(scheme string) (ethdb.Database, *Database, *StateTrie, map[string][]byte) {
+func makeTestTrie(scheme string) (ethdb.Database, *testDb, *StateTrie, map[string][]byte) {
// Create an empty trie
db := rawdb.NewMemoryDatabase()
triedb := newTestDatabase(db, scheme)
@@ -58,11 +59,11 @@ func makeTestTrie(scheme string) (ethdb.Database, *Database, *StateTrie, map[str
trie.MustUpdate(key, val)
}
}
- root, nodes, _ := trie.Commit(false)
- if err := triedb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil); err != nil {
+ root, nodes := trie.Commit(false)
+ if err := triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes)); err != nil {
panic(fmt.Errorf("failed to commit db %v", err))
}
- if err := triedb.Commit(root, false); err != nil {
+ if err := triedb.Commit(root); err != nil {
panic(err)
}
// Re-create the trie based on the new state
@@ -145,7 +146,7 @@ func TestEmptySync(t *testing.T) {
emptyD, _ := New(TrieID(types.EmptyRootHash), dbD)
for i, trie := range []*Trie{emptyA, emptyB, emptyC, emptyD} {
- sync := NewSync(trie.Hash(), memorydb.New(), nil, []*Database{dbA, dbB, dbC, dbD}[i].Scheme())
+ sync := NewSync(trie.Hash(), memorydb.New(), nil, []*testDb{dbA, dbB, dbC, dbD}[i].Scheme())
if paths, nodes, codes := sync.Missing(1); len(paths) != 0 || len(nodes) != 0 || len(codes) != 0 {
t.Errorf("test %d: content requested for empty trie: %v, %v, %v", i, paths, nodes, codes)
}
@@ -751,11 +752,11 @@ func testSyncOrdering(t *testing.T, scheme string) {
}
}
}
-func syncWith(t *testing.T, root common.Hash, db ethdb.Database, srcDb *Database) {
+func syncWith(t *testing.T, root common.Hash, db ethdb.Database, srcDb *testDb) {
syncWithHookWriter(t, root, db, srcDb, nil)
}
-func syncWithHookWriter(t *testing.T, root common.Hash, db ethdb.Database, srcDb *Database, hookWriter ethdb.KeyValueWriter) {
+func syncWithHookWriter(t *testing.T, root common.Hash, db ethdb.Database, srcDb *testDb, hookWriter ethdb.KeyValueWriter) {
// Create a destination trie and sync with the scheduler
sched := NewSync(root, db, nil, srcDb.Scheme())
@@ -838,11 +839,11 @@ func testSyncMovingTarget(t *testing.T, scheme string) {
srcTrie.MustUpdate(key, val)
diff[string(key)] = val
}
- root, nodes, _ := srcTrie.Commit(false)
- if err := srcDb.Update(root, preRoot, 0, trienode.NewWithNodeSet(nodes), nil); err != nil {
+ root, nodes := srcTrie.Commit(false)
+ if err := srcDb.Update(root, preRoot, trienode.NewWithNodeSet(nodes)); err != nil {
panic(err)
}
- if err := srcDb.Commit(root, false); err != nil {
+ if err := srcDb.Commit(root); err != nil {
panic(err)
}
preRoot = root
@@ -863,11 +864,11 @@ func testSyncMovingTarget(t *testing.T, scheme string) {
srcTrie.MustUpdate([]byte(k), val)
reverted[k] = val
}
- root, nodes, _ = srcTrie.Commit(false)
- if err := srcDb.Update(root, preRoot, 0, trienode.NewWithNodeSet(nodes), nil); err != nil {
+ root, nodes = srcTrie.Commit(false)
+ if err := srcDb.Update(root, preRoot, trienode.NewWithNodeSet(nodes)); err != nil {
panic(err)
}
- if err := srcDb.Commit(root, false); err != nil {
+ if err := srcDb.Commit(root); err != nil {
panic(err)
}
srcTrie, _ = NewStateTrie(TrieID(root), srcDb)
@@ -905,13 +906,6 @@ func testPivotMove(t *testing.T, scheme string, tiny bool) {
tr.Update(key, val)
states[string(key)] = common.CopyBytes(val)
}
- copyStates = func(states map[string][]byte) map[string][]byte {
- cpy := make(map[string][]byte)
- for k, v := range states {
- cpy[k] = v
- }
- return cpy
- }
)
stateA := make(map[string][]byte)
writeFn([]byte{0x01, 0x23}, nil, srcTrie, stateA)
@@ -921,11 +915,11 @@ func testPivotMove(t *testing.T, scheme string, tiny bool) {
writeFn([]byte{0x02, 0x34}, nil, srcTrie, stateA)
writeFn([]byte{0x13, 0x44}, nil, srcTrie, stateA)
- rootA, nodesA, _ := srcTrie.Commit(false)
- if err := srcTrieDB.Update(rootA, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesA), nil); err != nil {
+ rootA, nodesA := srcTrie.Commit(false)
+ if err := srcTrieDB.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA)); err != nil {
panic(err)
}
- if err := srcTrieDB.Commit(rootA, false); err != nil {
+ if err := srcTrieDB.Commit(rootA); err != nil {
panic(err)
}
// Create a destination trie and sync with the scheduler
@@ -934,35 +928,35 @@ func testPivotMove(t *testing.T, scheme string, tiny bool) {
checkTrieContents(t, destDisk, scheme, srcTrie.Hash().Bytes(), stateA, true)
// Delete element to collapse trie
- stateB := copyStates(stateA)
+ stateB := maps.Clone(stateA)
srcTrie, _ = New(TrieID(rootA), srcTrieDB)
deleteFn([]byte{0x02, 0x34}, srcTrie, stateB)
deleteFn([]byte{0x13, 0x44}, srcTrie, stateB)
writeFn([]byte{0x01, 0x24}, nil, srcTrie, stateB)
- rootB, nodesB, _ := srcTrie.Commit(false)
- if err := srcTrieDB.Update(rootB, rootA, 0, trienode.NewWithNodeSet(nodesB), nil); err != nil {
+ rootB, nodesB := srcTrie.Commit(false)
+ if err := srcTrieDB.Update(rootB, rootA, trienode.NewWithNodeSet(nodesB)); err != nil {
panic(err)
}
- if err := srcTrieDB.Commit(rootB, false); err != nil {
+ if err := srcTrieDB.Commit(rootB); err != nil {
panic(err)
}
syncWith(t, rootB, destDisk, srcTrieDB)
checkTrieContents(t, destDisk, scheme, srcTrie.Hash().Bytes(), stateB, true)
// Add elements to expand trie
- stateC := copyStates(stateB)
+ stateC := maps.Clone(stateB)
srcTrie, _ = New(TrieID(rootB), srcTrieDB)
writeFn([]byte{0x01, 0x24}, stateA[string([]byte{0x01, 0x24})], srcTrie, stateC)
writeFn([]byte{0x02, 0x34}, nil, srcTrie, stateC)
writeFn([]byte{0x13, 0x44}, nil, srcTrie, stateC)
- rootC, nodesC, _ := srcTrie.Commit(false)
- if err := srcTrieDB.Update(rootC, rootB, 0, trienode.NewWithNodeSet(nodesC), nil); err != nil {
+ rootC, nodesC := srcTrie.Commit(false)
+ if err := srcTrieDB.Update(rootC, rootB, trienode.NewWithNodeSet(nodesC)); err != nil {
panic(err)
}
- if err := srcTrieDB.Commit(rootC, false); err != nil {
+ if err := srcTrieDB.Commit(rootC); err != nil {
panic(err)
}
syncWith(t, rootC, destDisk, srcTrieDB)
@@ -1009,13 +1003,6 @@ func testSyncAbort(t *testing.T, scheme string) {
tr.Update(key, val)
states[string(key)] = common.CopyBytes(val)
}
- copyStates = func(states map[string][]byte) map[string][]byte {
- cpy := make(map[string][]byte)
- for k, v := range states {
- cpy[k] = v
- }
- return cpy
- }
)
var (
stateA = make(map[string][]byte)
@@ -1027,11 +1014,11 @@ func testSyncAbort(t *testing.T, scheme string) {
}
writeFn(key, val, srcTrie, stateA)
- rootA, nodesA, _ := srcTrie.Commit(false)
- if err := srcTrieDB.Update(rootA, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodesA), nil); err != nil {
+ rootA, nodesA := srcTrie.Commit(false)
+ if err := srcTrieDB.Update(rootA, types.EmptyRootHash, trienode.NewWithNodeSet(nodesA)); err != nil {
panic(err)
}
- if err := srcTrieDB.Commit(rootA, false); err != nil {
+ if err := srcTrieDB.Commit(rootA); err != nil {
panic(err)
}
// Create a destination trie and sync with the scheduler
@@ -1040,15 +1027,15 @@ func testSyncAbort(t *testing.T, scheme string) {
checkTrieContents(t, destDisk, scheme, srcTrie.Hash().Bytes(), stateA, true)
// Delete the element from the trie
- stateB := copyStates(stateA)
+ stateB := maps.Clone(stateA)
srcTrie, _ = New(TrieID(rootA), srcTrieDB)
deleteFn(key, srcTrie, stateB)
- rootB, nodesB, _ := srcTrie.Commit(false)
- if err := srcTrieDB.Update(rootB, rootA, 0, trienode.NewWithNodeSet(nodesB), nil); err != nil {
+ rootB, nodesB := srcTrie.Commit(false)
+ if err := srcTrieDB.Update(rootB, rootA, trienode.NewWithNodeSet(nodesB)); err != nil {
panic(err)
}
- if err := srcTrieDB.Commit(rootB, false); err != nil {
+ if err := srcTrieDB.Commit(rootB); err != nil {
panic(err)
}
@@ -1067,15 +1054,15 @@ func testSyncAbort(t *testing.T, scheme string) {
}})
// Add elements to expand trie
- stateC := copyStates(stateB)
+ stateC := maps.Clone(stateB)
srcTrie, _ = New(TrieID(rootB), srcTrieDB)
writeFn(key, val, srcTrie, stateC)
- rootC, nodesC, _ := srcTrie.Commit(false)
- if err := srcTrieDB.Update(rootC, rootB, 0, trienode.NewWithNodeSet(nodesC), nil); err != nil {
+ rootC, nodesC := srcTrie.Commit(false)
+ if err := srcTrieDB.Update(rootC, rootB, trienode.NewWithNodeSet(nodesC)); err != nil {
panic(err)
}
- if err := srcTrieDB.Commit(rootC, false); err != nil {
+ if err := srcTrieDB.Commit(rootC); err != nil {
panic(err)
}
syncWith(t, rootC, destDisk, srcTrieDB)
diff --git a/trie/tracer.go b/trie/tracer.go
index 5e40f60d0b..297322ca2b 100644
--- a/trie/tracer.go
+++ b/trie/tracer.go
@@ -17,6 +17,8 @@
package trie
import (
+ "maps"
+
"github.com/ethereum/go-ethereum/common"
)
@@ -94,27 +96,14 @@ func (t *tracer) reset() {
// copy returns a deep copied tracer instance.
func (t *tracer) copy() *tracer {
- var (
- inserts = make(map[string]struct{})
- deletes = make(map[string]struct{})
- accessList = make(map[string][]byte)
- )
-
- for path := range t.inserts {
- inserts[path] = struct{}{}
- }
-
- for path := range t.deletes {
- deletes[path] = struct{}{}
- }
-
+ accessList := make(map[string][]byte, len(t.accessList))
for path, blob := range t.accessList {
accessList[path] = common.CopyBytes(blob)
}
return &tracer{
- inserts: inserts,
- deletes: deletes,
+ inserts: maps.Clone(t.inserts),
+ deletes: maps.Clone(t.deletes),
accessList: accessList,
}
}
diff --git a/trie/tracer_test.go b/trie/tracer_test.go
index 1c065c0b3d..e7ec84680e 100644
--- a/trie/tracer_test.go
+++ b/trie/tracer_test.go
@@ -62,7 +62,7 @@ func TestTrieTracer(t *testing.T) {
// Tests if the trie diffs are tracked correctly. Tracer should capture
// all non-leaf dirty nodes, no matter the node is embedded or not.
func testTrieTracer(t *testing.T, vals []struct{ k, v string }) {
- db := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trie := NewEmpty(db)
// Determine all new nodes are tracked
@@ -72,8 +72,8 @@ func testTrieTracer(t *testing.T, vals []struct{ k, v string }) {
insertSet := copySet(trie.tracer.inserts) // copy before commit
deleteSet := copySet(trie.tracer.deletes) // copy before commit
- root, nodes, _ := trie.Commit(false)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ root, nodes := trie.Commit(false)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
seen := setKeys(iterNodes(db, root))
if !compareSet(insertSet, seen) {
@@ -111,7 +111,8 @@ func TestTrieTracerNoop(t *testing.T) {
}
func testTrieTracerNoop(t *testing.T, vals []struct{ k, v string }) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
+ trie := NewEmpty(db)
for _, val := range vals {
trie.MustUpdate([]byte(val.k), []byte(val.v))
}
@@ -141,7 +142,7 @@ func testAccessList(t *testing.T, vals []struct{ k, v string }) {
t.Helper()
var (
- db = NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ db = newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trie = NewEmpty(db)
orig = trie.Copy()
)
@@ -149,8 +150,8 @@ func testAccessList(t *testing.T, vals []struct{ k, v string }) {
for _, val := range vals {
trie.MustUpdate([]byte(val.k), []byte(val.v))
}
- root, nodes, _ := trie.Commit(false)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ root, nodes := trie.Commit(false)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
trie, _ = New(TrieID(root), db)
if err := verifyAccessList(orig, trie, nodes); err != nil {
@@ -165,8 +166,8 @@ func testAccessList(t *testing.T, vals []struct{ k, v string }) {
for _, val := range vals {
trie.MustUpdate([]byte(val.k), randBytes(32))
}
- root, nodes, _ = trie.Commit(false)
- db.Update(root, parent, 0, trienode.NewWithNodeSet(nodes), nil)
+ root, nodes = trie.Commit(false)
+ db.Update(root, parent, trienode.NewWithNodeSet(nodes))
trie, _ = New(TrieID(root), db)
if err := verifyAccessList(orig, trie, nodes); err != nil {
@@ -185,8 +186,8 @@ func testAccessList(t *testing.T, vals []struct{ k, v string }) {
keys = append(keys, string(key))
trie.MustUpdate(key, randBytes(32))
}
- root, nodes, _ = trie.Commit(false)
- db.Update(root, parent, 0, trienode.NewWithNodeSet(nodes), nil)
+ root, nodes = trie.Commit(false)
+ db.Update(root, parent, trienode.NewWithNodeSet(nodes))
trie, _ = New(TrieID(root), db)
if err := verifyAccessList(orig, trie, nodes); err != nil {
@@ -201,8 +202,8 @@ func testAccessList(t *testing.T, vals []struct{ k, v string }) {
for _, key := range keys {
trie.MustUpdate([]byte(key), nil)
}
- root, nodes, _ = trie.Commit(false)
- db.Update(root, parent, 0, trienode.NewWithNodeSet(nodes), nil)
+ root, nodes = trie.Commit(false)
+ db.Update(root, parent, trienode.NewWithNodeSet(nodes))
trie, _ = New(TrieID(root), db)
if err := verifyAccessList(orig, trie, nodes); err != nil {
@@ -217,8 +218,8 @@ func testAccessList(t *testing.T, vals []struct{ k, v string }) {
for _, val := range vals {
trie.MustUpdate([]byte(val.k), nil)
}
- root, nodes, _ = trie.Commit(false)
- db.Update(root, parent, 0, trienode.NewWithNodeSet(nodes), nil)
+ root, nodes = trie.Commit(false)
+ db.Update(root, parent, trienode.NewWithNodeSet(nodes))
trie, _ = New(TrieID(root), db)
if err := verifyAccessList(orig, trie, nodes); err != nil {
@@ -231,15 +232,15 @@ func TestAccessListLeak(t *testing.T) {
t.Parallel()
var (
- db = NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ db = newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trie = NewEmpty(db)
)
// Create trie from scratch
for _, val := range standard {
trie.MustUpdate([]byte(val.k), []byte(val.v))
}
- root, nodes, _ := trie.Commit(false)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ root, nodes := trie.Commit(false)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
var cases = []struct {
op func(tr *Trie)
@@ -285,15 +286,15 @@ func TestTinyTree(t *testing.T) {
t.Parallel()
var (
- db = NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ db = newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trie = NewEmpty(db)
)
for _, val := range tiny {
trie.MustUpdate([]byte(val.k), randBytes(32))
}
- root, set, _ := trie.Commit(false)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(set), nil)
+ root, set := trie.Commit(false)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(set))
parent := root
trie, _ = New(TrieID(root), db)
@@ -302,8 +303,8 @@ func TestTinyTree(t *testing.T) {
for _, val := range tiny {
trie.MustUpdate([]byte(val.k), []byte(val.v))
}
- root, set, _ = trie.Commit(false)
- db.Update(root, parent, 0, trienode.NewWithNodeSet(set), nil)
+ root, set = trie.Commit(false)
+ db.Update(root, parent, trienode.NewWithNodeSet(set))
trie, _ = New(TrieID(root), db)
if err := verifyAccessList(orig, trie, set); err != nil {
@@ -342,7 +343,7 @@ func forNodes(tr *Trie) map[string][]byte {
return nodes
}
-func iterNodes(db *Database, root common.Hash) map[string][]byte {
+func iterNodes(db *testDb, root common.Hash) map[string][]byte {
tr, _ := New(TrieID(root), db)
return forNodes(tr)
}
diff --git a/trie/trie.go b/trie/trie.go
index 473c1452da..14dcacd857 100644
--- a/trie/trie.go
+++ b/trie/trie.go
@@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/ethereum/go-ethereum/triedb/database"
)
// Trie is a Merkle Patricia Trie. Use New to create a trie that sits on
@@ -84,7 +85,7 @@ func (t *Trie) Copy() *Trie {
// zero hash or the sha3 hash of an empty string, then trie is initially
// empty, otherwise, the root node must be present in database or returns
// a MissingNodeError if not.
-func New(id *ID, db *Database) (*Trie, error) {
+func New(id *ID, db database.Database) (*Trie, error) {
reader, err := newTrieReader(id.StateRoot, id.Owner, db)
if err != nil {
return nil, err
@@ -109,7 +110,7 @@ func New(id *ID, db *Database) (*Trie, error) {
}
// NewEmpty is a shortcut to create empty tree. It's mostly used in tests.
-func NewEmpty(db *Database) *Trie {
+func NewEmpty(db database.Database) *Trie {
tr, _ := New(TrieID(types.EmptyRootHash), db)
return tr
}
@@ -676,11 +677,7 @@ func (t *Trie) Hash() common.Hash {
// The returned nodeset can be nil if the trie is clean (nothing to commit).
// Once the trie is committed, it's not usable anymore. A new trie must
// be created with new root and updated trie database for following usage
-func (t *Trie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error) {
- t.tracerMutex.Lock()
- defer t.tracerMutex.Unlock()
-
- defer t.tracer.reset()
+func (t *Trie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet) {
defer func() {
t.committed = true
}()
@@ -691,13 +688,13 @@ func (t *Trie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error)
if t.root == nil {
paths := t.tracer.deletedNodes()
if len(paths) == 0 {
- return types.EmptyRootHash, nil, nil // case (a)
+ return types.EmptyRootHash, nil // case (a)
}
nodes := trienode.NewNodeSet(t.owner)
for _, path := range paths {
nodes.AddNode([]byte(path), trienode.NewDeleted())
}
- return types.EmptyRootHash, nodes, nil // case (b)
+ return types.EmptyRootHash, nodes // case (b)
}
// Derive the hash for all dirty nodes first. We hold the assumption
// in the following procedure that all nodes are hashed.
@@ -709,14 +706,14 @@ func (t *Trie) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error)
// Replace the root node with the origin hash in order to
// ensure all resolved nodes are dropped after the commit.
t.root = hashedNode
- return rootHash, nil, nil
+ return rootHash, nil
}
nodes := trienode.NewNodeSet(t.owner)
for _, path := range t.tracer.deletedNodes() {
nodes.AddNode([]byte(path), trienode.NewDeleted())
}
t.root = newCommitter(nodes, t.tracer, collectLeaf).Commit(t.root)
- return rootHash, nodes, nil
+ return rootHash, nodes
}
// hashRoot calculates the root hash of the given trie
@@ -737,6 +734,18 @@ func (t *Trie) hashRoot() (node, node) {
return hashed, cached
}
+// Witness returns a set containing all trie nodes that have been accessed.
+func (t *Trie) Witness() map[string]struct{} {
+ if len(t.tracer.accessList) == 0 {
+ return nil
+ }
+ witness := make(map[string]struct{})
+ for _, node := range t.tracer.accessList {
+ witness[string(node)] = struct{}{}
+ }
+ return witness
+}
+
// Reset drops the referenced root node and cleans all internal state.
func (t *Trie) Reset() {
t.root = nil
diff --git a/trie/trie_reader.go b/trie/trie_reader.go
index d326a4647d..49e7ba5e1a 100644
--- a/trie/trie_reader.go
+++ b/trie/trie_reader.go
@@ -20,32 +20,19 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/trie/triestate"
+ "github.com/ethereum/go-ethereum/triedb/database"
)
-// Reader wraps the Node method of a backing trie store.
-type Reader interface {
- // Node retrieves the trie node blob with the provided trie identifier, node path and
- // the corresponding node hash. No error will be returned if the node is not found.
- //
- // When looking up nodes in the account trie, 'owner' is the zero hash. For contract
- // storage trie nodes, 'owner' is the hash of the account address that containing the
- // storage.
- //
- // TODO(rjl493456442): remove the 'hash' parameter, it's redundant in PBSS.
- Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, error)
-}
-
// trieReader is a wrapper of the underlying node reader. It's not safe
// for concurrent usage.
type trieReader struct {
owner common.Hash
- reader Reader
+ reader database.Reader
banned map[string]struct{} // Marker to prevent node from being accessed, for tests
}
// newTrieReader initializes the trie reader with the given node reader.
-func newTrieReader(stateRoot, owner common.Hash, db *Database) (*trieReader, error) {
+func newTrieReader(stateRoot, owner common.Hash, db database.Database) (*trieReader, error) {
if stateRoot == (common.Hash{}) || stateRoot == types.EmptyRootHash {
if stateRoot == (common.Hash{}) {
log.Error("Zero state root hash!")
@@ -87,18 +74,3 @@ func (r *trieReader) node(path []byte, hash common.Hash) ([]byte, error) {
return blob, nil
}
-
-// trieLoader implements triestate.TrieLoader for constructing tries.
-type trieLoader struct {
- db *Database
-}
-
-// OpenTrie opens the main account trie.
-func (l *trieLoader) OpenTrie(root common.Hash) (triestate.Trie, error) {
- return New(TrieID(root), l.db)
-}
-
-// OpenStorageTrie opens the storage trie of an account.
-func (l *trieLoader) OpenStorageTrie(stateRoot common.Hash, addrHash, root common.Hash) (triestate.Trie, error) {
- return New(StorageTrieID(stateRoot, addrHash, root), l.db)
-}
diff --git a/trie/trie_test.go b/trie/trie_test.go
index d0bb8c5ffa..bdbe243797 100644
--- a/trie/trie_test.go
+++ b/trie/trie_test.go
@@ -23,9 +23,9 @@ import (
"fmt"
"hash"
"io"
- "math/big"
"math/rand"
"reflect"
+ "sort"
"testing"
"testing/quick"
@@ -37,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
)
@@ -46,7 +47,7 @@ func init() {
}
func TestEmptyTrie(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
res := trie.Hash()
exp := types.EmptyRootHash
@@ -56,7 +57,7 @@ func TestEmptyTrie(t *testing.T) {
}
func TestNull(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
key := make([]byte, 32)
value := []byte("test")
trie.MustUpdate(key, value)
@@ -98,11 +99,11 @@ func testMissingNode(t *testing.T, memonly bool, scheme string) {
trie := NewEmpty(triedb)
updateString(trie, "120000", "qwerqwerqwerqwerqwerqwerqwerqwer")
updateString(trie, "123456", "asdfasdfasdfasdfasdfasdfasdfasdf")
- root, nodes, _ := trie.Commit(false)
- triedb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ root, nodes := trie.Commit(false)
+ triedb.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
if !memonly {
- _ = triedb.Commit(root, false)
+ _ = triedb.Commit(root)
}
trie, _ = New(TrieID(root), triedb)
@@ -180,7 +181,7 @@ func testMissingNode(t *testing.T, memonly bool, scheme string) {
}
func TestInsert(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
updateString(trie, "doe", "reindeer")
updateString(trie, "dog", "puppy")
@@ -193,18 +194,18 @@ func TestInsert(t *testing.T) {
t.Errorf("case 1: exp %x got %x", exp, root)
}
- trie = NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie = NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
updateString(trie, "A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
exp = common.HexToHash("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab")
- root, _, _ = trie.Commit(false)
+ root, _ = trie.Commit(false)
if root != exp {
t.Errorf("case 2: exp %x got %x", exp, root)
}
}
func TestGet(t *testing.T) {
- db := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trie := NewEmpty(db)
updateString(trie, "doe", "reindeer")
updateString(trie, "dog", "puppy")
@@ -224,14 +225,15 @@ func TestGet(t *testing.T) {
if i == 1 {
return
}
- root, nodes, _ := trie.Commit(false)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ root, nodes := trie.Commit(false)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
trie, _ = New(TrieID(root), db)
}
}
func TestDelete(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
+ trie := NewEmpty(db)
vals := []struct{ k, v string }{
{"do", "verb"},
{"ether", "wookiedoo"},
@@ -259,7 +261,7 @@ func TestDelete(t *testing.T) {
}
func TestEmptyValues(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
vals := []struct{ k, v string }{
{"do", "verb"},
@@ -284,7 +286,7 @@ func TestEmptyValues(t *testing.T) {
}
func TestReplication(t *testing.T) {
- db := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trie := NewEmpty(db)
vals := []struct{ k, v string }{
{"do", "verb"},
@@ -299,8 +301,8 @@ func TestReplication(t *testing.T) {
for _, val := range vals {
updateString(trie, val.k, val.v)
}
- root, nodes, _ := trie.Commit(false)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ root, nodes := trie.Commit(false)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
// create a new trie on top of the database and check that lookups work.
trie2, err := New(TrieID(root), db)
@@ -313,14 +315,14 @@ func TestReplication(t *testing.T) {
t.Errorf("trie2 doesn't have %q => %q", kv.k, kv.v)
}
}
- hash, nodes, _ := trie2.Commit(false)
+ hash, nodes := trie2.Commit(false)
if hash != root {
t.Errorf("root failure. expected %x got %x", root, hash)
}
// recreate the trie after commit
if nodes != nil {
- db.Update(hash, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ db.Update(hash, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
}
trie2, err = New(TrieID(hash), db)
if err != nil {
@@ -347,7 +349,7 @@ func TestReplication(t *testing.T) {
}
func TestLargeValue(t *testing.T) {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
trie.MustUpdate([]byte("key1"), []byte{99, 99, 99, 99})
trie.MustUpdate([]byte("key2"), bytes.Repeat([]byte{1}, 32))
trie.Hash()
@@ -556,9 +558,9 @@ func runRandTest(rt randTest) error {
case opHash:
tr.Hash()
case opCommit:
- root, nodes, _ := tr.Commit(true)
+ root, nodes := tr.Commit(true)
if nodes != nil {
- triedb.Update(root, origin, 0, trienode.NewWithNodeSet(nodes), nil)
+ triedb.Update(root, origin, trienode.NewWithNodeSet(nodes))
}
newtr, err := New(TrieID(root), triedb)
@@ -585,7 +587,7 @@ func runRandTest(rt randTest) error {
}
if tr.Hash() != checktr.Hash() {
- rt[i].err = fmt.Errorf("hash mismatch in opItercheckhash")
+ rt[i].err = errors.New("hash mismatch in opItercheckhash")
}
case opNodeDiff:
var (
@@ -631,22 +633,22 @@ func runRandTest(rt randTest) error {
}
if len(insertExp) != len(tr.tracer.inserts) {
- rt[i].err = fmt.Errorf("insert set mismatch")
+ rt[i].err = errors.New("insert set mismatch")
}
if len(deleteExp) != len(tr.tracer.deletes) {
- rt[i].err = fmt.Errorf("delete set mismatch")
+ rt[i].err = errors.New("delete set mismatch")
}
for insert := range tr.tracer.inserts {
if _, present := insertExp[insert]; !present {
- rt[i].err = fmt.Errorf("missing inserted node")
+ rt[i].err = errors.New("missing inserted node")
}
}
for del := range tr.tracer.deletes {
if _, present := deleteExp[del]; !present {
- rt[i].err = fmt.Errorf("missing deleted node")
+ rt[i].err = errors.New("missing deleted node")
}
}
}
@@ -675,7 +677,7 @@ func BenchmarkUpdateLE(b *testing.B) { benchUpdate(b, binary.LittleEndian) }
const benchElemCount = 20000
func benchGet(b *testing.B) {
- triedb := NewDatabase(rawdb.NewMemoryDatabase(), nil)
+ triedb := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme)
trie := NewEmpty(triedb)
k := make([]byte, 32)
@@ -696,7 +698,7 @@ func benchGet(b *testing.B) {
}
func benchUpdate(b *testing.B, e binary.ByteOrder) *Trie {
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
k := make([]byte, 32)
b.ReportAllocs()
@@ -731,7 +733,7 @@ func BenchmarkHash(b *testing.B) {
// entries, then adding N more.
addresses, accounts := makeAccounts(2 * b.N)
// Insert the accounts into the trie and hash it
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
i := 0
for ; i < len(addresses)/2; i++ {
@@ -766,7 +768,7 @@ func benchmarkCommitAfterHash(b *testing.B, collectLeaf bool) {
// Make the random benchmark deterministic
addresses, accounts := makeAccounts(b.N)
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
for i := 0; i < len(addresses); i++ {
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i])
}
@@ -780,7 +782,7 @@ func benchmarkCommitAfterHash(b *testing.B, collectLeaf bool) {
func TestTinyTrie(t *testing.T) {
// Create a realistic account trie to hash
_, accounts := makeAccounts(5)
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
trie.MustUpdate(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001337"), accounts[3])
if exp, root := common.HexToHash("8c6a85a4d9fda98feff88450299e574e5378e32391f75a055d470ac0653f1005"), trie.Hash(); exp != root {
@@ -798,7 +800,7 @@ func TestTinyTrie(t *testing.T) {
if exp, root := common.HexToHash("0608c1d1dc3905fa22204c7a0e43644831c3b6d3def0f274be623a948197e64a"), trie.Hash(); exp != root {
t.Errorf("3: got %x, exp %x", root, exp)
}
- checktr := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ checktr := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
it := NewIterator(trie.MustNodeIterator(nil))
for it.Next() {
checktr.MustUpdate(it.Key, it.Value)
@@ -812,7 +814,7 @@ func TestTinyTrie(t *testing.T) {
func TestCommitAfterHash(t *testing.T) {
// Create a realistic account trie to hash
addresses, accounts := makeAccounts(1000)
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
for i := 0; i < len(addresses); i++ {
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i])
}
@@ -825,7 +827,7 @@ func TestCommitAfterHash(t *testing.T) {
if exp != root {
t.Errorf("got %x, exp %x", root, exp)
}
- root, _, _ = trie.Commit(false)
+ root, _ = trie.Commit(false)
if exp != root {
t.Errorf("got %x, exp %x", root, exp)
}
@@ -856,7 +858,7 @@ func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) {
numBytes := random.Uint32() % 33 // [0, 32] bytes
balanceBytes := make([]byte, numBytes)
random.Read(balanceBytes)
- balance := new(big.Int).SetBytes(balanceBytes)
+ balance := new(uint256.Int).SetBytes(balanceBytes)
data, _ := rlp.EncodeToBytes(&types.StateAccount{Nonce: nonce, Balance: balance, Root: root, CodeHash: code})
accounts[i] = data
}
@@ -869,6 +871,8 @@ type spongeDb struct {
sponge hash.Hash
id string
journal []string
+ keys []string
+ values map[string]string
}
func (s *spongeDb) Has(key []byte) (bool, error) { panic("implement me") }
@@ -877,7 +881,7 @@ func (s *spongeDb) Delete(key []byte) error { panic("implement
func (s *spongeDb) NewBatch() ethdb.Batch { return &spongeBatch{s} }
func (s *spongeDb) NewBatchWithSize(size int) ethdb.Batch { return &spongeBatch{s} }
func (s *spongeDb) NewSnapshot() (ethdb.Snapshot, error) { panic("implement me") }
-func (s *spongeDb) Stat(property string) (string, error) { panic("implement me") }
+func (s *spongeDb) Stat() (string, error) { panic("implement me") }
func (s *spongeDb) Compact(start []byte, limit []byte) error { panic("implement me") }
func (s *spongeDb) Close() error { return nil }
func (s *spongeDb) Put(key []byte, value []byte) error {
@@ -892,13 +896,27 @@ func (s *spongeDb) Put(key []byte, value []byte) error {
valbrief = valbrief[:8]
}
s.journal = append(s.journal, fmt.Sprintf("%v: PUT([%x...], [%d bytes] %x...)\n", s.id, keybrief, len(value), valbrief))
- s.sponge.Write(key)
- s.sponge.Write(value)
+ if s.values == nil {
+ s.sponge.Write(key)
+ s.sponge.Write(value)
+ } else {
+ s.keys = append(s.keys, string(key))
+ s.values[string(key)] = string(value)
+ }
return nil
}
func (s *spongeDb) NewIterator(prefix []byte, start []byte) ethdb.Iterator { panic("implement me") }
+func (s *spongeDb) Flush() {
+ // Bottom-up, the longest path first
+ sort.Sort(sort.Reverse(sort.StringSlice(s.keys)))
+ for _, key := range s.keys {
+ s.sponge.Write([]byte(key))
+ s.sponge.Write([]byte(s.values[key]))
+ }
+}
+
// spongeBatch is a dummy batch which immediately writes to the underlying spongedb
type spongeBatch struct {
db *spongeDb
@@ -923,24 +941,25 @@ func TestCommitSequence(t *testing.T) {
count int
expWriteSeqHash []byte
}{
- {20, common.FromHex("873c78df73d60e59d4a2bcf3716e8bfe14554549fea2fc147cb54129382a8066")},
- {200, common.FromHex("ba03d891bb15408c940eea5ee3d54d419595102648d02774a0268d892add9c8e")},
- {2000, common.FromHex("f7a184f20df01c94f09537401d11e68d97ad0c00115233107f51b9c287ce60c7")},
+ {20, common.FromHex("330b0afae2853d96b9f015791fbe0fb7f239bf65f335f16dfc04b76c7536276d")},
+ {200, common.FromHex("5162b3735c06b5d606b043a3ee8adbdbbb408543f4966bca9dcc63da82684eeb")},
+ {2000, common.FromHex("4574cd8e6b17f3fe8ad89140d1d0bf4f1bd7a87a8ac3fb623b33550544c77635")},
} {
addresses, accounts := makeAccounts(tc.count)
// This spongeDb is used to check the sequence of disk-db-writes
- s := &spongeDb{sponge: sha3.NewLegacyKeccak256()}
- db := NewDatabase(rawdb.NewDatabase(s), nil)
+ s := &spongeDb{sponge: crypto.NewKeccakState()}
+ db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme)
trie := NewEmpty(db)
// Fill the trie with elements
for i := 0; i < tc.count; i++ {
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i])
}
// Flush trie -> database
- root, nodes, _ := trie.Commit(false)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ root, nodes := trie.Commit(false)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
// Flush memdb -> disk (sponge)
- _ = db.Commit(root, false)
+
+ _ = db.Commit(root)
if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) {
t.Errorf("test %d, disk write sequence wrong:\ngot %x exp %x\n", i, got, exp)
@@ -955,14 +974,14 @@ func TestCommitSequenceRandomBlobs(t *testing.T) {
count int
expWriteSeqHash []byte
}{
- {20, common.FromHex("8e4a01548551d139fa9e833ebc4e66fc1ba40a4b9b7259d80db32cff7b64ebbc")},
- {200, common.FromHex("6869b4e7b95f3097a19ddb30ff735f922b915314047e041614df06958fc50554")},
- {2000, common.FromHex("444200e6f4e2df49f77752f629a96ccf7445d4698c164f962bbd85a0526ef424")},
+ {20, common.FromHex("8016650c7a50cf88485fd06cde52d634a89711051107f00d21fae98234f2f13d")},
+ {200, common.FromHex("dde92ca9812e068e6982d04b40846dc65a61a9fd4996fc0f55f2fde172a8e13c")},
+ {2000, common.FromHex("ab553a7f9aff82e3929c382908e30ef7dd17a332933e92ba3fe873fc661ef382")},
} {
prng := rand.New(rand.NewSource(int64(i)))
// This spongeDb is used to check the sequence of disk-db-writes
- s := &spongeDb{sponge: sha3.NewLegacyKeccak256()}
- db := NewDatabase(rawdb.NewDatabase(s), nil)
+ s := &spongeDb{sponge: crypto.NewKeccakState()}
+ db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme)
trie := NewEmpty(db)
// Fill the trie with elements
for i := 0; i < tc.count; i++ {
@@ -981,10 +1000,11 @@ func TestCommitSequenceRandomBlobs(t *testing.T) {
trie.MustUpdate(key, val)
}
// Flush trie -> database
- root, nodes, _ := trie.Commit(false)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
+ root, nodes := trie.Commit(false)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
// Flush memdb -> disk (sponge)
- _ = db.Commit(root, false)
+
+ _ = db.Commit(root)
if got, exp := s.sponge.Sum(nil), tc.expWriteSeqHash; !bytes.Equal(got, exp) {
t.Fatalf("test %d, disk write sequence wrong:\ngot %x exp %x\n", i, got, exp)
@@ -996,17 +1016,24 @@ func TestCommitSequenceStackTrie(t *testing.T) {
for count := 1; count < 200; count++ {
prng := rand.New(rand.NewSource(int64(count)))
// This spongeDb is used to check the sequence of disk-db-writes
- s := &spongeDb{sponge: sha3.NewLegacyKeccak256(), id: "a"}
- db := NewDatabase(rawdb.NewDatabase(s), nil)
+ s := &spongeDb{
+ sponge: sha3.NewLegacyKeccak256(),
+ id: "a",
+ values: make(map[string]string),
+ }
+ db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme)
trie := NewEmpty(db)
- // Another sponge is used for the stacktrie commits
- stackTrieSponge := &spongeDb{sponge: sha3.NewLegacyKeccak256(), id: "b"}
- options := NewStackTrieOptions()
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
+ // Another sponge is used for the stacktrie commits
+ stackTrieSponge := &spongeDb{
+ sponge: sha3.NewLegacyKeccak256(),
+ id: "b",
+ values: make(map[string]string),
+ }
+ stTrie := NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
rawdb.WriteTrieNode(stackTrieSponge, common.Hash{}, path, hash, blob, db.Scheme())
})
- stTrie := NewStackTrie(options)
+
// Fill the trie with elements
for i := 0; i < count; i++ {
// For the stack trie, we need to do inserts in proper order
@@ -1026,16 +1053,19 @@ func TestCommitSequenceStackTrie(t *testing.T) {
_ = stTrie.Update(key, val)
}
// Flush trie -> database
- root, nodes, _ := trie.Commit(false)
+ root, nodes := trie.Commit(false)
// Flush memdb -> disk (sponge)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
- db.Commit(root, false)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
+ db.Commit(root)
+ s.Flush()
+
// And flush stacktrie -> disk
- stRoot := stTrie.Commit()
+ stRoot := stTrie.Hash()
if stRoot != root {
t.Fatalf("root wrong, got %x exp %x", stRoot, root)
}
+ stackTrieSponge.Flush()
if got, exp := stackTrieSponge.sponge.Sum(nil), s.sponge.Sum(nil); !bytes.Equal(got, exp) {
// Show the journal
t.Logf("Expected:")
@@ -1062,41 +1092,49 @@ func TestCommitSequenceStackTrie(t *testing.T) {
// that even a small trie which contains a leaf will have an extension making it
// not fit into 32 bytes, rlp-encoded. However, it's still the correct thing to do.
func TestCommitSequenceSmallRoot(t *testing.T) {
- s := &spongeDb{sponge: sha3.NewLegacyKeccak256(), id: "a"}
- db := NewDatabase(rawdb.NewDatabase(s), nil)
+ s := &spongeDb{
+ sponge: sha3.NewLegacyKeccak256(),
+ id: "a",
+ values: make(map[string]string),
+ }
+ db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme)
trie := NewEmpty(db)
- // Another sponge is used for the stacktrie commits
- stackTrieSponge := &spongeDb{sponge: sha3.NewLegacyKeccak256(), id: "b"}
- options := NewStackTrieOptions()
- options = options.WithWriter(func(path []byte, hash common.Hash, blob []byte) {
+ // Another sponge is used for the stacktrie commits
+ stackTrieSponge := &spongeDb{
+ sponge: sha3.NewLegacyKeccak256(),
+ id: "b",
+ values: make(map[string]string),
+ }
+ stTrie := NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
rawdb.WriteTrieNode(stackTrieSponge, common.Hash{}, path, hash, blob, db.Scheme())
})
- stTrie := NewStackTrie(options)
// Add a single small-element to the trie(s)
key := make([]byte, 5)
key[0] = 1
_ = trie.Update(key, []byte{0x1})
_ = stTrie.Update(key, []byte{0x1})
// Flush trie -> database
- root, nodes, _ := trie.Commit(false)
+ root, nodes := trie.Commit(false)
// Flush memdb -> disk (sponge)
- db.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
- db.Commit(root, false)
+ db.Update(root, types.EmptyRootHash, trienode.NewWithNodeSet(nodes))
+ db.Commit(root)
+
// And flush stacktrie -> disk
- stRoot := stTrie.Commit()
+ stRoot := stTrie.Hash()
if stRoot != root {
t.Fatalf("root wrong, got %x exp %x", stRoot, root)
}
-
t.Logf("root: %x\n", stRoot)
+ s.Flush()
+ stackTrieSponge.Flush()
if got, exp := stackTrieSponge.sponge.Sum(nil), s.sponge.Sum(nil); !bytes.Equal(got, exp) {
t.Fatalf("test, disk write sequence wrong:\ngot %x exp %x\n", got, exp)
}
}
-// BenchmarkCommitAfterHashFixedSize benchmarks the Commit (after Hash) of a fixed number of updates to a trie.
+// BenchmarkHashFixedSize benchmarks the hash of a fixed number of updates to a trie.
// This benchmark is meant to capture the difference on efficiency of small versus large changes. Typically,
// storage tries are small (a couple of entries), whereas the full post-block account trie update is large (a couple
// of thousand entries)
@@ -1146,7 +1184,7 @@ func BenchmarkHashFixedSize(b *testing.B) {
func benchmarkHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) {
b.ReportAllocs()
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
for i := 0; i < len(addresses); i++ {
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i])
}
@@ -1202,7 +1240,7 @@ func BenchmarkCommitAfterHashFixedSize(b *testing.B) {
func benchmarkCommitAfterHashFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) {
b.ReportAllocs()
- trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase(), nil))
+ trie := NewEmpty(newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.HashScheme))
for i := 0; i < len(addresses); i++ {
trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i])
}
@@ -1213,67 +1251,6 @@ func benchmarkCommitAfterHashFixedSize(b *testing.B, addresses [][20]byte, accou
b.StopTimer()
}
-func BenchmarkDerefRootFixedSize(b *testing.B) {
- b.Run("10", func(b *testing.B) {
- b.StopTimer()
-
- acc, add := makeAccounts(20)
- for i := 0; i < b.N; i++ {
- benchmarkDerefRootFixedSize(b, acc, add)
- }
- })
- b.Run("100", func(b *testing.B) {
- b.StopTimer()
-
- acc, add := makeAccounts(100)
- for i := 0; i < b.N; i++ {
- benchmarkDerefRootFixedSize(b, acc, add)
- }
- })
-
- b.Run("1K", func(b *testing.B) {
- b.StopTimer()
-
- acc, add := makeAccounts(1000)
- for i := 0; i < b.N; i++ {
- benchmarkDerefRootFixedSize(b, acc, add)
- }
- })
- b.Run("10K", func(b *testing.B) {
- b.StopTimer()
-
- acc, add := makeAccounts(10000)
- for i := 0; i < b.N; i++ {
- benchmarkDerefRootFixedSize(b, acc, add)
- }
- })
- b.Run("100K", func(b *testing.B) {
- b.StopTimer()
-
- acc, add := makeAccounts(100000)
- for i := 0; i < b.N; i++ {
- benchmarkDerefRootFixedSize(b, acc, add)
- }
- })
-}
-
-func benchmarkDerefRootFixedSize(b *testing.B, addresses [][20]byte, accounts [][]byte) {
- b.ReportAllocs()
- triedb := NewDatabase(rawdb.NewMemoryDatabase(), nil)
- trie := NewEmpty(triedb)
-
- for i := 0; i < len(addresses); i++ {
- trie.MustUpdate(crypto.Keccak256(addresses[i][:]), accounts[i])
- }
-
- h := trie.Hash()
- root, nodes, _ := trie.Commit(false)
- triedb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
- b.StartTimer()
- triedb.Dereference(h)
- b.StopTimer()
-}
-
func getString(trie *Trie, k string) []byte {
return trie.MustGet([]byte(k))
}
diff --git a/trie/triedb/pathdb/testutils.go b/trie/triedb/pathdb/testutils.go
deleted file mode 100644
index d6fdacb421..0000000000
--- a/trie/triedb/pathdb/testutils.go
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2023 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 pathdb
-
-import (
- "bytes"
- "fmt"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/trie/trienode"
- "github.com/ethereum/go-ethereum/trie/triestate"
- "golang.org/x/exp/slices"
-)
-
-// testHasher is a test utility for computing root hash of a batch of state
-// elements. The hash algorithm is to sort all the elements in lexicographical
-// order, concat the key and value in turn, and perform hash calculation on
-// the concatenated bytes. Except the root hash, a nodeset will be returned
-// once Commit is called, which contains all the changes made to hasher.
-type testHasher struct {
- owner common.Hash // owner identifier
- root common.Hash // original root
- dirties map[common.Hash][]byte // dirty states
- cleans map[common.Hash][]byte // clean states
-}
-
-// newTestHasher constructs a hasher object with provided states.
-func newTestHasher(owner common.Hash, root common.Hash, cleans map[common.Hash][]byte) (*testHasher, error) {
- if cleans == nil {
- cleans = make(map[common.Hash][]byte)
- }
- if got, _ := hash(cleans); got != root {
- return nil, fmt.Errorf("state root mismatched, want: %x, got: %x", root, got)
- }
- return &testHasher{
- owner: owner,
- root: root,
- dirties: make(map[common.Hash][]byte),
- cleans: cleans,
- }, nil
-}
-
-// Get returns the value for key stored in the trie.
-func (h *testHasher) Get(key []byte) ([]byte, error) {
- hash := common.BytesToHash(key)
- val, ok := h.dirties[hash]
- if ok {
- return val, nil
- }
- return h.cleans[hash], nil
-}
-
-// Update associates key with value in the trie.
-func (h *testHasher) Update(key, value []byte) error {
- h.dirties[common.BytesToHash(key)] = common.CopyBytes(value)
- return nil
-}
-
-// Delete removes any existing value for key from the trie.
-func (h *testHasher) Delete(key []byte) error {
- h.dirties[common.BytesToHash(key)] = nil
- return nil
-}
-
-// Commit computes the new hash of the states and returns the set with all
-// state changes.
-func (h *testHasher) Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error) {
- var (
- nodes = make(map[common.Hash][]byte)
- set = trienode.NewNodeSet(h.owner)
- )
- for hash, val := range h.cleans {
- nodes[hash] = val
- }
- for hash, val := range h.dirties {
- nodes[hash] = val
- if bytes.Equal(val, h.cleans[hash]) {
- continue
- }
- if len(val) == 0 {
- set.AddNode(hash.Bytes(), trienode.NewDeleted())
- } else {
- set.AddNode(hash.Bytes(), trienode.New(crypto.Keccak256Hash(val), val))
- }
- }
- root, blob := hash(nodes)
-
- // Include the dirty root node as well.
- if root != types.EmptyRootHash && root != h.root {
- set.AddNode(nil, trienode.New(root, blob))
- }
- if root == types.EmptyRootHash && h.root != types.EmptyRootHash {
- set.AddNode(nil, trienode.NewDeleted())
- }
- return root, set, nil
-}
-
-// hash performs the hash computation upon the provided states.
-func hash(states map[common.Hash][]byte) (common.Hash, []byte) {
- var hs []common.Hash
- for hash := range states {
- hs = append(hs, hash)
- }
- slices.SortFunc(hs, common.Hash.Cmp)
-
- var input []byte
- for _, hash := range hs {
- if len(states[hash]) == 0 {
- continue
- }
- input = append(input, hash.Bytes()...)
- input = append(input, states[hash]...)
- }
- if len(input) == 0 {
- return types.EmptyRootHash, nil
- }
- return crypto.Keccak256Hash(input), input
-}
-
-type hashLoader struct {
- accounts map[common.Hash][]byte
- storages map[common.Hash]map[common.Hash][]byte
-}
-
-func newHashLoader(accounts map[common.Hash][]byte, storages map[common.Hash]map[common.Hash][]byte) *hashLoader {
- return &hashLoader{
- accounts: accounts,
- storages: storages,
- }
-}
-
-// OpenTrie opens the main account trie.
-func (l *hashLoader) OpenTrie(root common.Hash) (triestate.Trie, error) {
- return newTestHasher(common.Hash{}, root, l.accounts)
-}
-
-// OpenStorageTrie opens the storage trie of an account.
-func (l *hashLoader) OpenStorageTrie(stateRoot common.Hash, addrHash, root common.Hash) (triestate.Trie, error) {
- return newTestHasher(addrHash, root, l.storages[addrHash])
-}
diff --git a/trie/trienode/node.go b/trie/trienode/node.go
index 95315c2e9a..09f355f3b5 100644
--- a/trie/trienode/node.go
+++ b/trie/trienode/node.go
@@ -78,7 +78,7 @@ func NewNodeSet(owner common.Hash) *NodeSet {
// ForEachWithOrder iterates the nodes with the order from bottom to top,
// right to left, nodes with the longest path will be iterated first.
func (set *NodeSet) ForEachWithOrder(callback func(path string, n *Node)) {
- var paths []string
+ paths := make([]string, 0, len(set.Nodes))
for path := range set.Nodes {
paths = append(paths, path)
}
@@ -114,7 +114,12 @@ func (set *NodeSet) Merge(owner common.Hash, nodes map[string]*Node) error {
set.updates -= 1
}
}
- set.AddNode([]byte(path), node)
+ if node.IsDeleted() {
+ set.deletes += 1
+ } else {
+ set.updates += 1
+ }
+ set.Nodes[path] = node
}
return nil
}
@@ -130,30 +135,18 @@ func (set *NodeSet) Size() (int, int) {
return set.updates, set.deletes
}
-// Hashes returns the hashes of all updated nodes. TODO(rjl493456442) how can
-// we get rid of it?
-func (set *NodeSet) Hashes() []common.Hash {
- var ret []common.Hash
- for _, node := range set.Nodes {
- ret = append(ret, node.Hash)
- }
- return ret
-}
-
// Summary returns a string-representation of the NodeSet.
func (set *NodeSet) Summary() string {
var out = new(strings.Builder)
fmt.Fprintf(out, "nodeset owner: %v\n", set.Owner)
- if set.Nodes != nil {
- for path, n := range set.Nodes {
- // Deletion
- if n.IsDeleted() {
- fmt.Fprintf(out, " [-]: %x\n", path)
- continue
- }
- // Insertion or update
- fmt.Fprintf(out, " [+/*]: %x -> %v \n", path, n.Hash)
+ for path, n := range set.Nodes {
+ // Deletion
+ if n.IsDeleted() {
+ fmt.Fprintf(out, " [-]: %x\n", path)
+ continue
}
+ // Insertion or update
+ fmt.Fprintf(out, " [+/*]: %x -> %v \n", path, n.Hash)
}
for _, n := range set.Leaves {
fmt.Fprintf(out, "[leaf]: %v\n", n)
@@ -191,7 +184,7 @@ func (set *MergedNodeSet) Merge(other *NodeSet) error {
// Flatten returns a two-dimensional map for internal nodes.
func (set *MergedNodeSet) Flatten() map[common.Hash]map[string]*Node {
- nodes := make(map[common.Hash]map[string]*Node)
+ nodes := make(map[common.Hash]map[string]*Node, len(set.Sets))
for owner, set := range set.Sets {
nodes[owner] = set.Nodes
}
diff --git a/trie/trienode/node_test.go b/trie/trienode/node_test.go
new file mode 100644
index 0000000000..bcb3a2202b
--- /dev/null
+++ b/trie/trienode/node_test.go
@@ -0,0 +1,61 @@
+// Copyright 2023 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 trienode
+
+import (
+ "crypto/rand"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+)
+
+func BenchmarkMerge(b *testing.B) {
+ b.Run("1K", func(b *testing.B) {
+ benchmarkMerge(b, 1000)
+ })
+ b.Run("10K", func(b *testing.B) {
+ benchmarkMerge(b, 10_000)
+ })
+}
+
+func benchmarkMerge(b *testing.B, count int) {
+ x := NewNodeSet(common.Hash{})
+ y := NewNodeSet(common.Hash{})
+ addNode := func(s *NodeSet) {
+ path := make([]byte, 4)
+ rand.Read(path)
+ blob := make([]byte, 32)
+ rand.Read(blob)
+ hash := crypto.Keccak256Hash(blob)
+ s.AddNode(path, New(hash, blob))
+ }
+ for i := 0; i < count; i++ {
+ // Random path of 4 nibbles
+ addNode(x)
+ addNode(y)
+ }
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ // Store set x into a backup
+ z := NewNodeSet(common.Hash{})
+ z.Merge(common.Hash{}, x.Nodes)
+ // Merge y into x
+ x.Merge(common.Hash{}, y.Nodes)
+ x = z
+ }
+}
diff --git a/trie/trienode/proof.go b/trie/trienode/proof.go
index 012f0087dd..d3075ecccf 100644
--- a/trie/trienode/proof.go
+++ b/trie/trienode/proof.go
@@ -102,14 +102,14 @@ func (db *ProofSet) DataSize() int {
return db.dataSize
}
-// List converts the node set to a ProofList
-func (db *ProofSet) List() ProofList {
+// List converts the node set to a slice of bytes.
+func (db *ProofSet) List() [][]byte {
db.lock.RLock()
defer db.lock.RUnlock()
- var values ProofList
- for _, key := range db.order {
- values = append(values, db.nodes[key])
+ values := make([][]byte, len(db.order))
+ for i, key := range db.order {
+ values[i] = db.nodes[key]
}
return values
}
diff --git a/trie/triestate/state.go b/trie/triestate/state.go
index 4c47e9c397..62a9043873 100644
--- a/trie/triestate/state.go
+++ b/trie/triestate/state.go
@@ -16,61 +16,22 @@
package triestate
-import (
- "errors"
- "fmt"
- "sync"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/trie/trienode"
- "golang.org/x/crypto/sha3"
-)
-
-// Trie is an Ethereum state trie, can be implemented by Ethereum Merkle Patricia
-// tree or Verkle tree.
-type Trie interface {
- // Get returns the value for key stored in the trie.
- Get(key []byte) ([]byte, error)
-
- // Update associates key with value in the trie.
- Update(key, value []byte) error
-
- // Delete removes any existing value for key from the trie.
- Delete(key []byte) error
-
- // Commit the trie and returns a set of dirty nodes generated along with
- // the new root hash.
- Commit(collectLeaf bool) (common.Hash, *trienode.NodeSet, error)
-}
-
-// TrieLoader wraps functions to load tries.
-type TrieLoader interface {
- // OpenTrie opens the main account trie.
- OpenTrie(root common.Hash) (Trie, error)
-
- // OpenStorageTrie opens the storage trie of an account.
- OpenStorageTrie(stateRoot common.Hash, addrHash, root common.Hash) (Trie, error)
-}
+import "github.com/ethereum/go-ethereum/common"
// Set represents a collection of mutated states during a state transition.
// The value refers to the original content of state before the transition
// is made. Nil means that the state was not present previously.
type Set struct {
- Accounts map[common.Address][]byte // Mutated account set, nil means the account was not present
- Storages map[common.Address]map[common.Hash][]byte // Mutated storage set, nil means the slot was not present
- Incomplete map[common.Address]struct{} // Indicator whether the storage is incomplete due to large deletion
- size common.StorageSize // Approximate size of set
+ Accounts map[common.Address][]byte // Mutated account set, nil means the account was not present
+ Storages map[common.Address]map[common.Hash][]byte // Mutated storage set, nil means the slot was not present
+ size common.StorageSize // Approximate size of set
}
// New constructs the state set with provided data.
-func New(accounts map[common.Address][]byte, storages map[common.Address]map[common.Hash][]byte, incomplete map[common.Address]struct{}) *Set {
+func New(accounts map[common.Address][]byte, storages map[common.Address]map[common.Hash][]byte) *Set {
return &Set{
- Accounts: accounts,
- Storages: storages,
- Incomplete: incomplete,
+ Accounts: accounts,
+ Storages: storages,
}
}
@@ -88,189 +49,5 @@ func (s *Set) Size() common.StorageSize {
}
s.size += common.StorageSize(common.AddressLength)
}
- s.size += common.StorageSize(common.AddressLength * len(s.Incomplete))
return s.size
}
-
-// context wraps all fields for executing state diffs.
-type context struct {
- prevRoot common.Hash
- postRoot common.Hash
- accounts map[common.Address][]byte
- storages map[common.Address]map[common.Hash][]byte
- accountTrie Trie
- nodes *trienode.MergedNodeSet
-}
-
-// Apply traverses the provided state diffs, apply them in the associated
-// post-state and return the generated dirty trie nodes. The state can be
-// loaded via the provided trie loader.
-func Apply(prevRoot common.Hash, postRoot common.Hash, accounts map[common.Address][]byte, storages map[common.Address]map[common.Hash][]byte, loader TrieLoader) (map[common.Hash]map[string]*trienode.Node, error) {
- tr, err := loader.OpenTrie(postRoot)
- if err != nil {
- return nil, err
- }
- ctx := &context{
- prevRoot: prevRoot,
- postRoot: postRoot,
- accounts: accounts,
- storages: storages,
- accountTrie: tr,
- nodes: trienode.NewMergedNodeSet(),
- }
- for addr, account := range accounts {
- var err error
- if len(account) == 0 {
- err = deleteAccount(ctx, loader, addr)
- } else {
- err = updateAccount(ctx, loader, addr)
- }
- if err != nil {
- return nil, fmt.Errorf("failed to revert state, err: %w", err)
- }
- }
- root, result, err := tr.Commit(false)
- if err != nil {
- return nil, err
- }
- if root != prevRoot {
- return nil, fmt.Errorf("failed to revert state, want %#x, got %#x", prevRoot, root)
- }
- if err := ctx.nodes.Merge(result); err != nil {
- return nil, err
- }
- return ctx.nodes.Flatten(), nil
-}
-
-// updateAccount the account was present in prev-state, and may or may not
-// existent in post-state. Apply the reverse diff and verify if the storage
-// root matches the one in prev-state account.
-func updateAccount(ctx *context, loader TrieLoader, addr common.Address) error {
- // The account was present in prev-state, decode it from the
- // 'slim-rlp' format bytes.
- h := newHasher()
- defer h.release()
-
- addrHash := h.hash(addr.Bytes())
- prev, err := types.FullAccount(ctx.accounts[addr])
- if err != nil {
- return err
- }
- // The account may or may not existent in post-state, try to
- // load it and decode if it's found.
- blob, err := ctx.accountTrie.Get(addrHash.Bytes())
- if err != nil {
- return err
- }
- post := types.NewEmptyStateAccount()
- if len(blob) != 0 {
- if err := rlp.DecodeBytes(blob, &post); err != nil {
- return err
- }
- }
- // Apply all storage changes into the post-state storage trie.
- st, err := loader.OpenStorageTrie(ctx.postRoot, addrHash, post.Root)
- if err != nil {
- return err
- }
- for key, val := range ctx.storages[addr] {
- var err error
- if len(val) == 0 {
- err = st.Delete(key.Bytes())
- } else {
- err = st.Update(key.Bytes(), val)
- }
- if err != nil {
- return err
- }
- }
- root, result, err := st.Commit(false)
- if err != nil {
- return err
- }
- if root != prev.Root {
- return errors.New("failed to reset storage trie")
- }
- // The returned set can be nil if storage trie is not changed
- // at all.
- if result != nil {
- if err := ctx.nodes.Merge(result); err != nil {
- return err
- }
- }
- // Write the prev-state account into the main trie
- full, err := rlp.EncodeToBytes(prev)
- if err != nil {
- return err
- }
- return ctx.accountTrie.Update(addrHash.Bytes(), full)
-}
-
-// deleteAccount the account was not present in prev-state, and is expected
-// to be existent in post-state. Apply the reverse diff and verify if the
-// account and storage is wiped out correctly.
-func deleteAccount(ctx *context, loader TrieLoader, addr common.Address) error {
- // The account must be existent in post-state, load the account.
- h := newHasher()
- defer h.release()
-
- addrHash := h.hash(addr.Bytes())
- blob, err := ctx.accountTrie.Get(addrHash.Bytes())
- if err != nil {
- return err
- }
- if len(blob) == 0 {
- return fmt.Errorf("account is non-existent %#x", addrHash)
- }
- var post types.StateAccount
- if err := rlp.DecodeBytes(blob, &post); err != nil {
- return err
- }
- st, err := loader.OpenStorageTrie(ctx.postRoot, addrHash, post.Root)
- if err != nil {
- return err
- }
- for key, val := range ctx.storages[addr] {
- if len(val) != 0 {
- return errors.New("expect storage deletion")
- }
- if err := st.Delete(key.Bytes()); err != nil {
- return err
- }
- }
- root, result, err := st.Commit(false)
- if err != nil {
- return err
- }
- if root != types.EmptyRootHash {
- return errors.New("failed to clear storage trie")
- }
- // The returned set can be nil if storage trie is not changed
- // at all.
- if result != nil {
- if err := ctx.nodes.Merge(result); err != nil {
- return err
- }
- }
- // Delete the post-state account from the main trie.
- return ctx.accountTrie.Delete(addrHash.Bytes())
-}
-
-// hasher is used to compute the sha256 hash of the provided data.
-type hasher struct{ sha crypto.KeccakState }
-
-var hasherPool = sync.Pool{
- New: func() interface{} { return &hasher{sha: sha3.NewLegacyKeccak256().(crypto.KeccakState)} },
-}
-
-func newHasher() *hasher {
- return hasherPool.Get().(*hasher)
-}
-
-func (h *hasher) hash(data []byte) common.Hash {
- return crypto.HashData(h.sha, data)
-}
-
-func (h *hasher) release() {
- hasherPool.Put(h)
-}
diff --git a/trie/utils/verkle.go b/trie/utils/verkle.go
index ce059edc64..2a4a632d49 100644
--- a/trie/utils/verkle.go
+++ b/trie/utils/verkle.go
@@ -23,7 +23,7 @@ import (
"github.com/crate-crypto/go-ipa/bandersnatch/fr"
"github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/metrics"
- "github.com/gballet/go-verkle"
+ "github.com/ethereum/go-verkle"
"github.com/holiman/uint256"
)
@@ -206,15 +206,10 @@ func CodeSizeKey(address []byte) []byte {
func codeChunkIndex(chunk *uint256.Int) (*uint256.Int, byte) {
var (
- chunkOffset = new(uint256.Int).Add(codeOffset, chunk)
- treeIndex = new(uint256.Int).Div(chunkOffset, verkleNodeWidth)
- subIndexMod = new(uint256.Int).Mod(chunkOffset, verkleNodeWidth)
+ chunkOffset = new(uint256.Int).Add(codeOffset, chunk)
+ treeIndex, subIndexMod = new(uint256.Int).DivMod(chunkOffset, verkleNodeWidth, new(uint256.Int))
)
- var subIndex byte
- if len(subIndexMod) != 0 {
- subIndex = byte(subIndexMod[0])
- }
- return treeIndex, subIndex
+ return treeIndex, byte(subIndexMod.Uint64())
}
// CodeChunkKey returns the verkle tree key of the code chunk for the
@@ -224,7 +219,7 @@ func CodeChunkKey(address []byte, chunk *uint256.Int) []byte {
return GetTreeKey(address, treeIndex, subIndex)
}
-func storageIndex(bytes []byte) (*uint256.Int, byte) {
+func StorageIndex(bytes []byte) (*uint256.Int, byte) {
// If the storage slot is in the header, we need to add the header offset.
var key uint256.Int
key.SetBytes(bytes)
@@ -250,7 +245,7 @@ func storageIndex(bytes []byte) (*uint256.Int, byte) {
// StorageSlotKey returns the verkle tree key of the storage slot for the
// specified account.
func StorageSlotKey(address []byte, storageKey []byte) []byte {
- treeIndex, subIndex := storageIndex(storageKey)
+ treeIndex, subIndex := StorageIndex(storageKey)
return GetTreeKey(address, treeIndex, subIndex)
}
@@ -301,7 +296,7 @@ func CodeChunkKeyWithEvaluatedAddress(addressPoint *verkle.Point, chunk *uint256
// slot for the specified account. The difference between StorageSlotKey is the
// address evaluation is already computed to minimize the computational overhead.
func StorageSlotKeyWithEvaluatedAddress(evaluated *verkle.Point, storageKey []byte) []byte {
- treeIndex, subIndex := storageIndex(storageKey)
+ treeIndex, subIndex := StorageIndex(storageKey)
return GetTreeKeyWithEvaluatedAddress(evaluated, treeIndex, subIndex)
}
diff --git a/trie/utils/verkle_test.go b/trie/utils/verkle_test.go
index 28b059c379..c29504a6d0 100644
--- a/trie/utils/verkle_test.go
+++ b/trie/utils/verkle_test.go
@@ -20,7 +20,7 @@ import (
"bytes"
"testing"
- "github.com/gballet/go-verkle"
+ "github.com/ethereum/go-verkle"
"github.com/holiman/uint256"
)
diff --git a/trie/verkle.go b/trie/verkle.go
index 89e2e53408..a457097e95 100644
--- a/trie/verkle.go
+++ b/trie/verkle.go
@@ -20,14 +20,14 @@ import (
"encoding/binary"
"errors"
"fmt"
- "math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/trie/utils"
- "github.com/gballet/go-verkle"
+ "github.com/ethereum/go-ethereum/triedb/database"
+ "github.com/ethereum/go-verkle"
"github.com/holiman/uint256"
)
@@ -40,13 +40,12 @@ var (
// interface so that Verkle trees can be reused verbatim.
type VerkleTrie struct {
root verkle.VerkleNode
- db *Database
cache *utils.PointCache
reader *trieReader
}
// NewVerkleTrie constructs a verkle tree based on the specified root hash.
-func NewVerkleTrie(root common.Hash, db *Database, cache *utils.PointCache) (*VerkleTrie, error) {
+func NewVerkleTrie(root common.Hash, db database.Database, cache *utils.PointCache) (*VerkleTrie, error) {
reader, err := newTrieReader(root, common.Hash{}, db)
if err != nil {
return nil, err
@@ -65,7 +64,6 @@ func NewVerkleTrie(root common.Hash, db *Database, cache *utils.PointCache) (*Ve
}
return &VerkleTrie{
root: node,
- db: db,
cache: cache,
reader: reader,
}, nil
@@ -108,7 +106,7 @@ func (t *VerkleTrie) GetAccount(addr common.Address) (*types.StateAccount, error
for i := 0; i < len(balance)/2; i++ {
balance[len(balance)-i-1], balance[i] = balance[i], balance[len(balance)-i-1]
}
- acc.Balance = new(big.Int).SetBytes(balance[:])
+ acc.Balance = new(uint256.Int).SetBytes32(balance[:])
// Decode codehash
acc.CodeHash = values[utils.CodeKeccakLeafKey]
@@ -146,10 +144,8 @@ func (t *VerkleTrie) UpdateAccount(addr common.Address, acc *types.StateAccount)
// Encode balance in little-endian
bytes := acc.Balance.Bytes()
- if len(bytes) > 0 {
- for i, b := range bytes {
- balance[len(bytes)-i-1] = b
- }
+ for i, b := range bytes {
+ balance[len(bytes)-i-1] = b
}
values[utils.BalanceLeafKey] = balance[:]
@@ -219,22 +215,21 @@ func (t *VerkleTrie) Hash() common.Hash {
}
// Commit writes all nodes to the tree's memory database.
-func (t *VerkleTrie) Commit(_ bool) (common.Hash, *trienode.NodeSet, error) {
- root, ok := t.root.(*verkle.InternalNode)
- if !ok {
- return common.Hash{}, nil, errors.New("unexpected root node type")
- }
+func (t *VerkleTrie) Commit(_ bool) (common.Hash, *trienode.NodeSet) {
+ root := t.root.(*verkle.InternalNode)
nodes, err := root.BatchSerialize()
if err != nil {
- return common.Hash{}, nil, fmt.Errorf("serializing tree nodes: %s", err)
+ // Error return from this function indicates error in the code logic
+ // of BatchSerialize, and we fail catastrophically if this is the case.
+ panic(fmt.Errorf("BatchSerialize failed: %v", err))
}
nodeset := trienode.NewNodeSet(common.Hash{})
for _, node := range nodes {
- // hash parameter is not used in pathdb
+ // Hash parameter is not used in pathdb
nodeset.AddNode(node.Path, trienode.New(common.Hash{}, node.SerializedBytes))
}
// Serialize root commitment form
- return t.Hash(), nodeset, nil
+ return t.Hash(), nodeset
}
// NodeIterator implements state.Trie, returning an iterator that returns
@@ -262,7 +257,6 @@ func (t *VerkleTrie) Prove(key []byte, proofDb ethdb.KeyValueWriter) error {
func (t *VerkleTrie) Copy() *VerkleTrie {
return &VerkleTrie{
root: t.root.Copy(),
- db: t.db,
cache: t.cache,
reader: t.reader,
}
@@ -373,3 +367,8 @@ func (t *VerkleTrie) ToDot() string {
func (t *VerkleTrie) nodeResolver(path []byte) ([]byte, error) {
return t.reader.node(path, common.Hash{})
}
+
+// Witness returns a set containing all trie nodes that have been accessed.
+func (t *VerkleTrie) Witness() map[string]struct{} {
+ panic("not implemented")
+}
diff --git a/trie/verkle_test.go b/trie/verkle_test.go
index bd31ea3879..0cbe28bf01 100644
--- a/trie/verkle_test.go
+++ b/trie/verkle_test.go
@@ -18,27 +18,26 @@ package trie
import (
"bytes"
- "math/big"
"reflect"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
"github.com/ethereum/go-ethereum/trie/utils"
+ "github.com/holiman/uint256"
)
var (
accounts = map[common.Address]*types.StateAccount{
{1}: {
Nonce: 100,
- Balance: big.NewInt(100),
+ Balance: uint256.NewInt(100),
CodeHash: common.Hash{0x1}.Bytes(),
},
{2}: {
Nonce: 200,
- Balance: big.NewInt(200),
+ Balance: uint256.NewInt(200),
CodeHash: common.Hash{0x2}.Bytes(),
},
}
@@ -57,12 +56,7 @@ var (
)
func TestVerkleTreeReadWrite(t *testing.T) {
- db := NewDatabase(rawdb.NewMemoryDatabase(), &Config{
- IsVerkle: true,
- PathDB: pathdb.Defaults,
- })
- defer db.Close()
-
+ db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.PathScheme)
tr, _ := NewVerkleTrie(types.EmptyVerkleHash, db, utils.NewPointCache(100))
for addr, acct := range accounts {
diff --git a/trie/database.go b/triedb/database.go
similarity index 89%
rename from trie/database.go
rename to triedb/database.go
index e20f7ef903..91386a9dbc 100644
--- a/trie/database.go
+++ b/triedb/database.go
@@ -14,18 +14,21 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package trie
+package triedb
import (
"errors"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/trie/triedb/hashdb"
- "github.com/ethereum/go-ethereum/trie/triedb/pathdb"
+ "github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/trie/triestate"
+ "github.com/ethereum/go-ethereum/triedb/database"
+ "github.com/ethereum/go-ethereum/triedb/hashdb"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
)
// Config defines all necessary options for database.
@@ -46,9 +49,6 @@ var HashDefaults = &Config{
// backend defines the methods needed to access/update trie nodes in different
// state scheme.
type backend interface {
- // Scheme returns the identifier of used storage scheme.
- Scheme() string
-
// Initialized returns an indicator if the state data is already initialized
// according to the state scheme.
Initialized(genesisRoot common.Hash) bool
@@ -74,6 +74,10 @@ type backend interface {
// Close closes the trie database backend and releases all held resources.
Close() error
+
+ // Reader returns a reader for accessing all trie nodes with provided state
+ // root. An error will be returned if the requested state is not available.
+ Reader(root common.Hash) (database.Reader, error)
}
// Database is the wrapper of the underlying backend which is shared by different
@@ -106,23 +110,24 @@ func NewDatabase(diskdb ethdb.Database, config *Config) *Database {
log.Crit("Both 'hash' and 'path' mode are configured")
}
if config.PathDB != nil {
- db.backend = pathdb.New(diskdb, config.PathDB)
+ db.backend = pathdb.New(diskdb, config.PathDB, config.IsVerkle)
} else {
- db.backend = hashdb.New(diskdb, config.HashDB, mptResolver{})
+ var resolver hashdb.ChildResolver
+ if config.IsVerkle {
+ // TODO define verkle resolver
+ log.Crit("verkle does not use a hash db")
+ } else {
+ resolver = trie.MerkleResolver{}
+ }
+ db.backend = hashdb.New(diskdb, config.HashDB, resolver)
}
return db
}
// Reader returns a reader for accessing all trie nodes with provided state root.
// An error will be returned if the requested state is not available.
-func (db *Database) Reader(blockRoot common.Hash) (Reader, error) {
- switch b := db.backend.(type) {
- case *hashdb.Database:
- return b.Reader(blockRoot)
- case *pathdb.Database:
- return b.Reader(blockRoot)
- }
- return nil, errors.New("unknown backend")
+func (db *Database) Reader(blockRoot common.Hash) (database.Reader, error) {
+ return db.backend.Reader(blockRoot)
}
// Update performs a state transition by committing dirty nodes contained in the
@@ -172,7 +177,10 @@ func (db *Database) Initialized(genesisRoot common.Hash) bool {
// Scheme returns the node scheme used in the database.
func (db *Database) Scheme() string {
- return db.backend.Scheme()
+ if db.config.PathDB != nil {
+ return rawdb.PathScheme
+ }
+ return rawdb.HashScheme
}
// Close flushes the dangling preimages to disk and closes the trie database.
@@ -190,8 +198,7 @@ func (db *Database) WritePreimages() {
}
}
-// Preimage retrieves a cached trie node pre-image from memory. If it cannot be
-// found cached, the method queries the persistent database for the content.
+// Preimage retrieves a cached trie node pre-image from preimage store.
func (db *Database) Preimage(hash common.Hash) []byte {
if db.preimages == nil {
return nil
@@ -199,6 +206,14 @@ func (db *Database) Preimage(hash common.Hash) []byte {
return db.preimages.preimage(hash)
}
+// InsertPreimage writes pre-images of trie node to the preimage store.
+func (db *Database) InsertPreimage(preimages map[common.Hash][]byte) {
+ if db.preimages == nil {
+ return
+ }
+ db.preimages.insertPreimage(preimages)
+}
+
// Cap iteratively flushes old but still referenced trie nodes until the total
// memory usage goes below the given threshold. The held pre-images accumulated
// up to this point will be flushed in case the size exceeds the threshold.
@@ -249,7 +264,7 @@ func (db *Database) Recover(target common.Hash) error {
if !ok {
return errors.New("not supported")
}
- return pdb.Recover(target, &trieLoader{db: db})
+ return pdb.Recover(target)
}
// Recoverable returns the indicator if the specified state is enabled to be
diff --git a/triedb/database/database.go b/triedb/database/database.go
new file mode 100644
index 0000000000..9bd5da08d1
--- /dev/null
+++ b/triedb/database/database.go
@@ -0,0 +1,37 @@
+// Copyright 2024 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 database
+
+import "github.com/ethereum/go-ethereum/common"
+
+// Reader wraps the Node method of a backing trie reader.
+type Reader interface {
+ // Node retrieves the trie node blob with the provided trie identifier,
+ // node path and the corresponding node hash. No error will be returned
+ // if the node is not found.
+ //
+ // Don't modify the returned byte slice since it's not deep-copied and
+ // still be referenced by database.
+ Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, error)
+}
+
+// Database wraps the methods of a backing trie store.
+type Database interface {
+ // Reader returns a node reader associated with the specific state.
+ // An error will be returned if the specified state is not available.
+ Reader(stateRoot common.Hash) (Reader, error)
+}
diff --git a/trie/triedb/hashdb/database.go b/triedb/hashdb/database.go
similarity index 99%
rename from trie/triedb/hashdb/database.go
rename to triedb/hashdb/database.go
index e45ccdba32..bb0deca9a7 100644
--- a/trie/triedb/hashdb/database.go
+++ b/triedb/hashdb/database.go
@@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/trie/triestate"
+ "github.com/ethereum/go-ethereum/triedb/database"
)
var (
@@ -619,19 +620,13 @@ func (db *Database) Size() (common.StorageSize, common.StorageSize) {
func (db *Database) Close() error {
if db.cleans != nil {
db.cleans.Reset()
- db.cleans = nil
}
return nil
}
-// Scheme returns the node scheme used in the database.
-func (db *Database) Scheme() string {
- return rawdb.HashScheme
-}
-
// Reader retrieves a node reader belonging to the given state root.
// An error will be returned if the requested state is not available.
-func (db *Database) Reader(root common.Hash) (*reader, error) {
+func (db *Database) Reader(root common.Hash) (database.Reader, error) {
if _, err := db.node(root); err != nil {
return nil, fmt.Errorf("state %#x is not available, %v", root, err)
}
diff --git a/triedb/history.go b/triedb/history.go
new file mode 100644
index 0000000000..f663cdd7c2
--- /dev/null
+++ b/triedb/history.go
@@ -0,0 +1,72 @@
+// Copyright 2023 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 triedb
+
+import (
+ "errors"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/triedb/pathdb"
+)
+
+// AccountHistory inspects the account history within the specified range.
+//
+// Start: State ID of the first history object for the query. 0 implies the first
+// available object is selected as the starting point.
+//
+// End: State ID of the last history for the query. 0 implies the last available
+// object is selected as the starting point. Note end is included for query.
+//
+// This function is only supported by path mode database.
+func (db *Database) AccountHistory(address common.Address, start, end uint64) (*pathdb.HistoryStats, error) {
+ pdb, ok := db.backend.(*pathdb.Database)
+ if !ok {
+ return nil, errors.New("not supported")
+ }
+ return pdb.AccountHistory(address, start, end)
+}
+
+// StorageHistory inspects the storage history within the specified range.
+//
+// Start: State ID of the first history object for the query. 0 implies the first
+// available object is selected as the starting point.
+//
+// End: State ID of the last history for the query. 0 implies the last available
+// object is selected as the starting point. Note end is included for query.
+//
+// Note, slot refers to the hash of the raw slot key.
+//
+// This function is only supported by path mode database.
+func (db *Database) StorageHistory(address common.Address, slot common.Hash, start uint64, end uint64) (*pathdb.HistoryStats, error) {
+ pdb, ok := db.backend.(*pathdb.Database)
+ if !ok {
+ return nil, errors.New("not supported")
+ }
+ return pdb.StorageHistory(address, slot, start, end)
+}
+
+// HistoryRange returns the block numbers associated with earliest and latest
+// state history in the local store.
+//
+// This function is only supported by path mode database.
+func (db *Database) HistoryRange() (uint64, uint64, error) {
+ pdb, ok := db.backend.(*pathdb.Database)
+ if !ok {
+ return 0, 0, errors.New("not supported")
+ }
+ return pdb.HistoryRange()
+}
diff --git a/trie/triedb/pathdb/database.go b/triedb/pathdb/database.go
similarity index 73%
rename from trie/triedb/pathdb/database.go
rename to triedb/pathdb/database.go
index dc64414e9b..450c3a8f4f 100644
--- a/trie/triedb/pathdb/database.go
+++ b/triedb/pathdb/database.go
@@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
@@ -34,9 +35,6 @@ import (
)
const (
- // maxDiffLayers is the maximum diff layers allowed in the layer tree.
- maxDiffLayers = 128
-
// defaultCleanSize is the default memory allowance of clean cache.
defaultCleanSize = 16 * 1024 * 1024
@@ -54,14 +52,20 @@ const (
DefaultBufferSize = 64 * 1024 * 1024
)
+var (
+ // maxDiffLayers is the maximum diff layers allowed in the layer tree.
+ maxDiffLayers = 128
+)
+
// layer is the interface implemented by all state layers which includes some
// public methods and some additional methods for internal usage.
type layer interface {
- // Node retrieves the trie node with the node info. An error will be returned
- // if the read operation exits abnormally. For example, if the layer is already
- // stale, or the associated state is regarded as corrupted. Notably, no error
- // will be returned if the requested node is not found in database.
- Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, error)
+ // node retrieves the trie node with the node info. An error will be returned
+ // if the read operation exits abnormally. Specifically, if the layer is
+ // already stale.
+ //
+ // Note, no error will be returned if the requested node is not found in database.
+ node(owner common.Hash, path []byte, depth int) ([]byte, common.Hash, *nodeLoc, error)
// rootHash returns the root hash for which this layer was made.
rootHash() common.Hash
@@ -128,20 +132,21 @@ type Database struct {
// readOnly is the flag whether the mutation is allowed to be applied.
// It will be set automatically when the database is journaled during
// the shutdown to reject all following unexpected mutations.
- readOnly bool // Flag if database is opened in read only mode
- waitSync bool // Flag if database is deactivated due to initial state sync
- bufferSize int // Memory allowance (in bytes) for caching dirty nodes
- config *Config // Configuration for database
- diskdb ethdb.Database // Persistent storage for matured trie nodes
- tree *layerTree // The group for all known layers
- freezer *rawdb.ResettableFreezer // Freezer for storing trie histories, nil possible in tests
- lock sync.RWMutex // Lock to prevent mutations from happening at the same time
+ readOnly bool // Flag if database is opened in read only mode
+ waitSync bool // Flag if database is deactivated due to initial state sync
+ isVerkle bool // Flag if database is used for verkle tree
+ bufferSize int // Memory allowance (in bytes) for caching dirty nodes
+ config *Config // Configuration for database
+ diskdb ethdb.Database // Persistent storage for matured trie nodes
+ tree *layerTree // The group for all known layers
+ freezer ethdb.ResettableAncientStore // Freezer for storing trie histories, nil possible in tests
+ lock sync.RWMutex // Lock to prevent mutations from happening at the same time
}
// New attempts to load an already existing layer from a persistent key-value
// store (with a number of memory layers from a journal). If the journal is not
// matched with the base persistent layer, all the recorded diff layers are discarded.
-func New(diskdb ethdb.Database, config *Config) *Database {
+func New(diskdb ethdb.Database, config *Config, isVerkle bool) *Database {
if config == nil {
config = Defaults
}
@@ -149,6 +154,7 @@ func New(diskdb ethdb.Database, config *Config) *Database {
db := &Database{
readOnly: config.ReadOnly,
+ isVerkle: isVerkle,
bufferSize: config.DirtyCacheSize,
config: config,
diskdb: diskdb,
@@ -157,28 +163,10 @@ func New(diskdb ethdb.Database, config *Config) *Database {
// and in-memory layer journal.
db.tree = newLayerTree(db.loadLayers())
- // Open the freezer for state history if the passed database contains an
- // ancient store. Otherwise, all the relevant functionalities are disabled.
- //
- // Because the freezer can only be opened once at the same time, this
- // mechanism also ensures that at most one **non-readOnly** database
- // is opened at the same time to prevent accidental mutation.
- if ancient, err := diskdb.AncientDatadir(); err == nil && ancient != "" && !db.readOnly {
- freezer, err := rawdb.NewStateFreezer(ancient, false)
- if err != nil {
- log.Crit("Failed to open state history freezer", "err", err)
- }
- db.freezer = freezer
-
- // Truncate the extra state histories above in freezer in case
- // it's not aligned with the disk layer.
- pruned, err := truncateFromHead(db.diskdb, freezer, db.tree.bottom().stateID())
- if err != nil {
- log.Crit("Failed to truncate extra state histories", "err", err)
- }
- if pruned != 0 {
- log.Warn("Truncated extra state histories", "number", pruned)
- }
+ // Repair the state history, which might not be aligned with the state
+ // in the key-value store due to an unclean shutdown.
+ if err := db.repairHistory(); err != nil {
+ log.Crit("Failed to repair pathdb", "err", err)
}
// Disable database in case node is still in the initial state sync stage.
if rawdb.ReadSnapSyncStatusFlag(diskdb) == rawdb.StateSyncRunning && !db.readOnly {
@@ -186,17 +174,56 @@ func New(diskdb ethdb.Database, config *Config) *Database {
log.Crit("Failed to disable database", "err", err) // impossible to happen
}
}
- log.Warn("Path-based state scheme is an experimental feature")
return db
}
-// Reader retrieves a layer belonging to the given state root.
-func (db *Database) Reader(root common.Hash) (layer, error) {
- l := db.tree.get(root)
- if l == nil {
- return nil, fmt.Errorf("state %#x is not available", root)
+// repairHistory truncates leftover state history objects, which may occur due
+// to an unclean shutdown or other unexpected reasons.
+func (db *Database) repairHistory() error {
+ // Open the freezer for state history. This mechanism ensures that
+ // only one database instance can be opened at a time to prevent
+ // accidental mutation.
+ ancient, err := db.diskdb.AncientDatadir()
+ if err != nil {
+ // TODO error out if ancient store is disabled. A tons of unit tests
+ // disable the ancient store thus the error here will immediately fail
+ // all of them. Fix the tests first.
+ return nil
+ }
+ freezer, err := rawdb.NewStateFreezer(ancient, db.readOnly)
+ if err != nil {
+ log.Crit("Failed to open state history freezer", "err", err)
+ }
+ db.freezer = freezer
+
+ // Reset the entire state histories if the trie database is not initialized
+ // yet. This action is necessary because these state histories are not
+ // expected to exist without an initialized trie database.
+ id := db.tree.bottom().stateID()
+ if id == 0 {
+ frozen, err := db.freezer.Ancients()
+ if err != nil {
+ log.Crit("Failed to retrieve head of state history", "err", err)
+ }
+ if frozen != 0 {
+ err := db.freezer.Reset()
+ if err != nil {
+ log.Crit("Failed to reset state histories", "err", err)
+ }
+ log.Info("Truncated extraneous state history")
+ }
+ return nil
}
- return l, nil
+ // Truncate the extra state histories above in freezer in case it's not
+ // aligned with the disk layer. It might happen after a unclean shutdown.
+ pruned, err := truncateFromHead(db.diskdb, db.freezer, id)
+ if err != nil {
+ log.Crit("Failed to truncate extra state histories", "err", err)
+ }
+ if pruned != 0 {
+ log.Warn("Truncated extra state histories", "number", pruned)
+ }
+ return nil
}
// Update adds a new layer into the tree, if that can be linked to an existing
@@ -280,7 +307,10 @@ func (db *Database) Enable(root common.Hash) error {
}
// Ensure the provided state root matches the stored one.
root = types.TrieRootHash(root)
- _, stored := rawdb.ReadAccountTrieNode(db.diskdb, nil)
+ stored := types.EmptyRootHash
+ if blob := rawdb.ReadAccountTrieNode(db.diskdb, nil); len(blob) > 0 {
+ stored = crypto.Keccak256Hash(blob)
+ }
if stored != root {
return fmt.Errorf("state root mismatch: stored %x, synced %x", stored, root)
}
@@ -315,7 +345,7 @@ func (db *Database) Enable(root common.Hash) error {
// Recover rollbacks the database to a specified historical point.
// The state is supported as the rollback destination only if it's
// canonical state and the corresponding trie histories are existent.
-func (db *Database) Recover(root common.Hash, loader triestate.TrieLoader) error {
+func (db *Database) Recover(root common.Hash) error {
db.lock.Lock()
defer db.lock.Unlock()
@@ -341,7 +371,7 @@ func (db *Database) Recover(root common.Hash, loader triestate.TrieLoader) error
if err != nil {
return err
}
- dl, err = dl.revert(h, loader)
+ dl, err = dl.revert(h)
if err != nil {
return err
}
@@ -374,17 +404,20 @@ func (db *Database) Recoverable(root common.Hash) bool {
if *id >= dl.stateID() {
return false
}
+ // This is a temporary workaround for the unavailability of the freezer in
+ // dev mode. As a consequence, the Pathdb loses the ability for deep reorg
+ // in certain cases.
+ // TODO(rjl493456442): Implement the in-memory ancient store.
+ if db.freezer == nil {
+ return false
+ }
// Ensure the requested state is a canonical state and all state
// histories in range [id+1, disklayer.ID] are present and complete.
- parent := root
return checkHistories(db.freezer, *id+1, dl.stateID()-*id, func(m *meta) error {
- if m.parent != parent {
+ if m.parent != root {
return errors.New("unexpected state history")
}
- if len(m.incomplete) > 0 {
- return errors.New("incomplete state history")
- }
- parent = m.root
+ root = m.root
return nil
}) == nil
}
@@ -431,6 +464,9 @@ func (db *Database) Initialized(genesisRoot common.Hash) bool {
inited = true
}
})
+ if !inited {
+ inited = rawdb.ReadSnapSyncStatusFlag(db.diskdb) != rawdb.StateSyncUnknown
+ }
return inited
}
@@ -447,11 +483,6 @@ func (db *Database) SetBufferSize(size int) error {
return db.tree.bottom().setBufferSize(db.bufferSize)
}
-// Scheme returns the node scheme used in the database.
-func (db *Database) Scheme() string {
- return rawdb.PathScheme
-}
-
// modifyAllowed returns the indicator if mutation is allowed. This function
// assumes the db.lock is already held.
func (db *Database) modifyAllowed() error {
@@ -463,3 +494,33 @@ func (db *Database) modifyAllowed() error {
}
return nil
}
+
+// AccountHistory inspects the account history within the specified range.
+//
+// Start: State ID of the first history object for the query. 0 implies the first
+// available object is selected as the starting point.
+//
+// End: State ID of the last history for the query. 0 implies the last available
+// object is selected as the ending point. Note end is included in the query.
+func (db *Database) AccountHistory(address common.Address, start, end uint64) (*HistoryStats, error) {
+ return accountHistory(db.freezer, address, start, end)
+}
+
+// StorageHistory inspects the storage history within the specified range.
+//
+// Start: State ID of the first history object for the query. 0 implies the first
+// available object is selected as the starting point.
+//
+// End: State ID of the last history for the query. 0 implies the last available
+// object is selected as the ending point. Note end is included in the query.
+//
+// Note, slot refers to the hash of the raw slot key.
+func (db *Database) StorageHistory(address common.Address, slot common.Hash, start uint64, end uint64) (*HistoryStats, error) {
+ return storageHistory(db.freezer, address, slot, start, end)
+}
+
+// HistoryRange returns the block numbers associated with earliest and latest
+// state history in the local store.
+func (db *Database) HistoryRange() (uint64, uint64, error) {
+ return historyRange(db.freezer)
+}
diff --git a/trie/triedb/pathdb/database_test.go b/triedb/pathdb/database_test.go
similarity index 80%
rename from trie/triedb/pathdb/database_test.go
rename to triedb/pathdb/database_test.go
index f2e68d3473..cc2408be3a 100644
--- a/trie/triedb/pathdb/database_test.go
+++ b/triedb/pathdb/database_test.go
@@ -20,7 +20,6 @@ import (
"bytes"
"errors"
"fmt"
- "math/big"
"math/rand"
"testing"
@@ -28,33 +27,40 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/internal/testrand"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/trie/testutil"
+ "github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/trie/triestate"
+ "github.com/holiman/uint256"
)
-func updateTrie(addrHash common.Hash, root common.Hash, dirties, cleans map[common.Hash][]byte) (common.Hash, *trienode.NodeSet) {
- h, err := newTestHasher(addrHash, root, cleans)
+func updateTrie(db *Database, stateRoot common.Hash, addrHash common.Hash, root common.Hash, dirties map[common.Hash][]byte) (common.Hash, *trienode.NodeSet) {
+ var id *trie.ID
+ if addrHash == (common.Hash{}) {
+ id = trie.StateTrieID(stateRoot)
+ } else {
+ id = trie.StorageTrieID(stateRoot, addrHash, root)
+ }
+ tr, err := trie.New(id, db)
if err != nil {
- panic(fmt.Errorf("failed to create hasher, err: %w", err))
+ panic(fmt.Errorf("failed to load trie, err: %w", err))
}
for key, val := range dirties {
if len(val) == 0 {
- h.Delete(key.Bytes())
+ tr.Delete(key.Bytes())
} else {
- h.Update(key.Bytes(), val)
+ tr.Update(key.Bytes(), val)
}
}
- root, nodes, _ := h.Commit(false)
- return root, nodes
+ return tr.Commit(false)
}
func generateAccount(storageRoot common.Hash) types.StateAccount {
return types.StateAccount{
Nonce: uint64(rand.Intn(100)),
- Balance: big.NewInt(rand.Int63()),
- CodeHash: testutil.RandBytes(32),
+ Balance: uint256.NewInt(rand.Uint64()),
+ CodeHash: testrand.Bytes(32),
Root: storageRoot,
}
}
@@ -67,6 +73,7 @@ const (
)
type genctx struct {
+ stateRoot common.Hash
accounts map[common.Hash][]byte
storages map[common.Hash]map[common.Hash][]byte
accountOrigin map[common.Address][]byte
@@ -74,8 +81,9 @@ type genctx struct {
nodes *trienode.MergedNodeSet
}
-func newCtx() *genctx {
+func newCtx(stateRoot common.Hash) *genctx {
return &genctx{
+ stateRoot: stateRoot,
accounts: make(map[common.Hash][]byte),
storages: make(map[common.Hash]map[common.Hash][]byte),
accountOrigin: make(map[common.Address][]byte),
@@ -101,9 +109,9 @@ func newTester(t *testing.T, historyLimit uint64) *tester {
disk, _ = rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false, false, false)
db = New(disk, &Config{
StateHistory: historyLimit,
- CleanCacheSize: 256 * 1024,
- DirtyCacheSize: 256 * 1024,
- })
+ CleanCacheSize: 16 * 1024,
+ DirtyCacheSize: 16 * 1024,
+ }, false)
obj = &tester{
db: db,
preimages: make(map[common.Hash]common.Address),
@@ -113,7 +121,7 @@ func newTester(t *testing.T, historyLimit uint64) *tester {
snapStorages: make(map[common.Hash]map[common.Hash]map[common.Hash][]byte),
}
)
- for i := 0; i < 2*maxDiffLayers; i++ {
+ for i := 0; i < 12; i++ {
var parent = types.EmptyRootHash
if len(obj.roots) != 0 {
parent = obj.roots[len(obj.roots)-1]
@@ -146,13 +154,13 @@ func (t *tester) generateStorage(ctx *genctx, addr common.Address) common.Hash {
origin = make(map[common.Hash][]byte)
)
for i := 0; i < 10; i++ {
- v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(testutil.RandBytes(32)))
- hash := testutil.RandomHash()
+ v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(testrand.Bytes(32)))
+ hash := testrand.Hash()
storage[hash] = v
origin[hash] = nil
}
- root, set := updateTrie(addrHash, types.EmptyRootHash, storage, nil)
+ root, set := updateTrie(t.db, ctx.stateRoot, addrHash, types.EmptyRootHash, storage)
ctx.storages[addrHash] = storage
ctx.storageOrigin[addr] = origin
@@ -175,13 +183,13 @@ func (t *tester) mutateStorage(ctx *genctx, addr common.Address, root common.Has
}
}
for i := 0; i < 3; i++ {
- v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(testutil.RandBytes(32)))
- hash := testutil.RandomHash()
+ v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(testrand.Bytes(32)))
+ hash := testrand.Hash()
storage[hash] = v
origin[hash] = nil
}
- root, set := updateTrie(crypto.Keccak256Hash(addr.Bytes()), root, storage, t.storages[addrHash])
+ root, set := updateTrie(t.db, ctx.stateRoot, crypto.Keccak256Hash(addr.Bytes()), root, storage)
ctx.storages[addrHash] = storage
ctx.storageOrigin[addr] = origin
@@ -199,7 +207,7 @@ func (t *tester) clearStorage(ctx *genctx, addr common.Address, root common.Hash
origin[hash] = val
storage[hash] = nil
}
- root, set := updateTrie(addrHash, root, storage, t.storages[addrHash])
+ root, set := updateTrie(t.db, ctx.stateRoot, addrHash, root, storage)
if root != types.EmptyRootHash {
panic("failed to clear storage trie")
}
@@ -211,14 +219,14 @@ func (t *tester) clearStorage(ctx *genctx, addr common.Address, root common.Hash
func (t *tester) generate(parent common.Hash) (common.Hash, *trienode.MergedNodeSet, *triestate.Set) {
var (
- ctx = newCtx()
+ ctx = newCtx(parent)
dirties = make(map[common.Hash]struct{})
)
for i := 0; i < 20; i++ {
switch rand.Intn(opLen) {
case createAccountOp:
// account creation
- addr := testutil.RandomAddress()
+ addr := testrand.Address()
addrHash := crypto.Keccak256Hash(addr.Bytes())
if _, ok := t.accounts[addrHash]; ok {
continue
@@ -272,7 +280,7 @@ func (t *tester) generate(parent common.Hash) (common.Hash, *trienode.MergedNode
ctx.accountOrigin[addr] = account
}
}
- root, set := updateTrie(common.Hash{}, parent, ctx.accounts, t.accounts)
+ root, set := updateTrie(t.db, parent, common.Hash{}, parent, ctx.accounts)
ctx.nodes.Merge(set)
// Save state snapshot before commit
@@ -298,11 +306,14 @@ func (t *tester) generate(parent common.Hash) (common.Hash, *trienode.MergedNode
t.storages[addrHash][sHash] = slot
}
}
+ if len(t.storages[addrHash]) == 0 {
+ delete(t.storages, addrHash)
+ }
}
- return root, ctx.nodes, triestate.New(ctx.accountOrigin, ctx.storageOrigin, nil)
+ return root, ctx.nodes, triestate.New(ctx.accountOrigin, ctx.storageOrigin)
}
-// lastRoot returns the latest root hash, or empty if nothing is cached.
+// lastHash returns the latest root hash, or empty if nothing is cached.
func (t *tester) lastHash() common.Hash {
if len(t.roots) == 0 {
return common.Hash{}
@@ -311,23 +322,31 @@ func (t *tester) lastHash() common.Hash {
}
func (t *tester) verifyState(root common.Hash) error {
- reader, err := t.db.Reader(root)
+ tr, err := trie.New(trie.StateTrieID(root), t.db)
if err != nil {
return err
}
- _, err = reader.Node(common.Hash{}, nil, root)
- if err != nil {
- return errors.New("root node is not available")
- }
for addrHash, account := range t.snapAccounts[root] {
- blob, err := reader.Node(common.Hash{}, addrHash.Bytes(), crypto.Keccak256Hash(account))
+ blob, err := tr.Get(addrHash.Bytes())
if err != nil || !bytes.Equal(blob, account) {
return fmt.Errorf("account is mismatched: %w", err)
}
}
for addrHash, slots := range t.snapStorages[root] {
+ blob := t.snapAccounts[root][addrHash]
+ if len(blob) == 0 {
+ return fmt.Errorf("account %x is missing", addrHash)
+ }
+ account := new(types.StateAccount)
+ if err := rlp.DecodeBytes(blob, account); err != nil {
+ return err
+ }
+ storageIt, err := trie.New(trie.StorageTrieID(root, addrHash, account.Root), t.db)
+ if err != nil {
+ return err
+ }
for hash, slot := range slots {
- blob, err := reader.Node(addrHash, hash.Bytes(), crypto.Keccak256Hash(slot))
+ blob, err := storageIt.Get(hash.Bytes())
if err != nil || !bytes.Equal(blob, slot) {
return fmt.Errorf("slot is mismatched: %w", err)
}
@@ -379,6 +398,12 @@ func (t *tester) bottomIndex() int {
}
func TestDatabaseRollback(t *testing.T) {
+ // Redefine the diff layer depth allowance for faster testing.
+ maxDiffLayers = 4
+ defer func() {
+ maxDiffLayers = 128
+ }()
+
// Verify state histories
tester := newTester(t, 0)
defer tester.release()
@@ -388,16 +413,18 @@ func TestDatabaseRollback(t *testing.T) {
}
// Revert database from top to bottom
for i := tester.bottomIndex(); i >= 0; i-- {
- root := tester.roots[i]
parent := types.EmptyRootHash
if i > 0 {
parent = tester.roots[i-1]
}
- loader := newHashLoader(tester.snapAccounts[root], tester.snapStorages[root])
- if err := tester.db.Recover(parent, loader); err != nil {
+ if err := tester.db.Recover(parent); err != nil {
t.Fatalf("Failed to revert db, err: %v", err)
}
- tester.verifyState(parent)
+ if i > 0 {
+ if err := tester.verifyState(parent); err != nil {
+ t.Fatalf("Failed to verify state, err: %v", err)
+ }
+ }
}
if tester.db.tree.len() != 1 {
t.Fatal("Only disk layer is expected")
@@ -405,6 +432,12 @@ func TestDatabaseRollback(t *testing.T) {
}
func TestDatabaseRecoverable(t *testing.T) {
+ // Redefine the diff layer depth allowance for faster testing.
+ maxDiffLayers = 4
+ defer func() {
+ maxDiffLayers = 128
+ }()
+
var (
tester = newTester(t, 0)
index = tester.bottomIndex()
@@ -444,18 +477,24 @@ func TestDatabaseRecoverable(t *testing.T) {
}
func TestDisable(t *testing.T) {
+ // Redefine the diff layer depth allowance for faster testing.
+ maxDiffLayers = 4
+ defer func() {
+ maxDiffLayers = 128
+ }()
+
tester := newTester(t, 0)
defer tester.release()
- _, stored := rawdb.ReadAccountTrieNode(tester.db.diskdb, nil)
+ stored := crypto.Keccak256Hash(rawdb.ReadAccountTrieNode(tester.db.diskdb, nil))
if err := tester.db.Disable(); err != nil {
- t.Fatal("Failed to deactivate database")
+ t.Fatalf("Failed to deactivate database: %v", err)
}
if err := tester.db.Enable(types.EmptyRootHash); err == nil {
- t.Fatalf("Invalid activation should be rejected")
+ t.Fatal("Invalid activation should be rejected")
}
if err := tester.db.Enable(stored); err != nil {
- t.Fatal("Failed to activate database")
+ t.Fatalf("Failed to activate database: %v", err)
}
// Ensure journal is deleted from disk
@@ -480,6 +519,12 @@ func TestDisable(t *testing.T) {
}
func TestCommit(t *testing.T) {
+ // Redefine the diff layer depth allowance for faster testing.
+ maxDiffLayers = 4
+ defer func() {
+ maxDiffLayers = 128
+ }()
+
tester := newTester(t, 0)
defer tester.release()
@@ -504,6 +549,12 @@ func TestCommit(t *testing.T) {
}
func TestJournal(t *testing.T) {
+ // Redefine the diff layer depth allowance for faster testing.
+ maxDiffLayers = 4
+ defer func() {
+ maxDiffLayers = 128
+ }()
+
tester := newTester(t, 0)
defer tester.release()
@@ -511,7 +562,7 @@ func TestJournal(t *testing.T) {
t.Errorf("Failed to journal, err: %v", err)
}
tester.db.Close()
- tester.db = New(tester.db.diskdb, nil)
+ tester.db = New(tester.db.diskdb, nil, false)
// Verify states including disk layer and all diff on top.
for i := 0; i < len(tester.roots); i++ {
@@ -528,6 +579,12 @@ func TestJournal(t *testing.T) {
}
func TestCorruptedJournal(t *testing.T) {
+ // Redefine the diff layer depth allowance for faster testing.
+ maxDiffLayers = 4
+ defer func() {
+ maxDiffLayers = 128
+ }()
+
tester := newTester(t, 0)
defer tester.release()
@@ -535,15 +592,15 @@ func TestCorruptedJournal(t *testing.T) {
t.Errorf("Failed to journal, err: %v", err)
}
tester.db.Close()
- _, root := rawdb.ReadAccountTrieNode(tester.db.diskdb, nil)
+ root := crypto.Keccak256Hash(rawdb.ReadAccountTrieNode(tester.db.diskdb, nil))
// Mutate the journal in disk, it should be regarded as invalid
blob := rawdb.ReadTrieJournal(tester.db.diskdb)
- blob[0] = 1
+ blob[0] = 0xa
rawdb.WriteTrieJournal(tester.db.diskdb, blob)
// Verify states, all not-yet-written states should be discarded
- tester.db = New(tester.db.diskdb, nil)
+ tester.db = New(tester.db.diskdb, nil, false)
for i := 0; i < len(tester.roots); i++ {
if tester.roots[i] == root {
if err := tester.verifyState(root); err != nil {
@@ -570,11 +627,17 @@ func TestCorruptedJournal(t *testing.T) {
// truncating the tail histories. This ensures that the ID of the persistent state
// always falls within the range of [oldest-history-id, latest-history-id].
func TestTailTruncateHistory(t *testing.T) {
+ // Redefine the diff layer depth allowance for faster testing.
+ maxDiffLayers = 4
+ defer func() {
+ maxDiffLayers = 128
+ }()
+
tester := newTester(t, 10)
defer tester.release()
tester.db.Close()
- tester.db = New(tester.db.diskdb, &Config{StateHistory: 10})
+ tester.db = New(tester.db.diskdb, &Config{StateHistory: 10}, false)
head, err := tester.db.freezer.Ancients()
if err != nil {
diff --git a/trie/triedb/pathdb/difflayer.go b/triedb/pathdb/difflayer.go
similarity index 82%
rename from trie/triedb/pathdb/difflayer.go
rename to triedb/pathdb/difflayer.go
index 10567715d2..6b87883482 100644
--- a/trie/triedb/pathdb/difflayer.go
+++ b/triedb/pathdb/difflayer.go
@@ -95,10 +95,9 @@ func (dl *diffLayer) parentLayer() layer {
return dl.parent
}
-// node retrieves the node with provided node information. It's the internal
-// version of Node function with additional accessed layer tracked. No error
-// will be returned if node is not found.
-func (dl *diffLayer) node(owner common.Hash, path []byte, hash common.Hash, depth int) ([]byte, error) {
+// node implements the layer interface, retrieving the trie node blob with the
+// provided node information. No error will be returned if the node is not found.
+func (dl *diffLayer) node(owner common.Hash, path []byte, depth int) ([]byte, common.Hash, *nodeLoc, error) {
// Hold the lock, ensure the parent won't be changed during the
// state accessing.
dl.lock.RLock()
@@ -109,31 +108,14 @@ func (dl *diffLayer) node(owner common.Hash, path []byte, hash common.Hash, dept
if ok {
n, ok := subset[string(path)]
if ok {
- // If the trie node is not hash matched, or marked as removed,
- // bubble up an error here. It shouldn't happen at all.
- if n.Hash != hash {
- dirtyFalseMeter.Mark(1)
- log.Error("Unexpected trie node in diff layer", "owner", owner, "path", path, "expect", hash, "got", n.Hash)
- return nil, newUnexpectedNodeError("diff", hash, n.Hash, owner, path, n.Blob)
- }
dirtyHitMeter.Mark(1)
dirtyNodeHitDepthHist.Update(int64(depth))
dirtyReadMeter.Mark(int64(len(n.Blob)))
- return n.Blob, nil
+ return n.Blob, n.Hash, &nodeLoc{loc: locDiffLayer, depth: depth}, nil
}
}
// Trie node unknown to this layer, resolve from parent
- if diff, ok := dl.parent.(*diffLayer); ok {
- return diff.node(owner, path, hash, depth+1)
- }
- // Failed to resolve through diff layers, fallback to disk layer
- return dl.parent.Node(owner, path, hash)
-}
-
-// Node implements the layer interface, retrieving the trie node blob with the
-// provided node information. No error will be returned if the node is not found.
-func (dl *diffLayer) Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, error) {
- return dl.node(owner, path, hash, 0)
+ return dl.parent.node(owner, path, depth+1)
}
// update implements the layer interface, creating a new layer on top of the
diff --git a/trie/triedb/pathdb/difflayer_test.go b/triedb/pathdb/difflayer_test.go
similarity index 85%
rename from trie/triedb/pathdb/difflayer_test.go
rename to triedb/pathdb/difflayer_test.go
index a5e1c39450..9b9e6c90ae 100644
--- a/trie/triedb/pathdb/difflayer_test.go
+++ b/triedb/pathdb/difflayer_test.go
@@ -22,13 +22,14 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/trie/testutil"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/internal/testrand"
"github.com/ethereum/go-ethereum/trie/trienode"
)
func emptyLayer() *diskLayer {
return &diskLayer{
- db: New(rawdb.NewMemoryDatabase(), nil),
+ db: New(rawdb.NewMemoryDatabase(), nil, false),
buffer: newNodeBuffer(DefaultBufferSize, nil, 0),
}
}
@@ -58,7 +59,6 @@ func benchmarkSearch(b *testing.B, depth int, total int) {
b.Helper()
var (
npath []byte
- nhash common.Hash
nblob []byte
)
// First, we set up 128 diff layers, with 3K items each
@@ -67,14 +67,14 @@ func benchmarkSearch(b *testing.B, depth int, total int) {
nodes[common.Hash{}] = make(map[string]*trienode.Node)
for i := 0; i < 3000; i++ {
var (
- path = testutil.RandBytes(32)
- node = testutil.RandomNode()
+ path = testrand.Bytes(32)
+ blob = testrand.Bytes(100)
+ node = trienode.New(crypto.Keccak256Hash(blob), blob)
)
- nodes[common.Hash{}][string(path)] = trienode.New(node.Hash, node.Blob)
+ nodes[common.Hash{}][string(path)] = node
if npath == nil && depth == index {
npath = common.CopyBytes(path)
- nblob = common.CopyBytes(node.Blob)
- nhash = node.Hash
+ nblob = common.CopyBytes(blob)
}
}
return newDiffLayer(parent, common.Hash{}, 0, 0, nodes, nil)
@@ -91,7 +91,7 @@ func benchmarkSearch(b *testing.B, depth int, total int) {
err error
)
for i := 0; i < b.N; i++ {
- have, err = layer.Node(common.Hash{}, npath, nhash)
+ have, _, _, err = layer.node(common.Hash{}, npath, 0)
if err != nil {
b.Fatal(err)
}
@@ -113,10 +113,11 @@ func BenchmarkPersist(b *testing.B) {
nodes[common.Hash{}] = make(map[string]*trienode.Node)
for i := 0; i < 3000; i++ {
var (
- path = testutil.RandBytes(32)
- node = testutil.RandomNode()
+ path = testrand.Bytes(32)
+ blob = testrand.Bytes(100)
+ node = trienode.New(crypto.Keccak256Hash(blob), blob)
)
- nodes[common.Hash{}][string(path)] = trienode.New(node.Hash, node.Blob)
+ nodes[common.Hash{}][string(path)] = node
}
return newDiffLayer(parent, common.Hash{}, 0, 0, nodes, nil)
}
@@ -150,10 +151,11 @@ func BenchmarkJournal(b *testing.B) {
nodes[common.Hash{}] = make(map[string]*trienode.Node)
for i := 0; i < 3000; i++ {
var (
- path = testutil.RandBytes(32)
- node = testutil.RandomNode()
+ path = testrand.Bytes(32)
+ blob = testrand.Bytes(100)
+ node = trienode.New(crypto.Keccak256Hash(blob), blob)
)
- nodes[common.Hash{}][string(path)] = trienode.New(node.Hash, node.Blob)
+ nodes[common.Hash{}][string(path)] = node
}
// TODO(rjl493456442) a non-nil state set is expected.
return newDiffLayer(parent, common.Hash{}, 0, 0, nodes, nil)
diff --git a/trie/triedb/pathdb/disklayer.go b/triedb/pathdb/disklayer.go
similarity index 83%
rename from trie/triedb/pathdb/disklayer.go
rename to triedb/pathdb/disklayer.go
index ef697cbce8..e538a79280 100644
--- a/trie/triedb/pathdb/disklayer.go
+++ b/triedb/pathdb/disklayer.go
@@ -17,7 +17,6 @@
package pathdb
import (
- "errors"
"fmt"
"sync"
@@ -28,7 +27,6 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/trie/triestate"
- "golang.org/x/crypto/sha3"
)
// diskLayer is a low level persistent layer built on top of a key-value store.
@@ -59,7 +57,7 @@ func newDiskLayer(root common.Hash, id uint64, db *Database, cleans *fastcache.C
}
}
-// root implements the layer interface, returning root hash of corresponding state.
+// rootHash implements the layer interface, returning root hash of corresponding state.
func (dl *diskLayer) rootHash() common.Hash {
return dl.root
}
@@ -69,7 +67,7 @@ func (dl *diskLayer) stateID() uint64 {
return dl.id
}
-// parent implements the layer interface, returning nil as there's no layer
+// parentLayer implements the layer interface, returning nil as there's no layer
// below the disk.
func (dl *diskLayer) parentLayer() layer {
return nil
@@ -95,68 +93,54 @@ func (dl *diskLayer) markStale() {
dl.stale = true
}
-// Node implements the layer interface, retrieving the trie node with the
+// node implements the layer interface, retrieving the trie node with the
// provided node info. No error will be returned if the node is not found.
-func (dl *diskLayer) Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, error) {
+func (dl *diskLayer) node(owner common.Hash, path []byte, depth int) ([]byte, common.Hash, *nodeLoc, error) {
dl.lock.RLock()
defer dl.lock.RUnlock()
if dl.stale {
- return nil, errSnapshotStale
+ return nil, common.Hash{}, nil, errSnapshotStale
}
// Try to retrieve the trie node from the not-yet-written
// node buffer first. Note the buffer is lock free since
// it's impossible to mutate the buffer before tagging the
// layer as stale.
- n, err := dl.buffer.node(owner, path, hash)
- if err != nil {
- return nil, err
- }
- if n != nil {
+ n, found := dl.buffer.node(owner, path)
+ if found {
dirtyHitMeter.Mark(1)
dirtyReadMeter.Mark(int64(len(n.Blob)))
- return n.Blob, nil
+ dirtyNodeHitDepthHist.Update(int64(depth))
+ return n.Blob, n.Hash, &nodeLoc{loc: locDirtyCache, depth: depth}, nil
}
dirtyMissMeter.Mark(1)
// Try to retrieve the trie node from the clean memory cache
+ h := newHasher()
+ defer h.release()
+
key := cacheKey(owner, path)
if dl.cleans != nil {
if blob := dl.cleans.Get(nil, key); len(blob) > 0 {
- h := newHasher()
- defer h.release()
-
- got := h.hash(blob)
- if got == hash {
- cleanHitMeter.Mark(1)
- cleanReadMeter.Mark(int64(len(blob)))
- return blob, nil
- }
- cleanFalseMeter.Mark(1)
- log.Error("Unexpected trie node in clean cache", "owner", owner, "path", path, "expect", hash, "got", got)
+ cleanHitMeter.Mark(1)
+ cleanReadMeter.Mark(int64(len(blob)))
+ return blob, h.hash(blob), &nodeLoc{loc: locCleanCache, depth: depth}, nil
}
cleanMissMeter.Mark(1)
}
// Try to retrieve the trie node from the disk.
- var (
- nBlob []byte
- nHash common.Hash
- )
+ var blob []byte
if owner == (common.Hash{}) {
- nBlob, nHash = rawdb.ReadAccountTrieNode(dl.db.diskdb, path)
+ blob = rawdb.ReadAccountTrieNode(dl.db.diskdb, path)
} else {
- nBlob, nHash = rawdb.ReadStorageTrieNode(dl.db.diskdb, owner, path)
- }
- if nHash != hash {
- diskFalseMeter.Mark(1)
- log.Error("Unexpected trie node in disk", "owner", owner, "path", path, "expect", hash, "got", nHash)
- return nil, newUnexpectedNodeError("disk", hash, nHash, owner, path, nBlob)
+ blob = rawdb.ReadStorageTrieNode(dl.db.diskdb, owner, path)
}
- if dl.cleans != nil && len(nBlob) > 0 {
- dl.cleans.Set(key, nBlob)
- cleanWriteMeter.Mark(int64(len(nBlob)))
+ if dl.cleans != nil && len(blob) > 0 {
+ dl.cleans.Set(key, blob)
+ cleanWriteMeter.Mark(int64(len(blob)))
}
- return nBlob, nil
+
+ return blob, h.hash(blob), &nodeLoc{loc: locDiskLayer, depth: depth}, nil
}
// update implements the layer interface, returning a new diff layer on top
@@ -235,23 +219,17 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) {
}
// revert applies the given state history and return a reverted disk layer.
-func (dl *diskLayer) revert(h *history, loader triestate.TrieLoader) (*diskLayer, error) {
+func (dl *diskLayer) revert(h *history) (*diskLayer, error) {
if h.meta.root != dl.rootHash() {
return nil, errUnexpectedHistory
}
- // Reject if the provided state history is incomplete. It's due to
- // a large construct SELF-DESTRUCT which can't be handled because
- // of memory limitation.
- if len(h.meta.incomplete) > 0 {
- return nil, errors.New("incomplete state history")
- }
if dl.id == 0 {
return nil, fmt.Errorf("%w: zero state id", errStateUnrecoverable)
}
// Apply the reverse state changes upon the current state. This must
// be done before holding the lock in order to access state in "this"
// layer.
- nodes, err := triestate.Apply(h.meta.parent, h.meta.root, h.accounts, h.storages, loader)
+ nodes, err := apply(dl.db, h.meta.parent, h.meta.root, h.accounts, h.storages)
if err != nil {
return nil, err
}
@@ -322,7 +300,7 @@ func (dl *diskLayer) resetCache() {
type hasher struct{ sha crypto.KeccakState }
var hasherPool = sync.Pool{
- New: func() interface{} { return &hasher{sha: sha3.NewLegacyKeccak256().(crypto.KeccakState)} },
+ New: func() interface{} { return &hasher{sha: crypto.NewKeccakState()} },
}
func newHasher() *hasher {
diff --git a/trie/triedb/pathdb/errors.go b/triedb/pathdb/errors.go
similarity index 70%
rename from trie/triedb/pathdb/errors.go
rename to triedb/pathdb/errors.go
index 78ee4459fe..498bc9ec81 100644
--- a/trie/triedb/pathdb/errors.go
+++ b/triedb/pathdb/errors.go
@@ -16,13 +16,7 @@
package pathdb
-import (
- "errors"
- "fmt"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
-)
+import "errors"
var (
// errDatabaseReadOnly is returned if the database is opened in read only mode
@@ -34,7 +28,7 @@ var (
errDatabaseWaitSync = errors.New("waiting for sync")
// errSnapshotStale is returned from data accessors if the underlying layer
- // layer had been invalidated due to the chain progressing forward far enough
+ // had been invalidated due to the chain progressing forward far enough
// to not maintain the layer's original state.
errSnapshotStale = errors.New("layer stale")
@@ -45,16 +39,4 @@ var (
// errStateUnrecoverable is returned if state is required to be reverted to
// a destination without associated state history available.
errStateUnrecoverable = errors.New("state is unrecoverable")
-
- // errUnexpectedNode is returned if the requested node with specified path is
- // not hash matched with expectation.
- errUnexpectedNode = errors.New("unexpected node")
)
-
-func newUnexpectedNodeError(loc string, expHash common.Hash, gotHash common.Hash, owner common.Hash, path []byte, blob []byte) error {
- blobHex := "nil"
- if len(blob) > 0 {
- blobHex = hexutil.Encode(blob)
- }
- return fmt.Errorf("%w, loc: %s, node: (%x %v), %x!=%x, blob: %s", errUnexpectedNode, loc, owner, path, expHash, gotHash, blobHex)
-}
diff --git a/triedb/pathdb/execute.go b/triedb/pathdb/execute.go
new file mode 100644
index 0000000000..9074e4debf
--- /dev/null
+++ b/triedb/pathdb/execute.go
@@ -0,0 +1,186 @@
+// Copyright 2024 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 pathdb
+
+import (
+ "errors"
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/rlp"
+ "github.com/ethereum/go-ethereum/trie"
+ "github.com/ethereum/go-ethereum/trie/trienode"
+ "github.com/ethereum/go-ethereum/triedb/database"
+)
+
+// context wraps all fields for executing state diffs.
+type context struct {
+ prevRoot common.Hash
+ postRoot common.Hash
+ accounts map[common.Address][]byte
+ storages map[common.Address]map[common.Hash][]byte
+ nodes *trienode.MergedNodeSet
+
+ // TODO (rjl493456442) abstract out the state hasher
+ // for supporting verkle tree.
+ accountTrie *trie.Trie
+}
+
+// apply processes the given state diffs, updates the corresponding post-state
+// and returns the trie nodes that have been modified.
+func apply(db database.Database, prevRoot common.Hash, postRoot common.Hash, accounts map[common.Address][]byte, storages map[common.Address]map[common.Hash][]byte) (map[common.Hash]map[string]*trienode.Node, error) {
+ tr, err := trie.New(trie.TrieID(postRoot), db)
+ if err != nil {
+ return nil, err
+ }
+ ctx := &context{
+ prevRoot: prevRoot,
+ postRoot: postRoot,
+ accounts: accounts,
+ storages: storages,
+ accountTrie: tr,
+ nodes: trienode.NewMergedNodeSet(),
+ }
+ for addr, account := range accounts {
+ var err error
+ if len(account) == 0 {
+ err = deleteAccount(ctx, db, addr)
+ } else {
+ err = updateAccount(ctx, db, addr)
+ }
+ if err != nil {
+ return nil, fmt.Errorf("failed to revert state, err: %w", err)
+ }
+ }
+ root, result := tr.Commit(false)
+ if root != prevRoot {
+ return nil, fmt.Errorf("failed to revert state, want %#x, got %#x", prevRoot, root)
+ }
+ if err := ctx.nodes.Merge(result); err != nil {
+ return nil, err
+ }
+ return ctx.nodes.Flatten(), nil
+}
+
+// updateAccount the account was present in prev-state, and may or may not
+// existent in post-state. Apply the reverse diff and verify if the storage
+// root matches the one in prev-state account.
+func updateAccount(ctx *context, db database.Database, addr common.Address) error {
+ // The account was present in prev-state, decode it from the
+ // 'slim-rlp' format bytes.
+ h := newHasher()
+ defer h.release()
+
+ addrHash := h.hash(addr.Bytes())
+ prev, err := types.FullAccount(ctx.accounts[addr])
+ if err != nil {
+ return err
+ }
+ // The account may or may not existent in post-state, try to
+ // load it and decode if it's found.
+ blob, err := ctx.accountTrie.Get(addrHash.Bytes())
+ if err != nil {
+ return err
+ }
+ post := types.NewEmptyStateAccount()
+ if len(blob) != 0 {
+ if err := rlp.DecodeBytes(blob, &post); err != nil {
+ return err
+ }
+ }
+ // Apply all storage changes into the post-state storage trie.
+ st, err := trie.New(trie.StorageTrieID(ctx.postRoot, addrHash, post.Root), db)
+ if err != nil {
+ return err
+ }
+ for key, val := range ctx.storages[addr] {
+ var err error
+ if len(val) == 0 {
+ err = st.Delete(key.Bytes())
+ } else {
+ err = st.Update(key.Bytes(), val)
+ }
+ if err != nil {
+ return err
+ }
+ }
+ root, result := st.Commit(false)
+ if root != prev.Root {
+ return errors.New("failed to reset storage trie")
+ }
+ // The returned set can be nil if storage trie is not changed
+ // at all.
+ if result != nil {
+ if err := ctx.nodes.Merge(result); err != nil {
+ return err
+ }
+ }
+ // Write the prev-state account into the main trie
+ full, err := rlp.EncodeToBytes(prev)
+ if err != nil {
+ return err
+ }
+ return ctx.accountTrie.Update(addrHash.Bytes(), full)
+}
+
+// deleteAccount the account was not present in prev-state, and is expected
+// to be existent in post-state. Apply the reverse diff and verify if the
+// account and storage is wiped out correctly.
+func deleteAccount(ctx *context, db database.Database, addr common.Address) error {
+ // The account must be existent in post-state, load the account.
+ h := newHasher()
+ defer h.release()
+
+ addrHash := h.hash(addr.Bytes())
+ blob, err := ctx.accountTrie.Get(addrHash.Bytes())
+ if err != nil {
+ return err
+ }
+ if len(blob) == 0 {
+ return fmt.Errorf("account is non-existent %#x", addrHash)
+ }
+ var post types.StateAccount
+ if err := rlp.DecodeBytes(blob, &post); err != nil {
+ return err
+ }
+ st, err := trie.New(trie.StorageTrieID(ctx.postRoot, addrHash, post.Root), db)
+ if err != nil {
+ return err
+ }
+ for key, val := range ctx.storages[addr] {
+ if len(val) != 0 {
+ return errors.New("expect storage deletion")
+ }
+ if err := st.Delete(key.Bytes()); err != nil {
+ return err
+ }
+ }
+ root, result := st.Commit(false)
+ if root != types.EmptyRootHash {
+ return errors.New("failed to clear storage trie")
+ }
+ // The returned set can be nil if storage trie is not changed
+ // at all.
+ if result != nil {
+ if err := ctx.nodes.Merge(result); err != nil {
+ return err
+ }
+ }
+ // Delete the post-state account from the main trie.
+ return ctx.accountTrie.Delete(addrHash.Bytes())
+}
diff --git a/trie/triedb/pathdb/history.go b/triedb/pathdb/history.go
similarity index 87%
rename from trie/triedb/pathdb/history.go
rename to triedb/pathdb/history.go
index 6e3f3faaed..d77f7aa04d 100644
--- a/trie/triedb/pathdb/history.go
+++ b/triedb/pathdb/history.go
@@ -21,6 +21,7 @@ import (
"encoding/binary"
"errors"
"fmt"
+ "slices"
"time"
"github.com/ethereum/go-ethereum/common"
@@ -28,7 +29,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/trie/triestate"
- "golang.org/x/exp/slices"
+ "golang.org/x/exp/maps"
)
// State history records the state changes involved in executing a block. The
@@ -66,7 +67,7 @@ import (
const (
accountIndexSize = common.AddressLength + 13 // The length of encoded account index
slotIndexSize = common.HashLength + 5 // The length of encoded slot index
- historyMetaSize = 9 + 2*common.HashLength // The length of fixed size part of meta object
+ historyMetaSize = 9 + 2*common.HashLength // The length of encoded history meta
stateHistoryVersion = uint8(0) // initial version of state history structure.
)
@@ -192,47 +193,36 @@ func (i *slotIndex) decode(blob []byte) {
// meta describes the meta data of state history object.
type meta struct {
- version uint8 // version tag of history object
- parent common.Hash // prev-state root before the state transition
- root common.Hash // post-state root after the state transition
- block uint64 // associated block number
- incomplete []common.Address // list of address whose storage set is incomplete
+ version uint8 // version tag of history object
+ parent common.Hash // prev-state root before the state transition
+ root common.Hash // post-state root after the state transition
+ block uint64 // associated block number
}
// encode packs the meta object into byte stream.
func (m *meta) encode() []byte {
- buf := make([]byte, historyMetaSize+len(m.incomplete)*common.AddressLength)
+ buf := make([]byte, historyMetaSize)
buf[0] = m.version
copy(buf[1:1+common.HashLength], m.parent.Bytes())
copy(buf[1+common.HashLength:1+2*common.HashLength], m.root.Bytes())
binary.BigEndian.PutUint64(buf[1+2*common.HashLength:historyMetaSize], m.block)
- for i, h := range m.incomplete {
- copy(buf[i*common.AddressLength+historyMetaSize:], h.Bytes())
- }
return buf[:]
}
// decode unpacks the meta object from byte stream.
func (m *meta) decode(blob []byte) error {
if len(blob) < 1 {
- return fmt.Errorf("no version tag")
+ return errors.New("no version tag")
}
switch blob[0] {
case stateHistoryVersion:
- if len(blob) < historyMetaSize {
+ if len(blob) != historyMetaSize {
return fmt.Errorf("invalid state history meta, len: %d", len(blob))
}
- if (len(blob)-historyMetaSize)%common.AddressLength != 0 {
- return fmt.Errorf("corrupted state history meta, len: %d", len(blob))
- }
m.version = blob[0]
m.parent = common.BytesToHash(blob[1 : 1+common.HashLength])
m.root = common.BytesToHash(blob[1+common.HashLength : 1+2*common.HashLength])
m.block = binary.BigEndian.Uint64(blob[1+2*common.HashLength : historyMetaSize])
- for pos := historyMetaSize; pos < len(blob); {
- m.incomplete = append(m.incomplete, common.BytesToAddress(blob[pos:pos+common.AddressLength]))
- pos += common.AddressLength
- }
return nil
default:
return fmt.Errorf("unknown version %d", blob[0])
@@ -255,35 +245,22 @@ type history struct {
// newHistory constructs the state history object with provided state change set.
func newHistory(root common.Hash, parent common.Hash, block uint64, states *triestate.Set) *history {
var (
- accountList []common.Address
+ accountList = maps.Keys(states.Accounts)
storageList = make(map[common.Address][]common.Hash)
- incomplete []common.Address
)
- for addr := range states.Accounts {
- accountList = append(accountList, addr)
- }
slices.SortFunc(accountList, common.Address.Cmp)
for addr, slots := range states.Storages {
- slist := make([]common.Hash, 0, len(slots))
- for slotHash := range slots {
- slist = append(slist, slotHash)
- }
+ slist := maps.Keys(slots)
slices.SortFunc(slist, common.Hash.Cmp)
storageList[addr] = slist
}
- for addr := range states.Incomplete {
- incomplete = append(incomplete, addr)
- }
- slices.SortFunc(incomplete, common.Address.Cmp)
-
return &history{
meta: &meta{
- version: stateHistoryVersion,
- parent: parent,
- root: root,
- block: block,
- incomplete: incomplete,
+ version: stateHistoryVersion,
+ parent: parent,
+ root: root,
+ block: block,
},
accounts: states.Accounts,
accountList: accountList,
@@ -402,10 +379,11 @@ func (r *decoder) readAccount(pos int) (accountIndex, []byte, error) {
func (r *decoder) readStorage(accIndex accountIndex) ([]common.Hash, map[common.Hash][]byte, error) {
var (
last common.Hash
- list []common.Hash
- storage = make(map[common.Hash][]byte)
+ count = int(accIndex.storageSlots)
+ list = make([]common.Hash, 0, count)
+ storage = make(map[common.Hash][]byte, count)
)
- for j := 0; j < int(accIndex.storageSlots); j++ {
+ for j := 0; j < count; j++ {
var (
index slotIndex
start = (accIndex.storageOffset + uint32(j)) * uint32(slotIndexSize)
@@ -448,9 +426,10 @@ func (r *decoder) readStorage(accIndex accountIndex) ([]common.Hash, map[common.
// decode deserializes the account and storage data from the provided byte stream.
func (h *history) decode(accountData, storageData, accountIndexes, storageIndexes []byte) error {
var (
- accounts = make(map[common.Address][]byte)
+ count = len(accountIndexes) / accountIndexSize
+ accounts = make(map[common.Address][]byte, count)
storages = make(map[common.Address]map[common.Hash][]byte)
- accountList []common.Address
+ accountList = make([]common.Address, 0, count)
storageList = make(map[common.Address][]common.Hash)
r = &decoder{
@@ -463,7 +442,7 @@ func (h *history) decode(accountData, storageData, accountIndexes, storageIndexe
if err := r.verify(); err != nil {
return err
}
- for i := 0; i < len(accountIndexes)/accountIndexSize; i++ {
+ for i := 0; i < count; i++ {
// Resolve account first
accIndex, accData, err := r.readAccount(i)
if err != nil {
@@ -490,8 +469,8 @@ func (h *history) decode(accountData, storageData, accountIndexes, storageIndexe
}
// readHistory reads and decodes the state history object by the given id.
-func readHistory(freezer *rawdb.ResettableFreezer, id uint64) (*history, error) {
- blob := rawdb.ReadStateHistoryMeta(freezer, id)
+func readHistory(reader ethdb.AncientReader, id uint64) (*history, error) {
+ blob := rawdb.ReadStateHistoryMeta(reader, id)
if len(blob) == 0 {
return nil, fmt.Errorf("state history not found %d", id)
}
@@ -501,10 +480,10 @@ func readHistory(freezer *rawdb.ResettableFreezer, id uint64) (*history, error)
}
var (
dec = history{meta: &m}
- accountData = rawdb.ReadStateAccountHistory(freezer, id)
- storageData = rawdb.ReadStateStorageHistory(freezer, id)
- accountIndexes = rawdb.ReadStateAccountIndex(freezer, id)
- storageIndexes = rawdb.ReadStateStorageIndex(freezer, id)
+ accountData = rawdb.ReadStateAccountHistory(reader, id)
+ storageData = rawdb.ReadStateStorageHistory(reader, id)
+ accountIndexes = rawdb.ReadStateAccountIndex(reader, id)
+ storageIndexes = rawdb.ReadStateStorageIndex(reader, id)
)
if err := dec.decode(accountData, storageData, accountIndexes, storageIndexes); err != nil {
return nil, err
@@ -513,7 +492,7 @@ func readHistory(freezer *rawdb.ResettableFreezer, id uint64) (*history, error)
}
// writeHistory persists the state history with the provided state set.
-func writeHistory(freezer *rawdb.ResettableFreezer, dl *diffLayer) error {
+func writeHistory(writer ethdb.AncientWriter, dl *diffLayer) error {
// Short circuit if state set is not available.
if dl.states == nil {
return errors.New("state change set is not available")
@@ -527,7 +506,7 @@ func writeHistory(freezer *rawdb.ResettableFreezer, dl *diffLayer) error {
indexSize := common.StorageSize(len(accountIndex) + len(storageIndex))
// Write history data into five freezer table respectively.
- rawdb.WriteStateHistory(freezer, dl.stateID(), history.meta.encode(), accountIndex, storageIndex, accountData, storageData)
+ rawdb.WriteStateHistory(writer, dl.stateID(), history.meta.encode(), accountIndex, storageIndex, accountData, storageData)
historyDataBytesMeter.Mark(int64(dataSize))
historyIndexBytesMeter.Mark(int64(indexSize))
@@ -539,13 +518,13 @@ func writeHistory(freezer *rawdb.ResettableFreezer, dl *diffLayer) error {
// checkHistories retrieves a batch of meta objects with the specified range
// and performs the callback on each item.
-func checkHistories(freezer *rawdb.ResettableFreezer, start, count uint64, check func(*meta) error) error {
+func checkHistories(reader ethdb.AncientReader, start, count uint64, check func(*meta) error) error {
for count > 0 {
number := count
if number > 10000 {
number = 10000 // split the big read into small chunks
}
- blobs, err := rawdb.ReadStateHistoryMetaList(freezer, start, number)
+ blobs, err := rawdb.ReadStateHistoryMetaList(reader, start, number)
if err != nil {
return err
}
@@ -566,12 +545,12 @@ func checkHistories(freezer *rawdb.ResettableFreezer, start, count uint64, check
// truncateFromHead removes the extra state histories from the head with the given
// parameters. It returns the number of items removed from the head.
-func truncateFromHead(db ethdb.Batcher, freezer *rawdb.ResettableFreezer, nhead uint64) (int, error) {
- ohead, err := freezer.Ancients()
+func truncateFromHead(db ethdb.Batcher, store ethdb.AncientStore, nhead uint64) (int, error) {
+ ohead, err := store.Ancients()
if err != nil {
return 0, err
}
- otail, err := freezer.Tail()
+ otail, err := store.Tail()
if err != nil {
return 0, err
}
@@ -584,7 +563,7 @@ func truncateFromHead(db ethdb.Batcher, freezer *rawdb.ResettableFreezer, nhead
return 0, nil
}
// Load the meta objects in range [nhead+1, ohead]
- blobs, err := rawdb.ReadStateHistoryMetaList(freezer, nhead+1, ohead-nhead)
+ blobs, err := rawdb.ReadStateHistoryMetaList(store, nhead+1, ohead-nhead)
if err != nil {
return 0, err
}
@@ -599,7 +578,7 @@ func truncateFromHead(db ethdb.Batcher, freezer *rawdb.ResettableFreezer, nhead
if err := batch.Write(); err != nil {
return 0, err
}
- ohead, err = freezer.TruncateHead(nhead)
+ ohead, err = store.TruncateHead(nhead)
if err != nil {
return 0, err
}
@@ -608,12 +587,12 @@ func truncateFromHead(db ethdb.Batcher, freezer *rawdb.ResettableFreezer, nhead
// truncateFromTail removes the extra state histories from the tail with the given
// parameters. It returns the number of items removed from the tail.
-func truncateFromTail(db ethdb.Batcher, freezer *rawdb.ResettableFreezer, ntail uint64) (int, error) {
- ohead, err := freezer.Ancients()
+func truncateFromTail(db ethdb.Batcher, store ethdb.AncientStore, ntail uint64) (int, error) {
+ ohead, err := store.Ancients()
if err != nil {
return 0, err
}
- otail, err := freezer.Tail()
+ otail, err := store.Tail()
if err != nil {
return 0, err
}
@@ -626,7 +605,7 @@ func truncateFromTail(db ethdb.Batcher, freezer *rawdb.ResettableFreezer, ntail
return 0, nil
}
// Load the meta objects in range [otail+1, ntail]
- blobs, err := rawdb.ReadStateHistoryMetaList(freezer, otail+1, ntail-otail)
+ blobs, err := rawdb.ReadStateHistoryMetaList(store, otail+1, ntail-otail)
if err != nil {
return 0, err
}
@@ -641,7 +620,7 @@ func truncateFromTail(db ethdb.Batcher, freezer *rawdb.ResettableFreezer, ntail
if err := batch.Write(); err != nil {
return 0, err
}
- otail, err = freezer.TruncateTail(ntail)
+ otail, err = store.TruncateTail(ntail)
if err != nil {
return 0, err
}
diff --git a/triedb/pathdb/history_inspect.go b/triedb/pathdb/history_inspect.go
new file mode 100644
index 0000000000..240474da37
--- /dev/null
+++ b/triedb/pathdb/history_inspect.go
@@ -0,0 +1,151 @@
+// Copyright 2024 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 first {
+ first = start
+ }
+ // Load the id of the last history object in local store.
+ head, err := freezer.Ancients()
+ if err != nil {
+ return 0, 0, err
+ }
+ last := head - 1
+ if end != 0 && end < last {
+ last = end
+ }
+ // Make sure the range is valid
+ if first >= last {
+ return 0, 0, fmt.Errorf("range is invalid, first: %d, last: %d", first, last)
+ }
+ return first, last, nil
+}
+
+func inspectHistory(freezer ethdb.AncientReader, start, end uint64, onHistory func(*history, *HistoryStats)) (*HistoryStats, error) {
+ var (
+ stats = &HistoryStats{}
+ init = time.Now()
+ logged = time.Now()
+ )
+ start, end, err := sanitizeRange(start, end, freezer)
+ if err != nil {
+ return nil, err
+ }
+ for id := start; id <= end; id += 1 {
+ // The entire history object is decoded, although it's unnecessary for
+ // account inspection. TODO(rjl493456442) optimization is worthwhile.
+ h, err := readHistory(freezer, id)
+ if err != nil {
+ return nil, err
+ }
+ if id == start {
+ stats.Start = h.meta.block
+ }
+ if id == end {
+ stats.End = h.meta.block
+ }
+ onHistory(h, stats)
+
+ if time.Since(logged) > time.Second*8 {
+ logged = time.Now()
+ eta := float64(time.Since(init)) / float64(id-start+1) * float64(end-id)
+ log.Info("Inspecting state history", "checked", id-start+1, "left", end-id, "elapsed", common.PrettyDuration(time.Since(init)), "eta", common.PrettyDuration(eta))
+ }
+ }
+ log.Info("Inspected state history", "total", end-start+1, "elapsed", common.PrettyDuration(time.Since(init)))
+ return stats, nil
+}
+
+// accountHistory inspects the account history within the range.
+func accountHistory(freezer ethdb.AncientReader, address common.Address, start, end uint64) (*HistoryStats, error) {
+ return inspectHistory(freezer, start, end, func(h *history, stats *HistoryStats) {
+ blob, exists := h.accounts[address]
+ if !exists {
+ return
+ }
+ stats.Blocks = append(stats.Blocks, h.meta.block)
+ stats.Origins = append(stats.Origins, blob)
+ })
+}
+
+// storageHistory inspects the storage history within the range.
+func storageHistory(freezer ethdb.AncientReader, address common.Address, slot common.Hash, start uint64, end uint64) (*HistoryStats, error) {
+ return inspectHistory(freezer, start, end, func(h *history, stats *HistoryStats) {
+ slots, exists := h.storages[address]
+ if !exists {
+ return
+ }
+ blob, exists := slots[slot]
+ if !exists {
+ return
+ }
+ stats.Blocks = append(stats.Blocks, h.meta.block)
+ stats.Origins = append(stats.Origins, blob)
+ })
+}
+
+// historyRange returns the block number range of local state histories.
+func historyRange(freezer ethdb.AncientReader) (uint64, uint64, error) {
+ // Load the id of the first history object in local store.
+ tail, err := freezer.Tail()
+ if err != nil {
+ return 0, 0, err
+ }
+ first := tail + 1
+
+ // Load the id of the last history object in local store.
+ head, err := freezer.Ancients()
+ if err != nil {
+ return 0, 0, err
+ }
+ last := head - 1
+
+ fh, err := readHistory(freezer, first)
+ if err != nil {
+ return 0, 0, err
+ }
+ lh, err := readHistory(freezer, last)
+ if err != nil {
+ return 0, 0, err
+ }
+ return fh.meta.block, lh.meta.block, nil
+}
diff --git a/trie/triedb/pathdb/history_test.go b/triedb/pathdb/history_test.go
similarity index 90%
rename from trie/triedb/pathdb/history_test.go
rename to triedb/pathdb/history_test.go
index 90675bd5fe..4114aa1185 100644
--- a/trie/triedb/pathdb/history_test.go
+++ b/triedb/pathdb/history_test.go
@@ -26,8 +26,8 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/internal/testrand"
"github.com/ethereum/go-ethereum/rlp"
- "github.com/ethereum/go-ethereum/trie/testutil"
"github.com/ethereum/go-ethereum/trie/triestate"
)
@@ -38,20 +38,20 @@ func randomStateSet(n int) *triestate.Set {
storages = make(map[common.Address]map[common.Hash][]byte)
)
for i := 0; i < n; i++ {
- addr := testutil.RandomAddress()
+ addr := testrand.Address()
storages[addr] = make(map[common.Hash][]byte)
for j := 0; j < 3; j++ {
- v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(testutil.RandBytes(32)))
- storages[addr][testutil.RandomHash()] = v
+ v, _ := rlp.EncodeToBytes(common.TrimLeftZeroes(testrand.Bytes(32)))
+ storages[addr][testrand.Hash()] = v
}
account := generateAccount(types.EmptyRootHash)
accounts[addr] = types.SlimAccountRLP(account)
}
- return triestate.New(accounts, storages, nil)
+ return triestate.New(accounts, storages)
}
func makeHistory() *history {
- return newHistory(testutil.RandomHash(), types.EmptyRootHash, 0, randomStateSet(3))
+ return newHistory(testrand.Hash(), types.EmptyRootHash, 0, randomStateSet(3))
}
func makeHistories(n int) []*history {
@@ -60,7 +60,7 @@ func makeHistories(n int) []*history {
result []*history
)
for i := 0; i < n; i++ {
- root := testutil.RandomHash()
+ root := testrand.Hash()
h := newHistory(root, parent, uint64(i), randomStateSet(3))
parent = root
result = append(result, h)
@@ -102,8 +102,7 @@ func TestEncodeDecodeHistory(t *testing.T) {
}
}
-func checkHistory(t *testing.T, db ethdb.KeyValueReader, freezer *rawdb.ResettableFreezer, id uint64, root common.Hash, exist bool) {
- t.Helper()
+func checkHistory(t *testing.T, db ethdb.KeyValueReader, freezer ethdb.AncientReader, id uint64, root common.Hash, exist bool) {
blob := rawdb.ReadStateHistoryMeta(freezer, id)
if exist && len(blob) == 0 {
t.Fatalf("Failed to load trie history, %d", id)
@@ -119,8 +118,7 @@ func checkHistory(t *testing.T, db ethdb.KeyValueReader, freezer *rawdb.Resettab
}
}
-func checkHistoriesInRange(t *testing.T, db ethdb.KeyValueReader, freezer *rawdb.ResettableFreezer, from, to uint64, roots []common.Hash, exist bool) {
- t.Helper()
+func checkHistoriesInRange(t *testing.T, db ethdb.KeyValueReader, freezer ethdb.AncientReader, from, to uint64, roots []common.Hash, exist bool) {
for i, j := from, 0; i <= to; i, j = i+1, j+1 {
checkHistory(t, db, freezer, i, roots[j], exist)
}
@@ -131,7 +129,7 @@ func TestTruncateHeadHistory(t *testing.T) {
roots []common.Hash
hs = makeHistories(10)
db = rawdb.NewMemoryDatabase()
- freezer, _ = openFreezer(t.TempDir(), false)
+ freezer, _ = rawdb.NewStateFreezer(t.TempDir(), false)
)
defer freezer.Close()
@@ -159,7 +157,7 @@ func TestTruncateTailHistory(t *testing.T) {
roots []common.Hash
hs = makeHistories(10)
db = rawdb.NewMemoryDatabase()
- freezer, _ = openFreezer(t.TempDir(), false)
+ freezer, _ = rawdb.NewStateFreezer(t.TempDir(), false)
)
defer freezer.Close()
@@ -202,7 +200,7 @@ func TestTruncateTailHistories(t *testing.T) {
roots []common.Hash
hs = makeHistories(10)
db = rawdb.NewMemoryDatabase()
- freezer, _ = openFreezer(t.TempDir()+fmt.Sprintf("%d", i), false)
+ freezer, _ = rawdb.NewStateFreezer(t.TempDir()+fmt.Sprintf("%d", i), false)
)
defer freezer.Close()
@@ -230,7 +228,7 @@ func TestTruncateOutOfRange(t *testing.T) {
var (
hs = makeHistories(10)
db = rawdb.NewMemoryDatabase()
- freezer, _ = openFreezer(t.TempDir(), false)
+ freezer, _ = rawdb.NewStateFreezer(t.TempDir(), false)
)
defer freezer.Close()
@@ -270,11 +268,6 @@ func TestTruncateOutOfRange(t *testing.T) {
}
}
-// openFreezer initializes the freezer instance for storing state histories.
-func openFreezer(datadir string, readOnly bool) (*rawdb.ResettableFreezer, error) {
- return rawdb.NewStateFreezer(datadir, readOnly)
-}
-
func compareSet[k comparable](a, b map[k][]byte) bool {
if len(a) != len(b) {
return false
diff --git a/trie/triedb/pathdb/journal.go b/triedb/pathdb/journal.go
similarity index 93%
rename from trie/triedb/pathdb/journal.go
rename to triedb/pathdb/journal.go
index ac770763e3..1740ec5935 100644
--- a/trie/triedb/pathdb/journal.go
+++ b/triedb/pathdb/journal.go
@@ -41,7 +41,13 @@ var (
errUnmatchedJournal = errors.New("unmatched journal")
)
-const journalVersion uint64 = 0
+// journalVersion ensures that an incompatible journal is detected and discarded.
+//
+// Changelog:
+//
+// - Version 0: initial version
+// - Version 1: storage.Incomplete field is removed
+const journalVersion uint64 = 1
// journalNode represents a trie node persisted in the journal.
type journalNode struct {
@@ -64,10 +70,9 @@ type journalAccounts struct {
// journalStorage represents a list of storage slots belong to an account.
type journalStorage struct {
- Incomplete bool
- Account common.Address
- Hashes []common.Hash
- Slots [][]byte
+ Account common.Address
+ Hashes []common.Hash
+ Slots [][]byte
}
// loadJournal tries to parse the layer journal from the disk.
@@ -115,9 +120,10 @@ func (db *Database) loadJournal(diskRoot common.Hash) (layer, error) {
// loadLayers loads a pre-existing state layer backed by a key-value store.
func (db *Database) loadLayers() layer {
// Retrieve the root node of persistent state.
- _, root := rawdb.ReadAccountTrieNode(db.diskdb, nil)
- root = types.TrieRootHash(root)
-
+ var root = types.EmptyRootHash
+ if blob := rawdb.ReadAccountTrieNode(db.diskdb, nil); len(blob) > 0 {
+ root = crypto.Keccak256Hash(blob)
+ }
// Load the layers by resolving the journal
head, err := db.loadJournal(root)
if err == nil {
@@ -209,11 +215,10 @@ func (db *Database) loadDiffLayer(parent layer, r *rlp.Stream) (layer, error) {
}
// Read state changes from journal
var (
- jaccounts journalAccounts
- jstorages []journalStorage
- accounts = make(map[common.Address][]byte)
- storages = make(map[common.Address]map[common.Hash][]byte)
- incomplete = make(map[common.Address]struct{})
+ jaccounts journalAccounts
+ jstorages []journalStorage
+ accounts = make(map[common.Address][]byte)
+ storages = make(map[common.Address]map[common.Hash][]byte)
)
if err := r.Decode(&jaccounts); err != nil {
return nil, fmt.Errorf("load diff accounts: %v", err)
@@ -233,12 +238,9 @@ func (db *Database) loadDiffLayer(parent layer, r *rlp.Stream) (layer, error) {
set[h] = nil
}
}
- if entry.Incomplete {
- incomplete[entry.Account] = struct{}{}
- }
storages[entry.Account] = set
}
- return db.loadDiffLayer(newDiffLayer(parent, root, parent.stateID()+1, block, nodes, triestate.New(accounts, storages, incomplete)), r)
+ return db.loadDiffLayer(newDiffLayer(parent, root, parent.stateID()+1, block, nodes, triestate.New(accounts, storages)), r)
}
// journal implements the layer interface, marshaling the un-flushed trie nodes
@@ -316,9 +318,6 @@ func (dl *diffLayer) journal(w io.Writer) error {
storage := make([]journalStorage, 0, len(dl.states.Storages))
for addr, slots := range dl.states.Storages {
entry := journalStorage{Account: addr}
- if _, ok := dl.states.Incomplete[addr]; ok {
- entry.Incomplete = true
- }
for slotHash, slot := range slots {
entry.Hashes = append(entry.Hashes, slotHash)
entry.Slots = append(entry.Slots, slot)
@@ -363,14 +362,13 @@ func (db *Database) Journal(root common.Hash) error {
if err := rlp.Encode(journal, journalVersion); err != nil {
return err
}
- // The stored state in disk might be empty, convert the
- // root to emptyRoot in this case.
- _, diskroot := rawdb.ReadAccountTrieNode(db.diskdb, nil)
- diskroot = types.TrieRootHash(diskroot)
-
// Secondly write out the state root in disk, ensure all layers
// on top are continuous with disk.
- if err := rlp.Encode(journal, diskroot); err != nil {
+ diskRoot := types.EmptyRootHash
+ if blob := rawdb.ReadAccountTrieNode(db.diskdb, nil); len(blob) > 0 {
+ diskRoot = crypto.Keccak256Hash(blob)
+ }
+ if err := rlp.Encode(journal, diskRoot); err != nil {
return err
}
// Finally write out the journal of each layer in reverse order.
diff --git a/trie/triedb/pathdb/layertree.go b/triedb/pathdb/layertree.go
similarity index 100%
rename from trie/triedb/pathdb/layertree.go
rename to triedb/pathdb/layertree.go
diff --git a/trie/triedb/pathdb/metrics.go b/triedb/pathdb/metrics.go
similarity index 97%
rename from trie/triedb/pathdb/metrics.go
rename to triedb/pathdb/metrics.go
index 9e2b1dcbf5..a250f703cb 100644
--- a/trie/triedb/pathdb/metrics.go
+++ b/triedb/pathdb/metrics.go
@@ -33,6 +33,7 @@ var (
cleanFalseMeter = metrics.NewRegisteredMeter("pathdb/clean/false", nil)
dirtyFalseMeter = metrics.NewRegisteredMeter("pathdb/dirty/false", nil)
diskFalseMeter = metrics.NewRegisteredMeter("pathdb/disk/false", nil)
+ diffFalseMeter = metrics.NewRegisteredMeter("pathdb/diff/false", nil)
commitTimeTimer = metrics.NewRegisteredTimer("pathdb/commit/time", nil)
commitNodesMeter = metrics.NewRegisteredMeter("pathdb/commit/nodes", nil)
diff --git a/trie/triedb/pathdb/nodebuffer.go b/triedb/pathdb/nodebuffer.go
similarity index 90%
rename from trie/triedb/pathdb/nodebuffer.go
rename to triedb/pathdb/nodebuffer.go
index 4a7d328b9a..d3492602c8 100644
--- a/trie/triedb/pathdb/nodebuffer.go
+++ b/triedb/pathdb/nodebuffer.go
@@ -17,7 +17,9 @@
package pathdb
import (
+ "bytes"
"fmt"
+ "maps"
"time"
"github.com/VictoriaMetrics/fastcache"
@@ -59,21 +61,16 @@ func newNodeBuffer(limit int, nodes map[common.Hash]map[string]*trienode.Node, l
}
// node retrieves the trie node with given node info.
-func (b *nodebuffer) node(owner common.Hash, path []byte, hash common.Hash) (*trienode.Node, error) {
+func (b *nodebuffer) node(owner common.Hash, path []byte) (*trienode.Node, bool) {
subset, ok := b.nodes[owner]
if !ok {
- return nil, nil
+ return nil, false
}
n, ok := subset[string(path)]
if !ok {
- return nil, nil
+ return nil, false
}
- if n.Hash != hash {
- dirtyFalseMeter.Mark(1)
- log.Error("Unexpected trie node in node buffer", "owner", owner, "path", path, "expect", hash, "got", n.Hash)
- return nil, newUnexpectedNodeError("dirty", hash, n.Hash, owner, path, n.Blob)
- }
- return n, nil
+ return n, true
}
// commit merges the dirty nodes into the nodebuffer. This operation won't take
@@ -94,12 +91,10 @@ func (b *nodebuffer) commit(nodes map[common.Hash]map[string]*trienode.Node) *no
// The nodes belong to original diff layer are still accessible even
// after merging, thus the ownership of nodes map should still belong
// to original layer and any mutation on it should be prevented.
- current = make(map[string]*trienode.Node)
for path, n := range subset {
- current[path] = n
delta += int64(len(n.Blob) + len(path))
}
- b.nodes[owner] = current
+ b.nodes[owner] = maps.Clone(subset)
continue
}
for path, n := range subset {
@@ -153,14 +148,14 @@ func (b *nodebuffer) revert(db ethdb.KeyValueReader, nodes map[common.Hash]map[s
//
// In case of database rollback, don't panic if this "clean"
// node occurs which is not present in buffer.
- var nhash common.Hash
+ var blob []byte
if owner == (common.Hash{}) {
- _, nhash = rawdb.ReadAccountTrieNode(db, []byte(path))
+ blob = rawdb.ReadAccountTrieNode(db, []byte(path))
} else {
- _, nhash = rawdb.ReadStorageTrieNode(db, owner, []byte(path))
+ blob = rawdb.ReadStorageTrieNode(db, owner, []byte(path))
}
// Ignore the clean node in the case described above.
- if nhash == n.Hash {
+ if bytes.Equal(blob, n.Blob) {
continue
}
panic(fmt.Sprintf("non-existent node (%x %v) blob: %v", owner, path, crypto.Keccak256Hash(n.Blob).Hex()))
@@ -204,6 +199,19 @@ func (b *nodebuffer) setSize(size int, db ethdb.KeyValueStore, clean *fastcache.
return b.flush(db, clean, id, false)
}
+// allocBatch returns a database batch with pre-allocated buffer.
+func (b *nodebuffer) allocBatch(db ethdb.KeyValueStore) ethdb.Batch {
+ var metasize int
+ for owner, nodes := range b.nodes {
+ if owner == (common.Hash{}) {
+ metasize += len(nodes) * len(rawdb.TrieNodeAccountPrefix) // database key prefix
+ } else {
+ metasize += len(nodes) * (len(rawdb.TrieNodeStoragePrefix) + common.HashLength) // database key prefix + owner
+ }
+ }
+ return db.NewBatchWithSize((metasize + int(b.size)) * 11 / 10) // extra 10% for potential pebble internal stuff
+}
+
// flush persists the in-memory dirty trie node into the disk if the configured
// memory threshold is reached. Note, all data must be written atomically.
func (b *nodebuffer) flush(db ethdb.KeyValueStore, clean *fastcache.Cache, id uint64, force bool) error {
@@ -217,7 +225,7 @@ func (b *nodebuffer) flush(db ethdb.KeyValueStore, clean *fastcache.Cache, id ui
}
var (
start = time.Now()
- batch = db.NewBatchWithSize(int(b.size))
+ batch = b.allocBatch(db)
)
nodes := writeNodes(batch, b.nodes, clean)
rawdb.WritePersistentStateID(batch, id)
diff --git a/triedb/pathdb/reader.go b/triedb/pathdb/reader.go
new file mode 100644
index 0000000000..54dc98a543
--- /dev/null
+++ b/triedb/pathdb/reader.go
@@ -0,0 +1,94 @@
+// Copyright 2024 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 pathdb
+
+import (
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/triedb/database"
+)
+
+// The types of locations where the node is found.
+const (
+ locDirtyCache = "dirty" // dirty cache
+ locCleanCache = "clean" // clean cache
+ locDiskLayer = "disk" // persistent state
+ locDiffLayer = "diff" // diff layers
+)
+
+// nodeLoc is a helpful structure that contains the location where the node
+// is found, as it's useful for debugging purposes.
+type nodeLoc struct {
+ loc string
+ depth int
+}
+
+// string returns the string representation of node location.
+func (loc *nodeLoc) string() string {
+ return fmt.Sprintf("loc: %s, depth: %d", loc.loc, loc.depth)
+}
+
+// reader implements the database.Reader interface, providing the functionalities to
+// retrieve trie nodes by wrapping the internal state layer.
+type reader struct {
+ layer layer
+ noHashCheck bool
+}
+
+// Node implements database.Reader interface, retrieving the node with specified
+// node info. Don't modify the returned byte slice since it's not deep-copied
+// and still be referenced by database.
+func (r *reader) Node(owner common.Hash, path []byte, hash common.Hash) ([]byte, error) {
+ blob, got, loc, err := r.layer.node(owner, path, 0)
+ if err != nil {
+ return nil, err
+ }
+ // Error out if the local one is inconsistent with the target.
+ if !r.noHashCheck && got != hash {
+ // Location is always available even if the node
+ // is not found.
+ switch loc.loc {
+ case locCleanCache:
+ cleanFalseMeter.Mark(1)
+ case locDirtyCache:
+ dirtyFalseMeter.Mark(1)
+ case locDiffLayer:
+ diffFalseMeter.Mark(1)
+ case locDiskLayer:
+ diskFalseMeter.Mark(1)
+ }
+ blobHex := "nil"
+ if len(blob) > 0 {
+ blobHex = hexutil.Encode(blob)
+ }
+ log.Error("Unexpected trie node", "location", loc.loc, "owner", owner, "path", path, "expect", hash, "got", got, "blob", blobHex)
+ return nil, fmt.Errorf("unexpected node: (%x %v), %x!=%x, %s, blob: %s", owner, path, hash, got, loc.string(), blobHex)
+ }
+ return blob, nil
+}
+
+// Reader retrieves a layer belonging to the given state root.
+func (db *Database) Reader(root common.Hash) (database.Reader, error) {
+ layer := db.tree.get(root)
+ if layer == nil {
+ return nil, fmt.Errorf("state %#x is not available", root)
+ }
+ return &reader{layer: layer, noHashCheck: db.isVerkle}, nil
+}
diff --git a/trie/preimages.go b/triedb/preimages.go
similarity index 99%
rename from trie/preimages.go
rename to triedb/preimages.go
index d7e5f8729d..54b3859000 100644
--- a/trie/preimages.go
+++ b/triedb/preimages.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package trie
+package triedb
import (
"sync"