Skip to content

Commit bb07324

Browse files
authored
Add Parent hash to Block and provide Writer that verifies correctness (#18)
* Add Parent hash to Block and provide Writer that verifies correctness * rename * restore tests * wrap errors
1 parent 9c55e48 commit bb07324

3 files changed

Lines changed: 515 additions & 0 deletions

File tree

block.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66

77
type Block[T any] struct {
88
Hash common.Hash `json:"blockHash"`
9+
Parent common.Hash `json:"parentHash"`
910
Number uint64 `json:"blockNum"`
1011
TS uint64 `json:"blockTS"` // unix ts
1112
Data T `json:"blockData"`

writer_with_verify_hash.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package ethwal
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/0xsequence/ethkit/go-ethereum/common"
8+
)
9+
10+
type BlockHashGetter func(ctx context.Context, blockNum uint64) (common.Hash, error)
11+
12+
func BlockHashGetterFromReader[T any](options Options) BlockHashGetter {
13+
return func(ctx context.Context, blockNum uint64) (common.Hash, error) {
14+
reader, err := NewReader[T](options)
15+
if err != nil {
16+
return common.Hash{}, fmt.Errorf("failed to create reader: %w", err)
17+
}
18+
defer reader.Close()
19+
20+
err = reader.Seek(ctx, blockNum-1)
21+
if err != nil {
22+
return common.Hash{}, fmt.Errorf("failed to seek to block %d: %w", blockNum, err)
23+
}
24+
25+
block, err := reader.Read(ctx)
26+
if err != nil {
27+
return common.Hash{}, fmt.Errorf("failed to read block %d: %w", blockNum, err)
28+
}
29+
return block.Hash, nil
30+
}
31+
}
32+
33+
type writerWithVerifyHash[T any] struct {
34+
Writer[T]
35+
36+
blockHashGetter BlockHashGetter
37+
38+
prevHash common.Hash
39+
}
40+
41+
var _ Writer[any] = (*writerWithVerifyHash[any])(nil)
42+
43+
func NewWriterWithVerifyHash[T any](writer Writer[T], blockHashGetter BlockHashGetter) Writer[T] {
44+
return &writerWithVerifyHash[T]{Writer: writer, blockHashGetter: blockHashGetter}
45+
}
46+
47+
func (w *writerWithVerifyHash[T]) Write(ctx context.Context, b Block[T]) error {
48+
var err error
49+
if w.prevHash == (common.Hash{}) && b.Number > 1 {
50+
w.prevHash, err = w.blockHashGetter(ctx, b.Number-1)
51+
if err != nil {
52+
return fmt.Errorf("failed to get block hash: %w", err)
53+
}
54+
}
55+
56+
if b.Parent != w.prevHash {
57+
w.prevHash = common.Hash{}
58+
return fmt.Errorf("parent hash mismatch, expected %s, got %s",
59+
w.prevHash.String(), b.Parent.String())
60+
}
61+
62+
err = w.Writer.Write(ctx, b)
63+
if err != nil {
64+
w.prevHash = common.Hash{}
65+
return fmt.Errorf("failed to write block: %w", err)
66+
}
67+
68+
w.prevHash = b.Hash
69+
return nil
70+
}

0 commit comments

Comments
 (0)