Skip to content

Commit ed63753

Browse files
e3: move txnum to erigon-lib (#847)
1 parent 559e60f commit ed63753

File tree

3 files changed

+192
-3
lines changed

3 files changed

+192
-3
lines changed

common/address.go

-3
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ func BytesToAddress(b []byte) Address {
2828
return a
2929
}
3030

31-
// BytesToAddressNoCopy - see https://tip.golang.org/ref/spec#Conversions_from_slice_to_array_pointer
32-
func BytesToAddressNoCopy(b []byte) Address { return *(*Address)(b) }
33-
3431
// BigToAddress returns Address with byte values of b.
3532
// If b is larger than len(h), b will be cropped from the left.
3633
func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) }

common/hash.go

+6
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,9 @@ func (h *Hash) Scan(src interface{}) error {
152152
func (h Hash) Value() (driver.Value, error) {
153153
return h[:], nil
154154
}
155+
156+
type CodeRecord struct {
157+
BlockNumber uint64
158+
TxNumber uint64
159+
CodeHash Hash
160+
}

common/rawdbv3/txnum.go

+186
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
package rawdbv3
2+
3+
import (
4+
"encoding/binary"
5+
"fmt"
6+
"sort"
7+
8+
"github.com/ledgerwatch/erigon-lib/kv"
9+
)
10+
11+
type txNums struct{}
12+
13+
var TxNums txNums
14+
15+
// Min - returns maxTxNum in given block. If block not found - return last available value (`latest`/`pending` state)
16+
func (txNums) Max(tx kv.Tx, blockNum uint64) (maxTxNum uint64, err error) {
17+
var k [8]byte
18+
binary.BigEndian.PutUint64(k[:], blockNum)
19+
c, err := tx.Cursor(kv.MaxTxNum)
20+
if err != nil {
21+
return 0, err
22+
}
23+
defer c.Close()
24+
_, v, err := c.SeekExact(k[:])
25+
if err != nil {
26+
return 0, err
27+
}
28+
if len(v) == 0 {
29+
_, v, err = c.Last()
30+
if err != nil {
31+
return 0, err
32+
}
33+
if len(v) == 0 {
34+
return 0, nil
35+
}
36+
}
37+
return binary.BigEndian.Uint64(v), nil
38+
}
39+
40+
// Min = `max(blockNum-1)+1` returns minTxNum in given block. If block not found - return last available value (`latest`/`pending` state)
41+
func (txNums) Min(tx kv.Tx, blockNum uint64) (maxTxNum uint64, err error) {
42+
if blockNum == 0 {
43+
return 0, nil
44+
}
45+
var k [8]byte
46+
binary.BigEndian.PutUint64(k[:], blockNum-1)
47+
c, err := tx.Cursor(kv.MaxTxNum)
48+
if err != nil {
49+
return 0, err
50+
}
51+
defer c.Close()
52+
53+
_, v, err := c.SeekExact(k[:])
54+
if err != nil {
55+
return 0, err
56+
}
57+
if len(v) == 0 {
58+
_, v, err = c.Last()
59+
if err != nil {
60+
return 0, err
61+
}
62+
if len(v) == 0 {
63+
return 0, nil
64+
}
65+
}
66+
return binary.BigEndian.Uint64(v) + 1, nil
67+
}
68+
69+
func (txNums) Append(tx kv.RwTx, blockNum, maxTxNum uint64) (err error) {
70+
lastK, err := LastKey(tx, kv.MaxTxNum)
71+
if err != nil {
72+
return err
73+
}
74+
if len(lastK) != 0 {
75+
lastBlockNum := binary.BigEndian.Uint64(lastK)
76+
if lastBlockNum > 1 && lastBlockNum+1 != blockNum { //allow genesis
77+
return fmt.Errorf("append with gap blockNum=%d, but current heigh=%d", blockNum, lastBlockNum)
78+
}
79+
}
80+
81+
var k, v [8]byte
82+
binary.BigEndian.PutUint64(k[:], blockNum)
83+
binary.BigEndian.PutUint64(v[:], maxTxNum)
84+
if err := tx.Append(kv.MaxTxNum, k[:], v[:]); err != nil {
85+
return err
86+
}
87+
return nil
88+
}
89+
func (txNums) WriteForGenesis(tx kv.RwTx, maxTxNum uint64) (err error) {
90+
var k, v [8]byte
91+
binary.BigEndian.PutUint64(k[:], 0)
92+
binary.BigEndian.PutUint64(v[:], maxTxNum)
93+
return tx.Put(kv.MaxTxNum, k[:], v[:])
94+
}
95+
func (txNums) Truncate(tx kv.RwTx, blockNum uint64) (err error) {
96+
var seek [8]byte
97+
binary.BigEndian.PutUint64(seek[:], blockNum)
98+
c, err := tx.RwCursor(kv.MaxTxNum)
99+
if err != nil {
100+
return err
101+
}
102+
defer c.Close()
103+
for k, _, err := c.Seek(seek[:]); k != nil; k, _, err = c.Next() {
104+
if err != nil {
105+
return err
106+
}
107+
if err = c.DeleteCurrent(); err != nil {
108+
return err
109+
}
110+
111+
}
112+
return nil
113+
}
114+
func (txNums) FindBlockNum(tx kv.Tx, endTxNumMinimax uint64) (ok bool, blockNum uint64, err error) {
115+
var seek [8]byte
116+
c, err := tx.Cursor(kv.MaxTxNum)
117+
if err != nil {
118+
return false, 0, err
119+
}
120+
defer c.Close()
121+
122+
cnt, err := c.Count()
123+
if err != nil {
124+
return false, 0, err
125+
}
126+
127+
blockNum = uint64(sort.Search(int(cnt), func(i int) bool {
128+
binary.BigEndian.PutUint64(seek[:], uint64(i))
129+
var v []byte
130+
_, v, err = c.SeekExact(seek[:])
131+
return binary.BigEndian.Uint64(v) >= endTxNumMinimax
132+
}))
133+
if err != nil {
134+
return false, 0, err
135+
}
136+
if blockNum == cnt {
137+
return false, 0, nil
138+
}
139+
return true, blockNum, nil
140+
}
141+
142+
// LastKey
143+
func LastKey(tx kv.Tx, table string) ([]byte, error) {
144+
c, err := tx.Cursor(table)
145+
if err != nil {
146+
return nil, err
147+
}
148+
defer c.Close()
149+
k, _, err := c.Last()
150+
if err != nil {
151+
return nil, err
152+
}
153+
return k, nil
154+
}
155+
156+
// Last - candidate on move to kv.Tx interface
157+
func Last(tx kv.Tx, table string) ([]byte, []byte, error) {
158+
c, err := tx.Cursor(table)
159+
if err != nil {
160+
return nil, nil, err
161+
}
162+
defer c.Close()
163+
k, v, err := c.Last()
164+
if err != nil {
165+
return nil, nil, err
166+
}
167+
return k, v, nil
168+
}
169+
170+
// SecondKey - useful if table always has zero-key (for example genesis block)
171+
func SecondKey(tx kv.Tx, table string) ([]byte, error) {
172+
c, err := tx.Cursor(table)
173+
if err != nil {
174+
return nil, err
175+
}
176+
defer c.Close()
177+
_, _, err = c.First()
178+
if err != nil {
179+
return nil, err
180+
}
181+
k, _, err := c.Next()
182+
if err != nil {
183+
return nil, err
184+
}
185+
return k, nil
186+
}

0 commit comments

Comments
 (0)