github.com/datachainlab/burrow@v0.25.0/execution/state/state.go (about)

     1  // Copyright 2017 Monax Industries Limited
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package state
    16  
    17  import (
    18  	"crypto/sha256"
    19  	"fmt"
    20  	"sync"
    21  
    22  	"github.com/hyperledger/burrow/acm"
    23  	"github.com/hyperledger/burrow/acm/acmstate"
    24  	"github.com/hyperledger/burrow/acm/validator"
    25  	"github.com/hyperledger/burrow/binary"
    26  	"github.com/hyperledger/burrow/crypto"
    27  	"github.com/hyperledger/burrow/execution/exec"
    28  	"github.com/hyperledger/burrow/execution/names"
    29  	"github.com/hyperledger/burrow/execution/proposal"
    30  	"github.com/hyperledger/burrow/genesis"
    31  	"github.com/hyperledger/burrow/logging"
    32  	"github.com/hyperledger/burrow/permission"
    33  	"github.com/hyperledger/burrow/storage"
    34  	"github.com/hyperledger/burrow/txs"
    35  	dbm "github.com/tendermint/tendermint/libs/db"
    36  )
    37  
    38  const (
    39  	DefaultValidatorsWindowSize = 10
    40  	defaultCacheCapacity        = 1024
    41  	uint64Length                = 8
    42  	// Prefix under which the versioned merkle state tree resides - tracking previous versions of history
    43  	forestPrefix = "f"
    44  )
    45  
    46  // Implements account and blockchain state
    47  var _ acmstate.IterableReader = &State{}
    48  var _ names.IterableReader = &State{}
    49  var _ Updatable = &writeState{}
    50  
    51  type KeyFormatStore struct {
    52  	Account   *storage.MustKeyFormat
    53  	Storage   *storage.MustKeyFormat
    54  	Name      *storage.MustKeyFormat
    55  	Proposal  *storage.MustKeyFormat
    56  	Validator *storage.MustKeyFormat
    57  	Event     *storage.MustKeyFormat
    58  	TxHash    *storage.MustKeyFormat
    59  }
    60  
    61  var keys = KeyFormatStore{
    62  	// AccountAddress -> Account
    63  	Account: storage.NewMustKeyFormat("a", crypto.AddressLength),
    64  	// AccountAddress, Key -> Value
    65  	Storage: storage.NewMustKeyFormat("s", crypto.AddressLength, binary.Word256Length),
    66  	// Name -> Entry
    67  	Name: storage.NewMustKeyFormat("n", storage.VariadicSegmentLength),
    68  	// ProposalHash -> Proposal
    69  	Proposal: storage.NewMustKeyFormat("p", sha256.Size),
    70  	// ValidatorAddress -> Power
    71  	Validator: storage.NewMustKeyFormat("v", crypto.AddressLength),
    72  	// Height, EventIndex -> StreamEvent
    73  	Event: storage.NewMustKeyFormat("e", uint64Length, uint64Length),
    74  	// TxHash -> TxHeight, TxIndex
    75  	TxHash: storage.NewMustKeyFormat("th", txs.HashLength),
    76  }
    77  
    78  func init() {
    79  	err := storage.EnsureKeyFormatStore(keys)
    80  	if err != nil {
    81  		panic(fmt.Errorf("KeyFormatStore is invalid: %v", err))
    82  	}
    83  }
    84  
    85  type Updatable interface {
    86  	acmstate.Writer
    87  	names.Writer
    88  	proposal.Writer
    89  	validator.Writer
    90  	AddBlock(blockExecution *exec.BlockExecution) error
    91  }
    92  
    93  // Wraps state to give access to writer methods
    94  type writeState struct {
    95  	forest       *storage.MutableForest
    96  	accountStats acmstate.AccountStats
    97  	ring         *validator.Ring
    98  }
    99  
   100  type ReadState struct {
   101  	Forest storage.ForestReader
   102  	validator.History
   103  }
   104  
   105  // Writers to state are responsible for calling State.Lock() before calling
   106  type State struct {
   107  	sync.Mutex
   108  	db dbm.DB
   109  	ReadState
   110  	writeState writeState
   111  	logger     *logging.Logger
   112  }
   113  
   114  // Create a new State object
   115  func NewState(db dbm.DB) *State {
   116  	forest, err := storage.NewMutableForest(storage.NewPrefixDB(db, forestPrefix), defaultCacheCapacity)
   117  	if err != nil {
   118  		// This should only happen if we have negative cache capacity, which for us is a positive compile-time constant
   119  		panic(fmt.Errorf("could not create new state because error creating MutableForest"))
   120  	}
   121  	ring := validator.NewRing(nil, DefaultValidatorsWindowSize)
   122  	rs := ReadState{Forest: forest, History: ring}
   123  	ws := writeState{forest: forest, ring: ring}
   124  	return &State{
   125  		db:         db,
   126  		ReadState:  rs,
   127  		writeState: ws,
   128  		logger:     logging.NewNoopLogger(),
   129  	}
   130  }
   131  
   132  // Make genesis state from GenesisDoc and save to DB
   133  func MakeGenesisState(db dbm.DB, genesisDoc *genesis.GenesisDoc) (*State, error) {
   134  	s := NewState(db)
   135  
   136  	const errHeader = "MakeGenesisState():"
   137  	// Make accounts state tree
   138  	for _, genAcc := range genesisDoc.Accounts {
   139  		perm := genAcc.Permissions
   140  		acc := &acm.Account{
   141  			Address:     genAcc.Address,
   142  			Balance:     genAcc.Amount,
   143  			Permissions: perm,
   144  		}
   145  		err := s.writeState.UpdateAccount(acc)
   146  		if err != nil {
   147  			return nil, fmt.Errorf("%s %v", errHeader, err)
   148  		}
   149  	}
   150  	// Make genesis validators
   151  	err := s.writeState.MakeGenesisValidators(genesisDoc)
   152  	if err != nil {
   153  		return nil, fmt.Errorf("%s %v", errHeader, err)
   154  	}
   155  	// global permissions are saved as the 0 address
   156  	// so they are included in the accounts tree
   157  	globalPerms := permission.DefaultAccountPermissions
   158  	globalPerms = genesisDoc.GlobalPermissions
   159  	// XXX: make sure the set bits are all true
   160  	// Without it the HasPermission() functions will fail
   161  	globalPerms.Base.SetBit = permission.AllPermFlags
   162  
   163  	permsAcc := &acm.Account{
   164  		Address:     acm.GlobalPermissionsAddress,
   165  		Balance:     1337,
   166  		Permissions: globalPerms,
   167  	}
   168  	err = s.writeState.UpdateAccount(permsAcc)
   169  	if err != nil {
   170  		return nil, fmt.Errorf("%s %v", errHeader, err)
   171  	}
   172  
   173  	return s, nil
   174  }
   175  
   176  func (s *State) InitialCommit() error {
   177  	_, version, err := s.commit()
   178  	if err != nil {
   179  		return fmt.Errorf("could not save initial state: %v", err)
   180  	}
   181  	if version != VersionOffset {
   182  		return fmt.Errorf("initial state got version %d after committing genesis state but version offset should be %d",
   183  			version, VersionOffset)
   184  	}
   185  	return nil
   186  }
   187  
   188  // Tries to load the execution state from DB, returns nil with no error if no state found
   189  func LoadState(db dbm.DB, version int64) (*State, error) {
   190  	s := NewState(db)
   191  	err := s.writeState.forest.Load(version)
   192  	if err != nil {
   193  		return nil, fmt.Errorf("could not load MutableForest at version %d: %v", version, err)
   194  	}
   195  	// Populate stats. If this starts taking too long, store the value rather than the full scan at startup
   196  	err = s.IterateAccounts(func(acc *acm.Account) error {
   197  		if len(acc.Code) > 0 {
   198  			s.writeState.accountStats.AccountsWithCode++
   199  		} else {
   200  			s.writeState.accountStats.AccountsWithoutCode++
   201  		}
   202  		return nil
   203  	})
   204  	if err != nil {
   205  		return nil, err
   206  	}
   207  	// load the validator ring
   208  	ring, err := LoadValidatorRing(version, DefaultValidatorsWindowSize, s.writeState.forest.GetImmutable)
   209  	if err != nil {
   210  		return nil, err
   211  	}
   212  	s.writeState.ring = ring
   213  	s.ReadState.History = ring
   214  
   215  	return s, nil
   216  }
   217  
   218  func (s *State) Version() int64 {
   219  	return s.writeState.forest.Version()
   220  }
   221  
   222  func (s *State) Hash() []byte {
   223  	return s.writeState.forest.Hash()
   224  }
   225  
   226  func (s *State) LoadHeight(height uint64) (*ReadState, error) {
   227  	version := VersionAtHeight(height)
   228  	forest, err := s.writeState.forest.GetImmutable(version)
   229  	if err != nil {
   230  		return nil, err
   231  	}
   232  	ring, err := LoadValidatorRing(version, DefaultValidatorsWindowSize, s.writeState.forest.GetImmutable)
   233  	if err != nil {
   234  		return nil, err
   235  	}
   236  	return &ReadState{
   237  		Forest:  forest,
   238  		History: ring,
   239  	}, nil
   240  }
   241  
   242  // Perform updates to state whilst holding the write lock, allows a commit to hold the write lock across multiple
   243  // operations while preventing interlaced reads and writes
   244  func (s *State) Update(updater func(up Updatable) error) ([]byte, int64, error) {
   245  	s.Lock()
   246  	defer s.Unlock()
   247  	err := updater(&s.writeState)
   248  	if err != nil {
   249  		return nil, 0, err
   250  	}
   251  	return s.commit()
   252  }
   253  
   254  func (s *State) commit() ([]byte, int64, error) {
   255  	// save state at a new version may still be orphaned before we save the version against the hash
   256  	hash, version, err := s.writeState.forest.Save()
   257  	if err != nil {
   258  		return nil, 0, err
   259  	}
   260  	totalPowerChange, totalFlow, err := s.writeState.ring.Rotate()
   261  	if err != nil {
   262  		return nil, 0, err
   263  	}
   264  	if totalFlow.Sign() != 0 {
   265  		//noinspection ALL
   266  		s.logger.InfoMsg("validator set changes", "total_power_change", totalPowerChange, "total_flow", totalFlow)
   267  	}
   268  	return hash, version, err
   269  }
   270  
   271  // Creates a copy of the database to the supplied db
   272  func (s *State) Copy(db dbm.DB) (*State, error) {
   273  	stateCopy := NewState(db)
   274  	err := s.writeState.forest.IterateRWTree(nil, nil, true,
   275  		func(prefix []byte, tree *storage.RWTree) error {
   276  			treeCopy, err := stateCopy.writeState.forest.Writer(prefix)
   277  			if err != nil {
   278  				return err
   279  			}
   280  			return tree.IterateWriteTree(nil, nil, true, func(key []byte, value []byte) error {
   281  				treeCopy.Set(key, value)
   282  				return nil
   283  			})
   284  		})
   285  	if err != nil {
   286  		return nil, err
   287  	}
   288  	_, _, err = stateCopy.commit()
   289  	if err != nil {
   290  		return nil, err
   291  	}
   292  	return stateCopy, nil
   293  }
   294  
   295  func (s *State) SetLogger(logger *logging.Logger) {
   296  	s.logger = logger
   297  }