github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/execution/state/accounts.go (about)

     1  package state
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/hyperledger/burrow/storage"
     7  
     8  	"github.com/hyperledger/burrow/acm"
     9  	"github.com/hyperledger/burrow/acm/acmstate"
    10  	"github.com/hyperledger/burrow/binary"
    11  	"github.com/hyperledger/burrow/crypto"
    12  	"github.com/hyperledger/burrow/encoding"
    13  )
    14  
    15  // Returns nil if account does not exist with given address.
    16  func (s *ImmutableState) GetAccount(address crypto.Address) (*acm.Account, error) {
    17  	tree, err := s.Forest.Reader(keys.Account.Prefix())
    18  	if err != nil {
    19  		return nil, err
    20  	}
    21  	accBytes, err := tree.Get(keys.Account.KeyNoPrefix(address))
    22  	if err != nil {
    23  		return nil, err
    24  	} else if accBytes == nil {
    25  		return nil, nil
    26  	}
    27  	account := new(acm.Account)
    28  	err = encoding.Decode(accBytes, account)
    29  	if err != nil {
    30  		return nil, fmt.Errorf("could not decode Account: %v", err)
    31  	}
    32  	return account, nil
    33  }
    34  
    35  func (ws *writeState) statsAddAccount(acc *acm.Account) {
    36  	if acc != nil {
    37  		if len(acc.EVMCode) > 0 || len(acc.WASMCode) > 0 {
    38  			ws.accountStats.AccountsWithCode++
    39  		} else {
    40  			ws.accountStats.AccountsWithoutCode++
    41  		}
    42  	}
    43  }
    44  
    45  func (ws *writeState) statsRemoveAccount(acc *acm.Account) {
    46  	if acc != nil {
    47  		if len(acc.EVMCode) > 0 || len(acc.WASMCode) > 0 {
    48  			ws.accountStats.AccountsWithCode--
    49  		} else {
    50  			ws.accountStats.AccountsWithoutCode--
    51  		}
    52  	}
    53  }
    54  
    55  func (ws *writeState) UpdateAccount(account *acm.Account) error {
    56  	if account == nil {
    57  		return fmt.Errorf("UpdateAccount passed nil account in State")
    58  	}
    59  	bs, err := encoding.Encode(account)
    60  	if err != nil {
    61  		return fmt.Errorf("UpdateAccount could not encode account: %v", err)
    62  	}
    63  	return ws.forest.Write(keys.Account.Prefix(), func(tree *storage.RWTree) error {
    64  		updated := tree.Set(keys.Account.KeyNoPrefix(account.Address), bs)
    65  		if updated {
    66  			ws.statsAddAccount(account)
    67  		}
    68  		return nil
    69  	})
    70  }
    71  
    72  func (ws *writeState) RemoveAccount(address crypto.Address) error {
    73  	return ws.forest.Write(keys.Account.Prefix(), func(tree *storage.RWTree) error {
    74  		accBytes, deleted := tree.Delete(keys.Account.KeyNoPrefix(address))
    75  		if deleted {
    76  			account := new(acm.Account)
    77  			err := encoding.Decode(accBytes, account)
    78  			if err != nil {
    79  				return err
    80  			}
    81  			ws.statsRemoveAccount(account)
    82  			// Delete storage associated with account too
    83  			_, err = ws.forest.Delete(keys.Storage.Key(address))
    84  			if err != nil {
    85  				return err
    86  			}
    87  		}
    88  		return nil
    89  	})
    90  }
    91  
    92  func (s *ImmutableState) IterateAccounts(consumer func(*acm.Account) error) error {
    93  	tree, err := s.Forest.Reader(keys.Account.Prefix())
    94  	if err != nil {
    95  		return err
    96  	}
    97  	return tree.Iterate(nil, nil, true, func(key []byte, value []byte) error {
    98  		account := new(acm.Account)
    99  		err := encoding.Decode(value, account)
   100  		if err != nil {
   101  			return fmt.Errorf("IterateAccounts could not decode account: %v", err)
   102  		}
   103  		return consumer(account)
   104  	})
   105  }
   106  
   107  func (s *State) GetAccountStats() acmstate.AccountStats {
   108  	return s.writeState.accountStats
   109  }
   110  
   111  // Storage
   112  
   113  func (s *ImmutableState) GetStorage(address crypto.Address, key binary.Word256) ([]byte, error) {
   114  	keyFormat := keys.Storage.Fix(address)
   115  	tree, err := s.Forest.Reader(keyFormat.Prefix())
   116  	if err != nil {
   117  		return []byte{}, err
   118  	}
   119  	return tree.Get(keyFormat.KeyNoPrefix(key))
   120  }
   121  
   122  func (ws *writeState) SetStorage(address crypto.Address, key binary.Word256, value []byte) error {
   123  	keyFormat := keys.Storage.Fix(address)
   124  	return ws.forest.Write(keyFormat.Prefix(), func(tree *storage.RWTree) error {
   125  		zero := true
   126  		for _, b := range value {
   127  			if b != 0 {
   128  				zero = false
   129  				break
   130  			}
   131  		}
   132  		if zero {
   133  			tree.Delete(keyFormat.KeyNoPrefix(key))
   134  		} else {
   135  			tree.Set(keyFormat.KeyNoPrefix(key), value)
   136  		}
   137  		return nil
   138  	})
   139  }
   140  
   141  func (s *ImmutableState) IterateStorage(address crypto.Address, consumer func(key binary.Word256, value []byte) error) error {
   142  	keyFormat := keys.Storage.Fix(address)
   143  	tree, err := s.Forest.Reader(keyFormat.Prefix())
   144  	if err != nil {
   145  		return err
   146  	}
   147  	return tree.Iterate(nil, nil, true,
   148  		func(key []byte, value []byte) error {
   149  
   150  			if len(key) != binary.Word256Bytes {
   151  				return fmt.Errorf("key '%X' stored for account %s is not a %v-byte word",
   152  					key, address, binary.Word256Bytes)
   153  			}
   154  			if len(value) != binary.Word256Bytes {
   155  				return fmt.Errorf("value '%X' stored for account %s is not a %v-byte word",
   156  					key, address, binary.Word256Bytes)
   157  			}
   158  			return consumer(binary.LeftPadWord256(key), value)
   159  		})
   160  }