Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
60a349f4
Commit
60a349f4
authored
Sep 22, 2021
by
George Hotz
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
close to compiling with stock state_object
parent
018ee56a
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
711 additions
and
122 deletions
+711
-122
database.go
minigeth/core/state/database.go
+85
-5
journal.go
minigeth/core/state/journal.go
+269
-0
snapshot.go
minigeth/core/state/snapshot/snapshot.go
+14
-0
state_object.go
minigeth/core/state/state_object.go
+294
-107
statedb.go
minigeth/core/state/statedb.go
+46
-10
metrics.go
minigeth/metrics/metrics.go
+3
-0
No files found.
minigeth/core/state/database.go
View file @
60a349f4
...
...
@@ -4,6 +4,7 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/oracle"
)
...
...
@@ -15,24 +16,103 @@ type Database struct {
StateRoot
common
.
Hash
}
var
unhashMap
=
make
(
map
[
common
.
Hash
]
common
.
Address
)
func
unhash
(
addrHash
common
.
Hash
)
common
.
Address
{
return
unhashMap
[
addrHash
]
}
// ContractCode retrieves a particular contract's code.
func
(
db
*
Database
)
ContractCode
(
addr
common
.
Address
,
codeHash
common
.
Hash
)
([]
byte
,
error
)
{
func
(
db
*
Database
)
ContractCode
(
addrHash
common
.
Hash
,
codeHash
common
.
Hash
)
([]
byte
,
error
)
{
addr
:=
unhash
(
addrHash
)
code
:=
oracle
.
GetProvedCodeBytes
(
db
.
BlockNumber
,
addr
,
codeHash
)
return
code
,
nil
}
func
(
db
*
Database
)
CopyTrie
(
trie
Trie
)
Trie
{
// TODO: this is wrong
return
trie
}
// ContractCodeSize retrieves a particular contracts code's size.
func
(
db
*
Database
)
ContractCodeSize
(
addr
common
.
Address
,
codeHash
common
.
Hash
)
(
int
,
error
)
{
func
(
db
*
Database
)
ContractCodeSize
(
addrHash
common
.
Hash
,
codeHash
common
.
Hash
)
(
int
,
error
)
{
addr
:=
unhash
(
addrHash
)
code
:=
oracle
.
GetProvedCodeBytes
(
db
.
BlockNumber
,
addr
,
codeHash
)
return
len
(
code
),
nil
}
type
Trie
struct
{
// OpenStorageTrie opens the storage trie of an account.
func
(
db
*
Database
)
OpenStorageTrie
(
addrHash
,
root
common
.
Hash
)
(
Trie
,
error
)
{
return
simpleTrie
{},
nil
}
type
LeafCallback
func
(
paths
[][]
byte
,
hexpath
[]
byte
,
leaf
[]
byte
,
parent
common
.
Hash
)
error
type
Trie
interface
{
// TryGet returns the value for key stored in the trie. The value bytes must
// not be modified by the caller. If a node was not found in the database, a
// trie.MissingNodeError is returned.
TryGet
(
key
[]
byte
)
([]
byte
,
error
)
// TryUpdate associates key with value in the trie. If value has length zero, any
// existing value is deleted from the trie. The value bytes must not be modified
// by the caller while they are stored in the trie. If a node was not found in the
// database, a trie.MissingNodeError is returned.
TryUpdate
(
key
,
value
[]
byte
)
error
// TryDelete removes any existing value for key from the trie. If a node was not
// found in the database, a trie.MissingNodeError is returned.
TryDelete
(
key
[]
byte
)
error
// Hash returns the root hash of the trie. It does not write to the database and
// can be used even if the trie doesn't have one.
Hash
()
common
.
Hash
// Commit writes all nodes to the trie's memory database, tracking the internal
// and external (for account tries) references.
Commit
(
onleaf
LeafCallback
)
(
common
.
Hash
,
error
)
}
type
simpleTrie
struct
{
BlockNumber
*
big
.
Int
StateRoot
common
.
Hash
}
func
(
trie
*
Trie
)
TryGet
(
key
[]
byte
)
([]
byte
,
error
)
{
enc
:=
oracle
.
GetProvedAccountBytes
(
trie
.
BlockNumber
,
trie
.
StateRoot
,
common
.
BytesToAddress
(
key
))
func
(
trie
simpleTrie
)
Commit
(
onleaf
LeafCallback
)
(
common
.
Hash
,
error
)
{
return
trie
.
StateRoot
,
nil
}
func
(
trie
simpleTrie
)
Hash
()
common
.
Hash
{
return
trie
.
StateRoot
}
func
(
trie
simpleTrie
)
TryUpdate
(
key
,
value
[]
byte
)
error
{
return
nil
}
func
(
trie
simpleTrie
)
TryDelete
(
key
[]
byte
)
error
{
return
nil
}
func
(
trie
simpleTrie
)
TryGet
(
key
[]
byte
)
([]
byte
,
error
)
{
address
:=
common
.
BytesToAddress
(
key
)
addrHash
:=
crypto
.
Keccak256Hash
(
address
[
:
])
unhashMap
[
addrHash
]
=
address
enc
:=
oracle
.
GetProvedAccountBytes
(
trie
.
BlockNumber
,
trie
.
StateRoot
,
address
)
return
enc
,
nil
}
// stubbed: we don't prefetch
type
triePrefetcher
struct
{
}
func
(
p
*
triePrefetcher
)
prefetch
(
root
common
.
Hash
,
keys
[][]
byte
)
{
}
func
(
p
*
triePrefetcher
)
used
(
root
common
.
Hash
,
used
[][]
byte
)
{
}
func
(
p
*
triePrefetcher
)
trie
(
root
common
.
Hash
)
Trie
{
return
nil
}
minigeth/core/state/journal.go
0 → 100644
View file @
60a349f4
// Copyright 2016 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 <http://www.gnu.org/licenses/>.
package
state
import
(
"math/big"
"github.com/ethereum/go-ethereum/common"
)
// journalEntry is a modification entry in the state change journal that can be
// reverted on demand.
type
journalEntry
interface
{
// revert undoes the changes introduced by this journal entry.
revert
(
*
StateDB
)
// dirtied returns the Ethereum address modified by this journal entry.
dirtied
()
*
common
.
Address
}
// journal contains the list of state modifications applied since the last state
// commit. These are tracked to be able to be reverted in case of an execution
// exception or revertal request.
type
journal
struct
{
entries
[]
journalEntry
// Current changes tracked by the journal
dirties
map
[
common
.
Address
]
int
// Dirty accounts and the number of changes
}
// newJournal create a new initialized journal.
func
newJournal
()
*
journal
{
return
&
journal
{
dirties
:
make
(
map
[
common
.
Address
]
int
),
}
}
// append inserts a new modification entry to the end of the change journal.
func
(
j
*
journal
)
append
(
entry
journalEntry
)
{
j
.
entries
=
append
(
j
.
entries
,
entry
)
if
addr
:=
entry
.
dirtied
();
addr
!=
nil
{
j
.
dirties
[
*
addr
]
++
}
}
// revert undoes a batch of journalled modifications along with any reverted
// dirty handling too.
func
(
j
*
journal
)
revert
(
statedb
*
StateDB
,
snapshot
int
)
{
for
i
:=
len
(
j
.
entries
)
-
1
;
i
>=
snapshot
;
i
--
{
// Undo the changes made by the operation
j
.
entries
[
i
]
.
revert
(
statedb
)
// Drop any dirty tracking induced by the change
if
addr
:=
j
.
entries
[
i
]
.
dirtied
();
addr
!=
nil
{
if
j
.
dirties
[
*
addr
]
--
;
j
.
dirties
[
*
addr
]
==
0
{
delete
(
j
.
dirties
,
*
addr
)
}
}
}
j
.
entries
=
j
.
entries
[
:
snapshot
]
}
// dirty explicitly sets an address to dirty, even if the change entries would
// otherwise suggest it as clean. This method is an ugly hack to handle the RIPEMD
// precompile consensus exception.
func
(
j
*
journal
)
dirty
(
addr
common
.
Address
)
{
j
.
dirties
[
addr
]
++
}
// length returns the current number of entries in the journal.
func
(
j
*
journal
)
length
()
int
{
return
len
(
j
.
entries
)
}
type
(
// Changes to the account trie.
createObjectChange
struct
{
account
*
common
.
Address
}
resetObjectChange
struct
{
prev
*
stateObject
prevdestruct
bool
}
suicideChange
struct
{
account
*
common
.
Address
prev
bool
// whether account had already suicided
prevbalance
*
big
.
Int
}
// Changes to individual accounts.
balanceChange
struct
{
account
*
common
.
Address
prev
*
big
.
Int
}
nonceChange
struct
{
account
*
common
.
Address
prev
uint64
}
storageChange
struct
{
account
*
common
.
Address
key
,
prevalue
common
.
Hash
}
codeChange
struct
{
account
*
common
.
Address
prevcode
,
prevhash
[]
byte
}
// Changes to other state values.
refundChange
struct
{
prev
uint64
}
addLogChange
struct
{
txhash
common
.
Hash
}
addPreimageChange
struct
{
hash
common
.
Hash
}
touchChange
struct
{
account
*
common
.
Address
}
// Changes to the access list
accessListAddAccountChange
struct
{
address
*
common
.
Address
}
accessListAddSlotChange
struct
{
address
*
common
.
Address
slot
*
common
.
Hash
}
)
func
(
ch
createObjectChange
)
revert
(
s
*
StateDB
)
{
delete
(
s
.
stateObjects
,
*
ch
.
account
)
delete
(
s
.
stateObjectsDirty
,
*
ch
.
account
)
}
func
(
ch
createObjectChange
)
dirtied
()
*
common
.
Address
{
return
ch
.
account
}
func
(
ch
resetObjectChange
)
revert
(
s
*
StateDB
)
{
s
.
setStateObject
(
ch
.
prev
)
if
!
ch
.
prevdestruct
&&
s
.
snap
!=
nil
{
delete
(
s
.
snapDestructs
,
ch
.
prev
.
addrHash
)
}
}
func
(
ch
resetObjectChange
)
dirtied
()
*
common
.
Address
{
return
nil
}
func
(
ch
suicideChange
)
revert
(
s
*
StateDB
)
{
obj
:=
s
.
getStateObject
(
*
ch
.
account
)
if
obj
!=
nil
{
obj
.
suicided
=
ch
.
prev
obj
.
setBalance
(
ch
.
prevbalance
)
}
}
func
(
ch
suicideChange
)
dirtied
()
*
common
.
Address
{
return
ch
.
account
}
var
ripemd
=
common
.
HexToAddress
(
"0000000000000000000000000000000000000003"
)
func
(
ch
touchChange
)
revert
(
s
*
StateDB
)
{
}
func
(
ch
touchChange
)
dirtied
()
*
common
.
Address
{
return
ch
.
account
}
func
(
ch
balanceChange
)
revert
(
s
*
StateDB
)
{
s
.
getStateObject
(
*
ch
.
account
)
.
setBalance
(
ch
.
prev
)
}
func
(
ch
balanceChange
)
dirtied
()
*
common
.
Address
{
return
ch
.
account
}
func
(
ch
nonceChange
)
revert
(
s
*
StateDB
)
{
s
.
getStateObject
(
*
ch
.
account
)
.
setNonce
(
ch
.
prev
)
}
func
(
ch
nonceChange
)
dirtied
()
*
common
.
Address
{
return
ch
.
account
}
func
(
ch
codeChange
)
revert
(
s
*
StateDB
)
{
s
.
getStateObject
(
*
ch
.
account
)
.
setCode
(
common
.
BytesToHash
(
ch
.
prevhash
),
ch
.
prevcode
)
}
func
(
ch
codeChange
)
dirtied
()
*
common
.
Address
{
return
ch
.
account
}
func
(
ch
storageChange
)
revert
(
s
*
StateDB
)
{
s
.
getStateObject
(
*
ch
.
account
)
.
setState
(
ch
.
key
,
ch
.
prevalue
)
}
func
(
ch
storageChange
)
dirtied
()
*
common
.
Address
{
return
ch
.
account
}
func
(
ch
refundChange
)
revert
(
s
*
StateDB
)
{
s
.
refund
=
ch
.
prev
}
func
(
ch
refundChange
)
dirtied
()
*
common
.
Address
{
return
nil
}
func
(
ch
addLogChange
)
revert
(
s
*
StateDB
)
{
logs
:=
s
.
logs
[
ch
.
txhash
]
if
len
(
logs
)
==
1
{
delete
(
s
.
logs
,
ch
.
txhash
)
}
else
{
s
.
logs
[
ch
.
txhash
]
=
logs
[
:
len
(
logs
)
-
1
]
}
s
.
logSize
--
}
func
(
ch
addLogChange
)
dirtied
()
*
common
.
Address
{
return
nil
}
func
(
ch
addPreimageChange
)
revert
(
s
*
StateDB
)
{
delete
(
s
.
preimages
,
ch
.
hash
)
}
func
(
ch
addPreimageChange
)
dirtied
()
*
common
.
Address
{
return
nil
}
func
(
ch
accessListAddAccountChange
)
revert
(
s
*
StateDB
)
{
/*
One important invariant here, is that whenever a (addr, slot) is added, if the
addr is not already present, the add causes two journal entries:
- one for the address,
- one for the (address,slot)
Therefore, when unrolling the change, we can always blindly delete the
(addr) at this point, since no storage adds can remain when come upon
a single (addr) change.
*/
s
.
accessList
.
DeleteAddress
(
*
ch
.
address
)
}
func
(
ch
accessListAddAccountChange
)
dirtied
()
*
common
.
Address
{
return
nil
}
func
(
ch
accessListAddSlotChange
)
revert
(
s
*
StateDB
)
{
s
.
accessList
.
DeleteSlot
(
*
ch
.
address
,
*
ch
.
slot
)
}
func
(
ch
accessListAddSlotChange
)
dirtied
()
*
common
.
Address
{
return
nil
}
minigeth/core/state/snapshot/snapshot.go
0 → 100644
View file @
60a349f4
package
snapshot
import
"github.com/ethereum/go-ethereum/common"
// entirely stubs, this is never created
type
Tree
interface
{
}
type
Snapshot
interface
{
// Storage directly retrieves the storage data associated with a particular hash,
// within a particular account.
Storage
(
accountHash
,
storageHash
common
.
Hash
)
([]
byte
,
error
)
}
minigeth/core/state/state_object.go
View file @
60a349f4
This diff is collapsed.
Click to expand it.
minigeth/core/state/statedb.go
View file @
60a349f4
...
...
@@ -3,8 +3,10 @@ package state
import
(
"fmt"
"math/big"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
...
...
@@ -17,18 +19,37 @@ var (
)
type
StateDB
struct
{
db
Database
trie
Trie
db
Database
prefetcher
*
triePrefetcher
originalRoot
common
.
Hash
// The pre-state root, before any changes were made
trie
Trie
hasher
crypto
.
KeccakState
blockNumber
*
big
.
Int
stateRoot
common
.
Hash
// This map holds 'live' objects, which will get modified while processing a state transition.
stateObjects
map
[
common
.
Address
]
*
stateObject
stateObjects
map
[
common
.
Address
]
*
stateObject
stateObjectsPending
map
[
common
.
Address
]
struct
{}
// State objects finalized but not yet written to the trie
stateObjectsDirty
map
[
common
.
Address
]
struct
{}
// State objects modified in the current execution
// Per-transaction access list
accessList
*
accessList
preimages
map
[
common
.
Hash
][]
byte
snaps
*
snapshot
.
Tree
snap
snapshot
.
Snapshot
snapDestructs
map
[
common
.
Hash
]
struct
{}
snapAccounts
map
[
common
.
Hash
][]
byte
snapStorage
map
[
common
.
Hash
]
map
[
common
.
Hash
][]
byte
// Journal of state modifications. This is the backbone of
// Snapshot and RevertToSnapshot.
journal
*
journal
validRevisions
[]
revision
nextRevisionId
int
logs
map
[
common
.
Hash
][]
*
types
.
Log
logSize
uint
...
...
@@ -37,17 +58,32 @@ type StateDB struct {
// The refund counter, also used by state transitioning.
refund
uint64
// Measurements gathered during execution for debugging purposes
AccountReads
time
.
Duration
AccountHashes
time
.
Duration
AccountUpdates
time
.
Duration
AccountCommits
time
.
Duration
StorageReads
time
.
Duration
StorageHashes
time
.
Duration
StorageUpdates
time
.
Duration
StorageCommits
time
.
Duration
SnapshotAccountReads
time
.
Duration
SnapshotStorageReads
time
.
Duration
SnapshotCommits
time
.
Duration
}
func
NewStateDB
(
header
types
.
Header
)
*
StateDB
{
return
&
StateDB
{
blockNumber
:
header
.
Number
,
stateObjects
:
make
(
map
[
common
.
Address
]
*
stateObject
),
stateRoot
:
header
.
Root
,
db
:
Database
{
BlockNumber
:
header
.
Number
,
StateRoot
:
header
.
Root
},
trie
:
Trie
{
BlockNumber
:
header
.
Number
,
StateRoot
:
header
.
Root
},
accessList
:
newAccessList
(),
logs
:
make
(
map
[
common
.
Hash
][]
*
types
.
Log
),
blockNumber
:
header
.
Number
,
stateObjects
:
make
(
map
[
common
.
Address
]
*
stateObject
),
stateObjectsPending
:
make
(
map
[
common
.
Address
]
struct
{}),
stateObjectsDirty
:
make
(
map
[
common
.
Address
]
struct
{}),
stateRoot
:
header
.
Root
,
db
:
Database
{
BlockNumber
:
header
.
Number
,
StateRoot
:
header
.
Root
},
trie
:
Trie
{
BlockNumber
:
header
.
Number
,
StateRoot
:
header
.
Root
},
accessList
:
newAccessList
(),
logs
:
make
(
map
[
common
.
Hash
][]
*
types
.
Log
),
}
}
...
...
minigeth/metrics/metrics.go
0 → 100644
View file @
60a349f4
package
metrics
var
EnabledExpensive
=
false
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment