@ -25,25 +25,35 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rlp"
)
)
// SecureTrie wraps a trie with key hashing. In a secure trie, all
// SecureTrie is the old name of StateTrie.
// Deprecated: use StateTrie.
type SecureTrie = StateTrie
// NewSecure creates a new StateTrie.
// Deprecated: use NewStateTrie.
func NewSecure ( owner common . Hash , root common . Hash , db * Database ) ( * SecureTrie , error ) {
return NewStateTrie ( owner , root , db )
}
// StateTrie wraps a trie with key hashing. In a secure trie, all
// access operations hash the key using keccak256. This prevents
// access operations hash the key using keccak256. This prevents
// calling code from creating long chains of nodes that
// calling code from creating long chains of nodes that
// increase the access time.
// increase the access time.
//
//
// Contrary to a regular trie, a SecureTrie can only be created with
// Contrary to a regular trie, a Stat eTrie can only be created with
// New and must have an attached database. The database also stores
// New and must have an attached database. The database also stores
// the preimage of each key.
// the preimage of each key.
//
//
// SecureTrie is not safe for concurrent use.
// Stat eTrie is not safe for concurrent use.
type SecureTrie struct {
type Stat eTrie struct {
trie Trie
trie Trie
preimages * preimageStore
preimages * preimageStore
hashKeyBuf [ common . HashLength ] byte
hashKeyBuf [ common . HashLength ] byte
secKeyCache map [ string ] [ ] byte
secKeyCache map [ string ] [ ] byte
secKeyCacheOwner * Secur eTrie // Pointer to self, replace the key cache on mismatch
secKeyCacheOwner * Stat eTrie // Pointer to self, replace the key cache on mismatch
}
}
// NewSecur e creates a trie with an existing root node from a backing database
// NewStateTri e creates a trie with an existing root node from a backing database
// and optional intermediate in-memory node pool.
// and optional intermediate in-memory node pool.
//
//
// If root is the zero hash or the sha3 hash of an empty string, the
// If root is the zero hash or the sha3 hash of an empty string, the
@ -54,7 +64,7 @@ type SecureTrie struct {
// Loaded nodes are kept around until their 'cache generation' expires.
// Loaded nodes are kept around until their 'cache generation' expires.
// A new cache generation is created by each call to Commit.
// A new cache generation is created by each call to Commit.
// cachelimit sets the number of past cache generations to keep.
// cachelimit sets the number of past cache generations to keep.
func NewSecur e ( owner common . Hash , root common . Hash , db * Database ) ( * Secur eTrie , error ) {
func NewStateTri e ( owner common . Hash , root common . Hash , db * Database ) ( * Stat eTrie , error ) {
if db == nil {
if db == nil {
panic ( "trie.NewSecure called without a database" )
panic ( "trie.NewSecure called without a database" )
}
}
@ -62,12 +72,12 @@ func NewSecure(owner common.Hash, root common.Hash, db *Database) (*SecureTrie,
if err != nil {
if err != nil {
return nil , err
return nil , err
}
}
return & Secur eTrie { trie : * trie , preimages : db . preimages } , nil
return & Stat eTrie { trie : * trie , preimages : db . preimages } , nil
}
}
// Get returns the value for key stored in the trie.
// Get returns the value for key stored in the trie.
// The value bytes must not be modified by the caller.
// The value bytes must not be modified by the caller.
func ( t * Secur eTrie ) Get ( key [ ] byte ) [ ] byte {
func ( t * Stat eTrie ) Get ( key [ ] byte ) [ ] byte {
res , err := t . TryGet ( key )
res , err := t . TryGet ( key )
if err != nil {
if err != nil {
log . Error ( fmt . Sprintf ( "Unhandled trie error: %v" , err ) )
log . Error ( fmt . Sprintf ( "Unhandled trie error: %v" , err ) )
@ -78,19 +88,50 @@ func (t *SecureTrie) Get(key []byte) []byte {
// TryGet returns the value for key stored in the trie.
// TryGet returns the value for key stored in the trie.
// The value bytes must not be modified by the caller.
// The value bytes must not be modified by the caller.
// If a node was not found in the database, a MissingNodeError is returned.
// If a node was not found in the database, a MissingNodeError is returned.
func ( t * Secur eTrie ) TryGet ( key [ ] byte ) ( [ ] byte , error ) {
func ( t * Stat eTrie ) TryGet ( key [ ] byte ) ( [ ] byte , error ) {
return t . trie . TryGet ( t . hashKey ( key ) )
return t . trie . TryGet ( t . hashKey ( key ) )
}
}
func ( t * StateTrie ) TryGetAccount ( key [ ] byte ) ( * types . StateAccount , error ) {
var ret types . StateAccount
res , err := t . trie . TryGet ( t . hashKey ( key ) )
if err != nil {
log . Error ( fmt . Sprintf ( "Unhandled trie error: %v" , err ) )
return & ret , err
}
if res == nil {
return nil , nil
}
err = rlp . DecodeBytes ( res , & ret )
return & ret , err
}
// TryGetAccountWithPreHashedKey does the same thing as TryGetAccount, however
// it expects a key that is already hashed. This constitutes an abstraction leak,
// since the client code needs to know the key format.
func ( t * StateTrie ) TryGetAccountWithPreHashedKey ( key [ ] byte ) ( * types . StateAccount , error ) {
var ret types . StateAccount
res , err := t . trie . TryGet ( key )
if err != nil {
log . Error ( fmt . Sprintf ( "Unhandled trie error: %v" , err ) )
return & ret , err
}
if res == nil {
return nil , nil
}
err = rlp . DecodeBytes ( res , & ret )
return & ret , err
}
// TryGetNode attempts to retrieve a trie node by compact-encoded path. It is not
// TryGetNode attempts to retrieve a trie node by compact-encoded path. It is not
// possible to use keybyte-encoding as the path might contain odd nibbles.
// possible to use keybyte-encoding as the path might contain odd nibbles.
func ( t * SecureTrie ) TryGetNode ( path [ ] byte ) ( [ ] byte , int , error ) {
func ( t * Stat eTrie ) TryGetNode ( path [ ] byte ) ( [ ] byte , int , error ) {
return t . trie . TryGetNode ( path )
return t . trie . TryGetNode ( path )
}
}
// TryUpdateAccount account will abstract the write of an account to the
// TryUpdateAccount account will abstract the write of an account to the
// secure trie.
// secure trie.
func ( t * SecureTrie ) TryUpdateAccount ( key [ ] byte , acc * types . StateAccount ) error {
func ( t * Stat eTrie ) TryUpdateAccount ( key [ ] byte , acc * types . StateAccount ) error {
hk := t . hashKey ( key )
hk := t . hashKey ( key )
data , err := rlp . EncodeToBytes ( acc )
data , err := rlp . EncodeToBytes ( acc )
if err != nil {
if err != nil {
@ -109,7 +150,7 @@ func (t *SecureTrie) TryUpdateAccount(key []byte, acc *types.StateAccount) error
//
//
// The value bytes must not be modified by the caller while they are
// The value bytes must not be modified by the caller while they are
// stored in the trie.
// stored in the trie.
func ( t * Secur eTrie ) Update ( key , value [ ] byte ) {
func ( t * Stat eTrie ) Update ( key , value [ ] byte ) {
if err := t . TryUpdate ( key , value ) ; err != nil {
if err := t . TryUpdate ( key , value ) ; err != nil {
log . Error ( fmt . Sprintf ( "Unhandled trie error: %v" , err ) )
log . Error ( fmt . Sprintf ( "Unhandled trie error: %v" , err ) )
}
}
@ -123,7 +164,7 @@ func (t *SecureTrie) Update(key, value []byte) {
// stored in the trie.
// stored in the trie.
//
//
// If a node was not found in the database, a MissingNodeError is returned.
// If a node was not found in the database, a MissingNodeError is returned.
func ( t * Secur eTrie ) TryUpdate ( key , value [ ] byte ) error {
func ( t * Stat eTrie ) TryUpdate ( key , value [ ] byte ) error {
hk := t . hashKey ( key )
hk := t . hashKey ( key )
err := t . trie . TryUpdate ( hk , value )
err := t . trie . TryUpdate ( hk , value )
if err != nil {
if err != nil {
@ -134,7 +175,7 @@ func (t *SecureTrie) TryUpdate(key, value []byte) error {
}
}
// Delete removes any existing value for key from the trie.
// Delete removes any existing value for key from the trie.
func ( t * Secur eTrie ) Delete ( key [ ] byte ) {
func ( t * Stat eTrie ) Delete ( key [ ] byte ) {
if err := t . TryDelete ( key ) ; err != nil {
if err := t . TryDelete ( key ) ; err != nil {
log . Error ( fmt . Sprintf ( "Unhandled trie error: %v" , err ) )
log . Error ( fmt . Sprintf ( "Unhandled trie error: %v" , err ) )
}
}
@ -142,7 +183,7 @@ func (t *SecureTrie) Delete(key []byte) {
// TryDelete removes any existing value for key from the trie.
// TryDelete removes any existing value for key from the trie.
// If a node was not found in the database, a MissingNodeError is returned.
// If a node was not found in the database, a MissingNodeError is returned.
func ( t * Secur eTrie ) TryDelete ( key [ ] byte ) error {
func ( t * Stat eTrie ) TryDelete ( key [ ] byte ) error {
hk := t . hashKey ( key )
hk := t . hashKey ( key )
delete ( t . getSecKeyCache ( ) , string ( hk ) )
delete ( t . getSecKeyCache ( ) , string ( hk ) )
return t . trie . TryDelete ( hk )
return t . trie . TryDelete ( hk )
@ -150,7 +191,7 @@ func (t *SecureTrie) TryDelete(key []byte) error {
// GetKey returns the sha3 preimage of a hashed key that was
// GetKey returns the sha3 preimage of a hashed key that was
// previously used to store a value.
// previously used to store a value.
func ( t * Secur eTrie ) GetKey ( shaKey [ ] byte ) [ ] byte {
func ( t * Stat eTrie ) GetKey ( shaKey [ ] byte ) [ ] byte {
if key , ok := t . getSecKeyCache ( ) [ string ( shaKey ) ] ; ok {
if key , ok := t . getSecKeyCache ( ) [ string ( shaKey ) ] ; ok {
return key
return key
}
}
@ -167,7 +208,7 @@ func (t *SecureTrie) GetKey(shaKey []byte) []byte {
// All cached preimages will be also flushed if preimages recording is enabled.
// All cached preimages will be also flushed if preimages recording is enabled.
// Once the trie is committed, it's not usable anymore. A new trie must
// Once the trie is committed, it's not usable anymore. A new trie must
// be created with new root and updated trie database for following usage
// be created with new root and updated trie database for following usage
func ( t * Secur eTrie ) Commit ( collectLeaf bool ) ( common . Hash , * NodeSet , error ) {
func ( t * Stat eTrie ) Commit ( collectLeaf bool ) ( common . Hash , * NodeSet , error ) {
// Write all the pre-images to the actual disk database
// Write all the pre-images to the actual disk database
if len ( t . getSecKeyCache ( ) ) > 0 {
if len ( t . getSecKeyCache ( ) ) > 0 {
if t . preimages != nil {
if t . preimages != nil {
@ -183,15 +224,15 @@ func (t *SecureTrie) Commit(collectLeaf bool) (common.Hash, *NodeSet, error) {
return t . trie . Commit ( collectLeaf )
return t . trie . Commit ( collectLeaf )
}
}
// Hash returns the root hash of Secur eTrie. It does not write to the
// Hash returns the root hash of Stat eTrie. It does not write to the
// database and can be used even if the trie doesn't have one.
// database and can be used even if the trie doesn't have one.
func ( t * Secur eTrie ) Hash ( ) common . Hash {
func ( t * Stat eTrie ) Hash ( ) common . Hash {
return t . trie . Hash ( )
return t . trie . Hash ( )
}
}
// Copy returns a copy of Secur eTrie.
// Copy returns a copy of Stat eTrie.
func ( t * Secur eTrie ) Copy ( ) * Secur eTrie {
func ( t * Stat eTrie ) Copy ( ) * Stat eTrie {
return & Secur eTrie {
return & Stat eTrie {
trie : * t . trie . Copy ( ) ,
trie : * t . trie . Copy ( ) ,
preimages : t . preimages ,
preimages : t . preimages ,
secKeyCache : t . secKeyCache ,
secKeyCache : t . secKeyCache ,
@ -200,14 +241,14 @@ func (t *SecureTrie) Copy() *SecureTrie {
// NodeIterator returns an iterator that returns nodes of the underlying trie. Iteration
// NodeIterator returns an iterator that returns nodes of the underlying trie. Iteration
// starts at the key after the given start key.
// starts at the key after the given start key.
func ( t * Secur eTrie ) NodeIterator ( start [ ] byte ) NodeIterator {
func ( t * Stat eTrie ) NodeIterator ( start [ ] byte ) NodeIterator {
return t . trie . NodeIterator ( start )
return t . trie . NodeIterator ( start )
}
}
// hashKey returns the hash of key as an ephemeral buffer.
// hashKey returns the hash of key as an ephemeral buffer.
// The caller must not hold onto the return value because it will become
// The caller must not hold onto the return value because it will become
// invalid on the next call to hashKey or secKey.
// invalid on the next call to hashKey or secKey.
func ( t * Secur eTrie ) hashKey ( key [ ] byte ) [ ] byte {
func ( t * Stat eTrie ) hashKey ( key [ ] byte ) [ ] byte {
h := newHasher ( false )
h := newHasher ( false )
h . sha . Reset ( )
h . sha . Reset ( )
h . sha . Write ( key )
h . sha . Write ( key )
@ -219,7 +260,7 @@ func (t *SecureTrie) hashKey(key []byte) []byte {
// getSecKeyCache returns the current secure key cache, creating a new one if
// getSecKeyCache returns the current secure key cache, creating a new one if
// ownership changed (i.e. the current secure trie is a copy of another owning
// ownership changed (i.e. the current secure trie is a copy of another owning
// the actual cache).
// the actual cache).
func ( t * Secur eTrie ) getSecKeyCache ( ) map [ string ] [ ] byte {
func ( t * Stat eTrie ) getSecKeyCache ( ) map [ string ] [ ] byte {
if t != t . secKeyCacheOwner {
if t != t . secKeyCacheOwner {
t . secKeyCacheOwner = t
t . secKeyCacheOwner = t
t . secKeyCache = make ( map [ string ] [ ] byte )
t . secKeyCache = make ( map [ string ] [ ] byte )