Blockchain tutorial Ethereum Source Analysis Core-state Source Analysis (ii)

Source: Internet
Author: User

# # Statedb.go

Statedb is used to store all the contents of the Ethereum merkle trie. The statedb is responsible for caching and storing nested states. This is the general query interface for retrieving contracts and accounts:

Data

Type statedb struct {db//backend database trie trie//trie Tree Main account trie//This map holds ' live ' obje    CTS, which would get modified while processing a state transition.    The following map is used to store the currently active objects, which are modified when the state transitions.    Stateobjects is used to cache objects//Stateobjectsdirty used to cache objects that have been modified. Stateobjects Map[common. Address]*stateobject Stateobjectsdirty Map[common.    address]struct{}//DB error. State objects is used by the consensus core and VM which is//unable to deal with Database-level errors. Any error This occurs//during a database read is memoized here and would eventually be returned/by Statedb.commi    T. dberr error//The refund counter, also used by state transitioning. Refund counter.    The feature is not yet known. Refund *big. Int Thash, Bhash Common. Hash//Current transaction hash and block hash txindex INT//Current trade index logs Map[common. Hash][]*types. Log//Logs key is the hash value of the transaction logsize uint Preimages Map[common. Hash][]byte//EVM calculations for sha3->byte[] The mapping relationship//Journal of State modifications.    This is the backbone of//Snapshot and Reverttosnapshot. The status modification log.    This is the pillar of snapshot and reverttosnapshot. Journal Journal Validrevisions []revision nextrevisionid int lock sync. Mutex}

constructor function

General Usage Statedb, _: = state. New (Common. hash{}, state. Newdatabase (DB))

Create a new state from a given trie
Func New (Root common. Hash, DB Database) (statedb, error) {
TR, err: = db. Opentrie (Root)
If err! = Nil {
return nil, err
}
Return &statedb{
Db:db,
TRIE:TR,
Stateobjects:make (Map[common. Address]
stateobject),
Stateobjectsdirty:make (Map[common. address]struct{}),
Refund:new (big. INT),
Logs:make (Map[common. Hash][]*types. LOG),
Preimages:make (Map[common. Hash][]byte),
}, Nil
}

Handling of Log

The state provides log processing, which is unexpectedly because log is actually stored in the blockchain and is not stored in state trie, the State provides log processing, using several functions based on the following. Strange is not to see how to delete the information inside the logs, if not deleted, should be more accumulated. TODO Logs Delete

The prepare function is executed at the beginning of the transaction execution.

The Addlog function is executed by the VM during the execution of the transaction. Add a log. At the same time, the log and the transaction associated with the addition of part of the transaction information.

Getlogs function, the transaction is completed and taken away.

Prepare sets the current transaction hash and index and block hash which are
Used when the EVM is emits new state logs.
Func (self *statedb) Prepare (Thash, Bhash Common. Hash, ti int) {
Self.thash = Thash
Self.bhash = Bhash
Self.txindex = Ti
}

The Func (self statedb) addlog (log types. LOG) {
self.journal = Append (self.journal, Addlogchange{txhash:self.thash})

log.TxHash = self.thashlog.BlockHash = self.bhashlog.TxIndex = uint(self.txIndex)log.Index = self.logSizeself.logs[self.thash] = append(self.logs[self.thash], log)self.logSize++

}
Func (self statedb) getlogs (hash common. Hash) []types. Log {
return Self.logs[hash]
}

Func (self statedb) Logs () []types. Log {
var logs []*types. Log
For _, LGs: = Range Self.logs {
logs = append (logs, LGs ...)
}
return logs
}

StateObject processing

Getstateobject, first obtained from the cache, if not from the trie tree, and loaded into the cache.

Retrieve a state object given my the address. Returns Nil if not found.
The Func (self statedb) getstateobject (addr common. Address) (StateObject stateobject) {
Prefer ' Live ' objects.
If obj: = self.stateobjects[addr]; Obj! = Nil {
If obj.deleted {
return Nil
}
return obj
}

// Load the object from the database.enc, err := self.trie.TryGet(addr[:])if len(enc) == 0 {    self.setError(err)    return nil}var data Accountif err := rlp.DecodeBytes(enc, &data); err != nil {    log.Error("Failed to decode state object", "addr", addr, "err", err)    return nil}// Insert into the live set.obj := newObject(self, addr, data, self.MarkStateObjectDirty)self.setStateObject(obj)return obj

}

Markstateobjectdirty, set a stateobject to dirty. Insert an empty struct directly toward the address of the Stateobjectdirty.

Markstateobjectdirty adds the specified object to the dirty map to avoid costly
State object caches iteration to find a handful of modified ones.
The Func (self *statedb) markstateobjectdirty (addr common. Address) {
SELF.STATEOBJECTSDIRTY[ADDR] = struct{}{}
}

Snapshot and rollback features

Snapshot can create a snapshot and then roll back to which state through Reverttosnapshot, which is done through journal. Each step of the change will add an undo log to the journal. If you need to roll back, just execute the undo log.

Snapshot returns an identifier for the current revision of the state.
Func (self *statedb) Snapshot () int {
ID: = Self.nextrevisionid
self.nextrevisionid++
Self.validrevisions = Append (Self.validrevisions, Revision{id, Len (self.journal)})
Return ID
}

Reverttosnapshot reverts all state changes made since the given revision.
Func (self *statedb) reverttosnapshot (revid int) {
Find the snapshot in the stack of valid snapshots.
IDX: = sort. Search (Len (self.validrevisions), func (i int) bool {
return self.validrevisions[i].id >= revid
})
If idx = = Len (self.validrevisions) | | Self.validrevisions[idx].id! = revid {
Panic (FMT. Errorf ("revision ID%V cannot be reverted", revid))
}
Snapshot: = Self.validrevisions[idx].journalindex

// Replay the journal to undo changes.for i := len(self.journal) - 1; i >= snapshot; i-- {    self.journal[i].undo(self)}self.journal = self.journal[:snapshot]// Remove invalidated snapshots from the stack.self.validRevisions = self.validRevisions[:idx]

}

Gets the root hash value of the middle state

Intermediateroot is used to calculate the hash value of the root of the current state trie. This method is called during the execution of the transaction. will be deposited transaction receipt

The finalise method calls the Update method to write the changes stored in the cache layer to the Trie database. But this time it's not written to the underlying database. No commit has been invoked, the data is still in memory, and it has not landed as a file.

Finalise finalises the state by removing the self destructed objects
and clears the journal as well as the refunds.
Func (S *statedb) finalise (deleteemptyobjects bool) {
For addr: = Range S.stateobjectsdirty {
StateObject: = s.stateobjects[addr]
If stateobject.suicided | | (Deleteemptyobjects && stateobject.empty ()) {
S.deletestateobject (StateObject)
} else {
Stateobject.updateroot (s.db)
S.updatestateobject (StateObject)
}
}
Invalidate Journal because reverting across transactions is not allowed.
S.clearjournalandrefund ()
}

Intermediateroot computes the current root hash of the state trie.
It's called in between transactions to get the root hash that
goes into transaction receipts.
Func (S *statedb) intermediateroot (deleteemptyobjects bool) common. Hash {
S.finalise (deleteemptyobjects)
Return S.trie.hash ()
}

Commit method

Committo is used to commit changes.

Committo writes the state to the given database.
Func (S *statedb) Committo (dBW trie. Databasewriter, deleteemptyobjects bool) (Root common. Hash, err Error) {
Defer S.clearjournalandrefund ()

Commit objects to the Trie.for addr, stateobject: = Range S.stateobjects {_, IsDirty: = S.stateobjectsdirty[addr] Switch {case Stateobject.suicided | | (IsDirty && deleteemptyobjects && stateobject.empty ())://If The object has been removed, Don t bo        ther syncing it//And just mark it for deletion in the trie.        S.deletestateobject (stateobject) Case IsDirty://Write to contract code associated with the state object If Stateobject.code! = Nil && Stateobject.dirtycode {if err: = dBW. Put (Stateobject.codehash (), Stateobject.code); Err! = Nil {return common. hash{}, err} Stateobject.dirtycode = false}//Write any storage changes in the stat        E object to its storage trie. If err: = Stateobject.committrie (s.db, DBW); Err! = Nil {return common.        hash{}, err}//Update the object in the main account trie. S.updatestateObject (stateobject)} delete (S.stateobjectsdirty, addr)}//Write trie changes.root, err = S.trie.committo (DBW) log. Debug ("Trie cache stats after commit", "misses", Trie. Cachemisses (), "unloads", trie. Cacheunloads ()) return root, err

}

Summarize

The state package provides the status management capabilities of users and contracts. Various state transitions for states and contracts are managed. Cach

Blockchain tutorial Ethereum Source Analysis Core-state Source Analysis (ii)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.