diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9cfaa5f14d..3275d42562 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -159,12 +159,20 @@ jobs: os: [ubuntu-22.04] # List of OS: https://github.com/actions/virtual-environments runs-on: ${{ matrix.os }} needs: [unit-tests, integration-tests] + env: + RUN_CODECOV_UPLOAD: ${{ secrets.CODECOV_TOKEN != '' }} steps: + - name: Skip Codecov upload when CODECOV_TOKEN is unavailable + if: env.RUN_CODECOV_UPLOAD != 'true' + run: echo "Skipping Codecov upload because CODECOV_TOKEN is not available for this run." - name: Checkout + if: env.RUN_CODECOV_UPLOAD == 'true' uses: actions/checkout@v5 - name: Download artifacts + if: env.RUN_CODECOV_UPLOAD == 'true' uses: actions/download-artifact@v6.0.0 - name: Upload coverage to Codecov + if: env.RUN_CODECOV_UPLOAD == 'true' uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/kurtosis-e2e.yml b/.github/workflows/kurtosis-e2e.yml index b1b1eece8a..a41fe07383 100644 --- a/.github/workflows/kurtosis-e2e.yml +++ b/.github/workflows/kurtosis-e2e.yml @@ -69,14 +69,20 @@ jobs: - build-heimdall-v2 runs-on: ubuntu-latest timeout-minutes: 30 + env: + RUN_PRIVILEGED_STEPS: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} # These permissions are required to log in to GCR permissions: contents: read actions: write id-token: write steps: + - name: Skip privileged e2e steps on fork pull requests + if: env.RUN_PRIVILEGED_STEPS != 'true' + run: echo "Skipping privileged e2e workflow because fork pull requests do not receive the required OIDC token and secrets." # Set up kurtosis - name: Checkout kurtosis-pos + if: env.RUN_PRIVILEGED_STEPS == 'true' uses: actions/checkout@v5 with: repository: 0xPolygon/kurtosis-pos @@ -84,6 +90,7 @@ jobs: # This step will free disk space and thus remove any docker images previously built - name: Pre kurtosis run + if: env.RUN_PRIVILEGED_STEPS == 'true' uses: ./.github/actions/setup with: main_branch: develop @@ -91,6 +98,7 @@ jobs: docker_token: ${{ secrets.DOCKERHUB_KEY }} - name: Checkout pos-workflows + if: env.RUN_PRIVILEGED_STEPS == 'true' uses: actions/checkout@v5 with: repository: 0xPolygon/pos-workflows @@ -98,26 +106,31 @@ jobs: path: pos-workflows - name: Copy kurtosis config + if: env.RUN_PRIVILEGED_STEPS == 'true' run: cp ./pos-workflows/configs/kurtosis-e2e.yml ./kurtosis-e2e.yml # Load images - name: Download bor docker image + if: env.RUN_PRIVILEGED_STEPS == 'true' uses: actions/download-artifact@v4 with: name: bor-image - name: Download heimdall-v2 docker image + if: env.RUN_PRIVILEGED_STEPS == 'true' uses: actions/download-artifact@v4 with: name: heimdall-v2-image - name: Load bor docker image + if: env.RUN_PRIVILEGED_STEPS == 'true' run: | gunzip -c bor-image.tar.gz | docker load echo "Loaded bor docker image:" docker images bor:local --format "{{.ID}} {{.CreatedAt}}" - name: Load heimdall-v2 docker image + if: env.RUN_PRIVILEGED_STEPS == 'true' run: | gunzip -c heimdall-v2-image.tar.gz | docker load echo "Loaded heimdall-v2 docker image:" @@ -125,12 +138,15 @@ jobs: # Deploy kurtosis enclave - name: Kurtosis run + if: env.RUN_PRIVILEGED_STEPS == 'true' run: kurtosis run --args-file=kurtosis-e2e.yml --enclave=${{ env.ENCLAVE_NAME }} . - name: Inspect enclave + if: env.RUN_PRIVILEGED_STEPS == 'true' run: kurtosis enclave inspect ${{ env.ENCLAVE_NAME }} - name: Install polycli + if: env.RUN_PRIVILEGED_STEPS == 'true' run: | tmp_dir=$(mktemp -d) curl -L https://github.com/0xPolygon/polygon-cli/releases/download/${{ env.POLYCLI_VERSION }}/polycli_${{ env.POLYCLI_VERSION }}_linux_amd64.tar.gz | tar -xz -C "$tmp_dir" @@ -141,16 +157,19 @@ jobs: - name: Run smoke tests id: smoke-tests + if: env.RUN_PRIVILEGED_STEPS == 'true' working-directory: pos-workflows/tests run: bash kurtosis_smoke_test.sh - name: Install Go + if: env.RUN_PRIVILEGED_STEPS == 'true' uses: actions/setup-go@v6 with: go-version: 'stable' - name: Run RPC tests id: rpc-tests + if: env.RUN_PRIVILEGED_STEPS == 'true' working-directory: pos-workflows/tests/rpc_tests run: | export RPC_URL=$(kurtosis port print ${{ env.ENCLAVE_NAME }} l2-el-1-bor-heimdall-v2-validator rpc) @@ -160,7 +179,7 @@ jobs: # Collect diagnostics on failure - name: Collect network diagnostics and state dump if: >- - always() && ( + env.RUN_PRIVILEGED_STEPS == 'true' && always() && ( steps.smoke-tests.outcome == 'failure' || steps.rpc-tests.outcome == 'failure') uses: ./pos-workflows/.github/actions/network-diagnostics-and-state-dump @@ -169,7 +188,7 @@ jobs: # Clean up - name: Post kurtosis run - if: always() + if: env.RUN_PRIVILEGED_STEPS == 'true' && always() uses: ./.github/actions/cleanup with: main_branch: develop diff --git a/.github/workflows/kurtosis-stateless-e2e.yml b/.github/workflows/kurtosis-stateless-e2e.yml index cb517f74cf..7b0c50dd54 100644 --- a/.github/workflows/kurtosis-stateless-e2e.yml +++ b/.github/workflows/kurtosis-stateless-e2e.yml @@ -69,14 +69,20 @@ jobs: - build-heimdall-v2 runs-on: ubuntu-latest timeout-minutes: 45 + env: + RUN_PRIVILEGED_STEPS: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} # These permissions are required to log in to GCR permissions: contents: read actions: write id-token: write steps: + - name: Skip privileged e2e steps on fork pull requests + if: env.RUN_PRIVILEGED_STEPS != 'true' + run: echo "Skipping privileged e2e workflow because fork pull requests do not receive the required OIDC token and secrets." # Set up kurtosis - name: Checkout kurtosis-pos + if: env.RUN_PRIVILEGED_STEPS == 'true' uses: actions/checkout@v5 with: repository: 0xPolygon/kurtosis-pos @@ -84,6 +90,7 @@ jobs: # This step will free disk space and thus remove any docker images previously built - name: Pre kurtosis run + if: env.RUN_PRIVILEGED_STEPS == 'true' uses: ./.github/actions/setup with: main_branch: develop @@ -91,6 +98,7 @@ jobs: docker_token: ${{ secrets.DOCKERHUB_KEY }} - name: Checkout pos-workflows + if: env.RUN_PRIVILEGED_STEPS == 'true' uses: actions/checkout@v5 with: repository: 0xPolygon/pos-workflows @@ -98,26 +106,31 @@ jobs: path: pos-workflows - name: Copy kurtosis config + if: env.RUN_PRIVILEGED_STEPS == 'true' run: cp ./pos-workflows/configs/kurtosis-stateless-e2e.yml ./kurtosis-stateless-e2e.yml # Load images - name: Download bor docker image + if: env.RUN_PRIVILEGED_STEPS == 'true' uses: actions/download-artifact@v4 with: name: bor-image - name: Download heimdall-v2 docker image + if: env.RUN_PRIVILEGED_STEPS == 'true' uses: actions/download-artifact@v4 with: name: heimdall-v2-image - name: Load bor docker image + if: env.RUN_PRIVILEGED_STEPS == 'true' run: | gunzip -c bor-image.tar.gz | docker load echo "Loaded bor docker image:" docker images bor:local --format "{{.ID}} {{.CreatedAt}}" - name: Load heimdall-v2 docker image + if: env.RUN_PRIVILEGED_STEPS == 'true' run: | gunzip -c heimdall-v2-image.tar.gz | docker load echo "Loaded heimdall-v2 docker image:" @@ -125,13 +138,16 @@ jobs: # Deploy kurtosis enclave - name: Kurtosis run + if: env.RUN_PRIVILEGED_STEPS == 'true' run: kurtosis run --args-file=kurtosis-stateless-e2e.yml --enclave ${{ env.ENCLAVE_NAME }} . - name: Inspect enclave + if: env.RUN_PRIVILEGED_STEPS == 'true' run: kurtosis enclave inspect ${{ env.ENCLAVE_NAME }} # Run e2e tests - name: Install polycli + if: env.RUN_PRIVILEGED_STEPS == 'true' run: | tmp_dir=$(mktemp -d) curl -L https://github.com/0xPolygon/polygon-cli/releases/download/${{ env.POLYCLI_VERSION }}/polycli_${{ env.POLYCLI_VERSION }}_linux_amd64.tar.gz | tar -xz -C "$tmp_dir" @@ -142,19 +158,20 @@ jobs: - name: Run stateless e2e tests id: stateless-tests + if: env.RUN_PRIVILEGED_STEPS == 'true' working-directory: pos-workflows/tests/stateless_tests run: bash kurtosis_stateless_test.sh # Collect diagnostics on failure - name: Collect network diagnostics and state dump - if: always() && steps.stateless-tests.outcome == 'failure' + if: env.RUN_PRIVILEGED_STEPS == 'true' && always() && steps.stateless-tests.outcome == 'failure' uses: ./pos-workflows/.github/actions/network-diagnostics-and-state-dump with: enclave_name: ${{ env.ENCLAVE_NAME }} # Clean up - name: Post kurtosis run - if: always() + if: env.RUN_PRIVILEGED_STEPS == 'true' && always() uses: ./.github/actions/cleanup with: main_branch: develop diff --git a/Dockerfile b/Dockerfile index dc1517c7ce..32098fced0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # ─── BUILDER STAGE ─────────────────────────────────────────────────────────────── -FROM golang:1.26.1-alpine AS builder +FROM golang:1.26.2-alpine AS builder ARG BOR_DIR=/var/lib/bor/ ENV BOR_DIR=$BOR_DIR diff --git a/Dockerfile.alltools b/Dockerfile.alltools index 1ac856f090..0fe1dc4a57 100644 --- a/Dockerfile.alltools +++ b/Dockerfile.alltools @@ -1,5 +1,5 @@ # Build Geth in a stock Go builder container -FROM golang:1.26.1-alpine AS builder +FROM golang:1.26.2-alpine AS builder RUN apk add --no-cache make gcc musl-dev linux-headers git diff --git a/cmd/keeper/go.mod b/cmd/keeper/go.mod index 768125cbd1..db168eb7c1 100644 --- a/cmd/keeper/go.mod +++ b/cmd/keeper/go.mod @@ -1,6 +1,6 @@ module github.com/ethereum/go-ethereum/cmd/keeper -go 1.26.1 +go 1.26.2 require ( github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260104020744-7268a54d0358 diff --git a/core/rawdb/ancient_scheme.go b/core/rawdb/ancient_scheme.go index b4f6a175c7..5b334e4667 100644 --- a/core/rawdb/ancient_scheme.go +++ b/core/rawdb/ancient_scheme.go @@ -121,7 +121,7 @@ var freezers = []string{ // state freezer. func NewStateFreezer(ancientDir string, verkle bool, readOnly bool) (ethdb.ResettableAncientStore, error) { if ancientDir == "" { - return NewMemoryFreezer(readOnly, stateFreezerTableConfigs), nil + return NewMemoryFreezer(readOnly, 0, stateFreezerTableConfigs), nil } var name string if verkle { @@ -140,7 +140,7 @@ func NewStateFreezer(ancientDir string, verkle bool, readOnly bool) (ethdb.Reset // trienode freezer. func NewTrienodeFreezer(ancientDir string, verkle bool, readOnly bool) (ethdb.ResettableAncientStore, error) { if ancientDir == "" { - return NewMemoryFreezer(readOnly, trienodeFreezerTableConfigs), nil + return NewMemoryFreezer(readOnly, 0, trienodeFreezerTableConfigs), nil } var name string if verkle { diff --git a/core/rawdb/chain_freezer.go b/core/rawdb/chain_freezer.go index 0ff9c59635..dad20f3ed7 100644 --- a/core/rawdb/chain_freezer.go +++ b/core/rawdb/chain_freezer.go @@ -69,7 +69,7 @@ func NewChainFreezer(datadir string, namespace string, readonly bool, offset uin func newChainFreezer(datadir string, eraDir string, namespace string, readonly bool, offset uint64) (*chainFreezer, error) { if datadir == "" { return &chainFreezer{ - ancients: NewMemoryFreezer(readonly, chainFreezerTableConfigs), + ancients: NewMemoryFreezer(readonly, offset, chainFreezerTableConfigs), quit: make(chan struct{}), trigger: make(chan chan struct{}), }, nil diff --git a/core/rawdb/freezer_memory.go b/core/rawdb/freezer_memory.go index 96740d0c6e..eeaab2df77 100644 --- a/core/rawdb/freezer_memory.go +++ b/core/rawdb/freezer_memory.go @@ -29,6 +29,8 @@ import ( "github.com/ethereum/go-ethereum/rlp" ) +var errTruncateBelowOffset = errors.New("truncation below offset") + // memoryTable is used to store a list of sequential items in memory. type memoryTable struct { items uint64 // Number of stored items in the table, including the deleted ones @@ -149,7 +151,7 @@ func (b *memoryBatch) reset(freezer *MemoryFreezer) { b.size = make(map[string]int64) for name, table := range freezer.tables { - b.next[name] = table.items + b.next[name] = table.items + freezer.offset.Load() } } @@ -215,16 +217,24 @@ type MemoryFreezer struct { } // NewMemoryFreezer initializes an in-memory freezer instance. -func NewMemoryFreezer(readonly bool, tableName map[string]freezerTableConfig) *MemoryFreezer { +func NewMemoryFreezer(readonly bool, offset uint64, tableName map[string]freezerTableConfig) *MemoryFreezer { tables := make(map[string]*memoryTable) for name, cfg := range tableName { tables[name] = newMemoryTable(name, cfg) } - return &MemoryFreezer{ + freezer := &MemoryFreezer{ writeBatch: newMemoryBatch(), readonly: readonly, tables: tables, } + + freezer.offset.Store(offset) + + // Some blocks in ancientDB may have already been frozen and been pruned, so adding the offset to + // represent the absolute number of blocks already frozen. + freezer.items += offset + + return freezer } // todo: @anshalshukla || @manav2401 - Check if implementation is required @@ -240,7 +250,11 @@ func (f *MemoryFreezer) ItemAmountInAncient() (uint64, error) { f.lock.RLock() defer f.lock.RUnlock() - return f.items - f.offset.Load(), nil + offset := f.offset.Load() + if f.items < offset { + return 0, nil + } + return f.items - offset, nil } // Ancient retrieves an ancient binary blob from the in-memory freezer. @@ -252,7 +266,11 @@ func (f *MemoryFreezer) Ancient(kind string, number uint64) ([]byte, error) { if t == nil { return nil, errUnknownTable } - data, err := t.retrieve(number, 1, 0) + offset := f.offset.Load() + if number < offset { + return nil, errOutOfBounds + } + data, err := t.retrieve(number-offset, 1, 0) if err != nil { return nil, err } @@ -273,7 +291,11 @@ func (f *MemoryFreezer) AncientRange(kind string, start, count, maxBytes uint64) if t == nil { return nil, errUnknownTable } - return t.retrieve(start, count, maxBytes) + offset := f.offset.Load() + if start < offset { + return nil, errOutOfBounds + } + return t.retrieve(start-offset, count, maxBytes) } // Ancients returns the ancient item numbers in the freezer. @@ -322,18 +344,20 @@ func (f *MemoryFreezer) ModifyAncients(fn func(ethdb.AncientWriteOp) error) (wri return 0, errReadOnly } // Roll back all tables to the starting position in case of error. + old := f.items + offset := f.offset.Load() defer func(old uint64) { if err == nil { return } // The write operation has failed. Go back to the previous item position. for name, table := range f.tables { - err := table.truncateHead(old) + err := table.truncateHead(old - offset) if err != nil { log.Error("Freezer table roll-back failed", "table", name, "index", old, "err", err) } } - }(f.items) + }(old) // Modify the ancients in batch. f.writeBatch.reset(f) @@ -361,8 +385,12 @@ func (f *MemoryFreezer) TruncateHead(items uint64) (uint64, error) { if old <= items { return old, nil } + offset := f.offset.Load() + if items < offset { + return 0, errTruncateBelowOffset + } for _, table := range f.tables { - if err := table.truncateHead(items); err != nil { + if err := table.truncateHead(items - offset); err != nil { return 0, err } } @@ -384,9 +412,13 @@ func (f *MemoryFreezer) TruncateTail(tail uint64) (uint64, error) { if old >= tail { return old, nil } + offset := f.offset.Load() + if tail < offset { + return 0, errTruncateBelowOffset + } for _, table := range f.tables { if table.config.prunable { - if err := table.truncateTail(tail); err != nil { + if err := table.truncateTail(tail - offset); err != nil { return 0, err } } @@ -422,7 +454,7 @@ func (f *MemoryFreezer) Reset() error { tables[name] = newMemoryTable(name, table.config) } f.tables = tables - f.items, f.tail = 0, 0 + f.items, f.tail = f.offset.Load(), 0 return nil } diff --git a/core/rawdb/freezer_memory_test.go b/core/rawdb/freezer_memory_test.go index 4bd31d8027..8fb62ca250 100644 --- a/core/rawdb/freezer_memory_test.go +++ b/core/rawdb/freezer_memory_test.go @@ -17,6 +17,8 @@ package rawdb import ( + "bytes" + "errors" "testing" "github.com/ethereum/go-ethereum/core/rawdb/ancienttest" @@ -32,7 +34,7 @@ func TestMemoryFreezer(t *testing.T) { prunable: true, } } - return NewMemoryFreezer(false, tables) + return NewMemoryFreezer(false, 0, tables) }) ancienttest.TestResettableAncientSuite(t, func(kinds []string) ethdb.ResettableAncientStore { tables := make(map[string]freezerTableConfig) @@ -42,6 +44,131 @@ func TestMemoryFreezer(t *testing.T) { prunable: true, } } - return NewMemoryFreezer(false, tables) + return NewMemoryFreezer(false, 0, tables) }) } + +func TestMemoryFreezerOffset(t *testing.T) { + freezer := NewMemoryFreezer(false, 10, map[string]freezerTableConfig{ + "test": {noSnappy: true, prunable: true}, + }) + if got := freezer.AncientOffSet(); got != 10 { + t.Fatalf("AncientOffSet() = %d, want 10", got) + } + if got, err := freezer.Ancients(); err != nil { + t.Fatalf("Ancients() returned error: %v", err) + } else if got != 10 { + t.Fatalf("Ancients() = %d, want 10", got) + } + if got, err := freezer.ItemAmountInAncient(); err != nil { + t.Fatalf("ItemAmountInAncient() returned error: %v", err) + } else if got != 0 { + t.Fatalf("ItemAmountInAncient() = %d, want 0", got) + } + + if _, err := freezer.ModifyAncients(func(op ethdb.AncientWriteOp) error { + return op.AppendRaw("test", 0, []byte("zero")) + }); !errors.Is(err, errOutOrderInsertion) { + t.Fatalf("AppendRaw before offset error = %v, want %v", err, errOutOrderInsertion) + } + + if _, err := freezer.ModifyAncients(func(op ethdb.AncientWriteOp) error { + if err := op.AppendRaw("test", 10, []byte("ten")); err != nil { + return err + } + if err := op.AppendRaw("test", 11, []byte("eleven")); err != nil { + return err + } + return op.AppendRaw("test", 12, []byte("twelve")) + }); err != nil { + t.Fatalf("ModifyAncients() returned error: %v", err) + } + + if got, err := freezer.Ancients(); err != nil { + t.Fatalf("Ancients() returned error: %v", err) + } else if got != 13 { + t.Fatalf("Ancients() = %d, want 13", got) + } + if got, err := freezer.ItemAmountInAncient(); err != nil { + t.Fatalf("ItemAmountInAncient() returned error: %v", err) + } else if got != 3 { + t.Fatalf("ItemAmountInAncient() = %d, want 3", got) + } + + if blob, err := freezer.Ancient("test", 10); err != nil { + t.Fatalf("Ancient(10) returned error: %v", err) + } else if !bytes.Equal(blob, []byte("ten")) { + t.Fatalf("Ancient(10) = %q, want %q", blob, []byte("ten")) + } + if _, err := freezer.Ancient("test", 9); !errors.Is(err, errOutOfBounds) { + t.Fatalf("Ancient(9) error = %v, want %v", err, errOutOfBounds) + } + + if batch, err := freezer.AncientRange("test", 10, 2, 0); err != nil { + t.Fatalf("AncientRange(10, 2, 0) returned error: %v", err) + } else if len(batch) != 2 || !bytes.Equal(batch[0], []byte("ten")) || !bytes.Equal(batch[1], []byte("eleven")) { + t.Fatalf("AncientRange(10, 2, 0) = %q, want %q", batch, [][]byte{[]byte("ten"), []byte("eleven")}) + } + if _, err := freezer.AncientRange("test", 9, 1, 0); !errors.Is(err, errOutOfBounds) { + t.Fatalf("AncientRange(9, 1, 0) error = %v, want %v", err, errOutOfBounds) + } + + if _, err := freezer.TruncateHead(9); !errors.Is(err, errTruncateBelowOffset) { + t.Fatalf("TruncateHead(9) error = %v, want %v", err, errTruncateBelowOffset) + } + if _, err := freezer.TruncateTail(9); !errors.Is(err, errTruncateBelowOffset) { + t.Fatalf("TruncateTail(9) error = %v, want %v", err, errTruncateBelowOffset) + } + + if old, err := freezer.TruncateTail(11); err != nil { + t.Fatalf("TruncateTail(11) returned error: %v", err) + } else if old != 0 { + t.Fatalf("TruncateTail(11) old tail = %d, want 0", old) + } + if blob, err := freezer.Ancient("test", 11); err != nil { + t.Fatalf("Ancient(11) returned error: %v", err) + } else if !bytes.Equal(blob, []byte("eleven")) { + t.Fatalf("Ancient(11) = %q, want %q", blob, []byte("eleven")) + } + if _, err := freezer.Ancient("test", 10); !errors.Is(err, errOutOfBounds) { + t.Fatalf("Ancient(10) after tail truncation error = %v, want %v", err, errOutOfBounds) + } + + if old, err := freezer.TruncateHead(12); err != nil { + t.Fatalf("TruncateHead(12) returned error: %v", err) + } else if old != 13 { + t.Fatalf("TruncateHead(12) old head = %d, want 13", old) + } + if got, err := freezer.Ancients(); err != nil { + t.Fatalf("Ancients() after head truncation returned error: %v", err) + } else if got != 12 { + t.Fatalf("Ancients() after head truncation = %d, want 12", got) + } + if _, err := freezer.Ancient("test", 12); !errors.Is(err, errOutOfBounds) { + t.Fatalf("Ancient(12) after head truncation error = %v, want %v", err, errOutOfBounds) + } +} + +func TestMemoryFreezerResetKeepsOffset(t *testing.T) { + freezer := NewMemoryFreezer(false, 7, map[string]freezerTableConfig{ + "test": {noSnappy: true, prunable: true}, + }) + if err := freezer.Reset(); err != nil { + t.Fatalf("Reset() returned error: %v", err) + } + if got, err := freezer.Ancients(); err != nil { + t.Fatalf("Ancients() returned error: %v", err) + } else if got != 7 { + t.Fatalf("Ancients() = %d, want 7", got) + } + if got, err := freezer.ItemAmountInAncient(); err != nil { + t.Fatalf("ItemAmountInAncient() returned error: %v", err) + } else if got != 0 { + t.Fatalf("ItemAmountInAncient() = %d, want 0", got) + } + if _, err := freezer.ModifyAncients(func(op ethdb.AncientWriteOp) error { + return op.AppendRaw("test", 7, []byte("seven")) + }); err != nil { + t.Fatalf("ModifyAncients() after reset returned error: %v", err) + } +} diff --git a/go.mod b/go.mod index f618297e80..fc650b5dbe 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/ethereum/go-ethereum // Note: Change the go image version in Dockerfile if you change this. -go 1.26.1 +go 1.26.2 require ( github.com/0xPolygon/crand v1.0.3