-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathaccount.go
185 lines (170 loc) · 5.32 KB
/
account.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
package evm
import(
"sync"
"fmt"
"encoding/json"
"reflect")
type Account struct {
Info AccountInfo
Storage EvmStorage
Status AccountStatus
}
type AccountInfo struct {
Balance U256
Nonce uint64
CodeHash B256
Code *Bytecode
}
func NewAccountInfo(balance U256, nonce uint64, codeHash B256, code Bytecode) AccountInfo {
return AccountInfo{
Balance: balance,
Nonce: nonce,
CodeHash: codeHash,
Code: &code,
}
}
type EvmStorage map[U256]EvmStorageSlot
type EvmStorageSlot struct {
OriginalValue U256
PresentValue U256
IsCold bool
}
type AccountStatus uint8
const (
Loaded AccountStatus = 0b00000000 // Account is loaded but not interacted with
Created AccountStatus = 0b00000001 // Account is newly created, no DB fetch required
SelfDestructed AccountStatus = 0b00000010 // Account is marked for self-destruction
Touched AccountStatus = 0b00000100 // Account is touched and will be saved to DB
LoadedAsNotExisting AccountStatus = 0b0001000 // Pre-spurious state; account loaded but marked as non-existing
Cold AccountStatus = 0b0010000 // Account is marked as cold (not frequently accessed)
)
type BytecodeKind int
const (
LegacyRawKind BytecodeKind = iota
LegacyAnalyzedKind
EofKind
)
// BytecodeKind serves as discriminator for Bytecode to identify which variant of enum is being used
// 1 , 2 or 3 in this case
type Bytecode struct {
Kind BytecodeKind
LegacyRaw []byte // For LegacyRaw variant
LegacyAnalyzed *LegacyAnalyzedBytecode // For LegacyAnalyzed variant
Eof *Eof // For Eof variant
}
type LegacyAnalyzedBytecode struct {
Bytecode []byte
OriginalLen uint64
JumpTable JumpTable
}
// JumpTable equivalent in Go, using a sync.Once pointer to simulate Arc and BitVec<u8>.
type JumpTable struct {
BitVector *Bitvector // Simulating BitVec<u8> as []byte
once sync.Once // Lazy initialization if needed
}
type Bitvector struct {
bits []uint8
size int // Total number of bits represented
}
type Opcode struct {
InitCode Eof `json:"initcode"`
Input Bytes `json:"input"`
CreatedAddress Address `json:"created_address"`
}
type Eof struct {
Header EofHeader `json:"header"`
Body EofBody `json:"body"`
Raw Bytes `json:"raw"`
}
// EofHeader represents the header of the EOF.
type EofHeader struct {
TypesSize uint16 `json:"types_size"`
CodeSizes []uint16 `json:"code_sizes"`
ContainerSizes []uint16 `json:"container_sizes"`
DataSize uint16 `json:"data_size"`
SumCodeSizes int `json:"sum_code_sizes"`
SumContainerSizes int `json:"sum_container_sizes"`
}
// Marshaler interface for custom marshaling
type Marshaler interface {
MarshalType(val reflect.Value, b []byte, lastWrittenIdx uint64) (nextIdx uint64, err error)
}
// Unmarshaler interface for custom unmarshaling
type Unmarshaler interface {
UnmarshalType(target reflect.Value, b []byte, lastReadIdx uint64) (nextIdx uint64, err error)
}
// Implement Marshaler for EOFCreateInputs
func (eci EOFCreateInputs) MarshalType(val reflect.Value, b []byte, lastWrittenIdx uint64) (nextIdx uint64, err error) {
jsonData, err := json.Marshal(eci)
if err != nil {
return lastWrittenIdx, err
}
return uint64(len(jsonData)), nil
}
// Implement Unmarshaler for EOFCreateInputs
func (eci *EOFCreateInputs) UnmarshalType(target reflect.Value, b []byte, lastReadIdx uint64) (nextIdx uint64, err error) {
err = json.Unmarshal(b, eci)
if err != nil {
return lastReadIdx, err
}
return lastReadIdx + uint64(len(b)), nil
}
type EofBody struct {
TypesSection []TypesSection `json:"types_section"`
CodeSection []Bytes `json:"code_section"` // Using [][]byte for Vec<Bytes>
ContainerSection []Bytes `json:"container_section"` // Using [][]byte for Vec<Bytes>
DataSection Bytes `json:"data_section"` // Using []byte for Bytes
IsDataFilled bool `json:"is_data_filled"`
}
// TypesSection represents a section describing the types used in the EOF body.
type TypesSection struct {
Inputs uint8 `json:"inputs"` // 1 byte
Outputs uint8 `json:"outputs"` // 1 byte
MaxStackSize uint16 `json:"max_stack_size"` // 2 bytes
}
// MarshalJSON customizes the JSON marshalling for EOFCreateKind.
func (e *EOFCreateKind) MarshalJSON() ([]byte, error) {
switch e.Kind {
case TxK:
return json.Marshal(map[string]interface{}{
"type": "Tx",
"data": e.Data,
})
case OpcodeK:
return json.Marshal(map[string]interface{}{
"type": "Opcode",
"data": e.Data,
})
default:
return nil, fmt.Errorf("unknown EOFCreateKind type")
}
}
// UnmarshalJSON customizes the JSON unmarshalling for EOFCreateKind.
func (e *EOFCreateKind) UnmarshalJSON(data []byte) error {
var aux struct {
Type string `json:"type"`
Data json.RawMessage `json:"data"`
}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
switch aux.Type {
case "Tx":
var tx Tx
if err := json.Unmarshal(aux.Data, &tx); err != nil {
return err
}
e.Kind = TxK
e.Data = tx
case "Opcode":
var opcode Opcode
if err := json.Unmarshal(aux.Data, &opcode); err != nil {
return err
}
e.Kind = OpcodeK
e.Data = opcode
default:
return fmt.Errorf("unknown EOFCreateKind type: %s", aux.Type)
}
return nil
}