This repository has been archived by the owner on May 13, 2022. It is now read-only.
/
state.go
85 lines (75 loc) · 2.52 KB
/
state.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package native
import (
"github.com/hyperledger/burrow/acm"
"github.com/hyperledger/burrow/acm/acmstate"
"github.com/hyperledger/burrow/binary"
"github.com/hyperledger/burrow/crypto"
"github.com/hyperledger/burrow/execution/engine"
"github.com/hyperledger/burrow/execution/errors"
)
// This wrapper provides a state that behaves 'as if' the natives were stored directly in state.
// TODO: we may want to actually store native account sentinel values (and their metadata) in on-disk state down the line
type State struct {
natives engine.Natives
backend acmstate.ReaderWriter
}
// Get a new state that wraps the backend but intercepts any calls to natives returning appropriate errors message
// or an Account sentinel for the particular native
func NewState(natives engine.Natives, backend acmstate.ReaderWriter) *State {
return &State{
natives: natives,
backend: backend,
}
}
func (s *State) UpdateAccount(updatedAccount *acm.Account) error {
err := s.ensureNonNative(updatedAccount.Address, "update account")
if err != nil {
return err
}
return s.backend.UpdateAccount(updatedAccount)
}
func (s *State) GetAccount(address crypto.Address) (*acm.Account, error) {
contract := s.natives.GetByAddress(address)
if contract != nil {
return account(contract), nil
}
return s.backend.GetAccount(address)
}
func (s *State) RemoveAccount(address crypto.Address) error {
err := s.ensureNonNative(address, "remove account")
if err != nil {
return err
}
return s.backend.RemoveAccount(address)
}
func (s *State) GetStorage(address crypto.Address, key binary.Word256) ([]byte, error) {
err := s.ensureNonNative(address, "get storage")
if err != nil {
return nil, err
}
return s.backend.GetStorage(address, key)
}
func (s *State) SetStorage(address crypto.Address, key binary.Word256, value []byte) error {
err := s.ensureNonNative(address, "set storage")
if err != nil {
return err
}
return s.backend.SetStorage(address, key, value)
}
func (s *State) ensureNonNative(address crypto.Address, action string) error {
contract := s.natives.GetByAddress(address)
if contract != nil {
return errors.Errorf(errors.Codes.ReservedAddress,
"cannot %s at %v because that address is reserved for a native contract '%s'",
action, address, contract.FullName())
}
return nil
}
func account(callable engine.Native) *acm.Account {
return &acm.Account{
Address: callable.Address(),
NativeName: callable.FullName(),
// TODO: this is not populated yet, see FIXME note on native.Contract
ContractMeta: callable.ContractMeta(),
}
}