You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

136 lines
2.9 KiB

package state
import (
"bytes"
"sync"
"time"
. "github.com/tendermint/tendermint/binary"
. "github.com/tendermint/tendermint/blocks"
db_ "github.com/tendermint/tendermint/db"
"github.com/tendermint/tendermint/merkle"
)
var (
stateKey = []byte("stateKey")
)
type State struct {
mtx sync.Mutex
db db_.Db
height uint32
commitTime time.Time
accounts merkle.Tree
validators *ValidatorSet
}
func LoadState(db db_.Db) *State {
s := &State{}
buf := db.Get(stateKey)
if len(buf) == 0 {
s.height = uint32(0)
s.commitTime = time.Unix(0, 0) // XXX BOOTSTRAP
s.accounts = merkle.NewIAVLTree(db) // XXX BOOTSTRAP
s.validators = NewValidatorSet(nil) // XXX BOOTSTRAP
} else {
reader := bytes.NewReader(buf)
var n int64
var err error
s.height = ReadUInt32(reader, &n, &err)
s.commitTime = ReadTime(reader, &n, &err)
accountsMerkleRoot := ReadByteSlice(reader, &n, &err)
s.accounts = merkle.NewIAVLTreeFromHash(db, accountsMerkleRoot)
s.validators = NewValidatorSet(nil)
for reader.Len() > 0 {
validator := ReadValidator(reader, &n, &err)
s.validators.Add(validator)
}
if err != nil {
panic(err)
}
}
return s
}
func (s *State) Save() {
s.mtx.Lock()
defer s.mtx.Unlock()
s.accounts.Save()
var buf bytes.Buffer
var n int64
var err error
WriteUInt32(&buf, s.height, &n, &err)
WriteTime(&buf, s.commitTime, &n, &err)
WriteByteSlice(&buf, s.accounts.Hash(), &n, &err)
for _, validator := range s.validators.Map() {
WriteBinary(&buf, validator, &n, &err)
}
if err != nil {
panic(err)
}
s.db.Set(stateKey, buf.Bytes())
}
func (s *State) Copy() *State {
s.mtx.Lock()
defer s.mtx.Unlock()
return &State{
db: s.db,
height: s.height,
commitTime: s.commitTime,
accounts: s.accounts.Copy(),
validators: s.validators.Copy(),
}
}
func (s *State) CommitTx(tx *Tx) error {
s.mtx.Lock()
defer s.mtx.Unlock()
// TODO commit the tx
panic("Implement CommitTx()")
return nil
}
func (s *State) CommitBlock(b *Block, commitTime time.Time) error {
s.mtx.Lock()
defer s.mtx.Unlock()
// TODO commit the txs
// XXX also increment validator accum.
panic("Implement CommitBlock()")
return nil
}
func (s *State) Height() uint32 {
s.mtx.Lock()
defer s.mtx.Unlock()
return s.height
}
func (s *State) CommitTime() time.Time {
s.mtx.Lock()
defer s.mtx.Unlock()
return s.commitTime
}
// The returned ValidatorSet gets mutated upon s.Commit*().
func (s *State) Validators() *ValidatorSet {
s.mtx.Lock()
defer s.mtx.Unlock()
return s.validators
}
func (s *State) Account(accountId uint64) (*Account, error) {
s.mtx.Lock()
defer s.mtx.Unlock()
idBytes, err := BasicCodec.Write(accountId)
if err != nil {
return nil, err
}
accountBytes := s.accounts.Get(idBytes)
if accountBytes == nil {
return nil, nil
}
n, err := int64(0), error(nil)
account := ReadAccount(bytes.NewBuffer(accountBytes), &n, &err)
return account, err
}