forked from TrueCloudLab/neoneo-go
core: add InitializeCache method to NEO native contracts
There might be a case when cached contract values store nil (e.g.
after restoring chain from dump). We should always initialize cached
values irrespective to the (NEO).Initialize method.
This commit fixes a bug introduced in 83e94d3
when 4-nodes privnet is failing after restoring from dump:
```
$ docker logs neo_go_node_one
=> Try to restore blocks before running node
2020-09-30T11:55:49.122Z INFO no storage version found! creating genesis block
2020-09-30T11:55:49.124Z INFO service hasn't started since it's disabled {"service": "Pprof"}
2020-09-30T11:55:49.124Z INFO service hasn't started since it's disabled {"service": "Prometheus"}
2020-09-30T11:55:49.124Z INFO skipped genesis block {"hash": "3792eaa22c196399a114666fd491c4b9ac52491d9abb1f633a8036a8ac81e4db"}
2020-09-30T11:55:49.141Z INFO shutting down service {"service": "Pprof", "endpoint": ":30001"}
2020-09-30T11:55:49.141Z INFO shutting down service {"service": "Prometheus", "endpoint": ":40001"}
2020-09-30T11:55:49.141Z INFO blockchain persist completed {"persistedBlocks": 3, "persistedKeys": 146, "headerHeight": 3, "blockHeight": 3, "took": "324.27µs"}
2020-09-30T11:55:49.150Z INFO restoring blockchain {"version": "0.1.0"}
2020-09-30T11:55:49.150Z INFO service hasn't started since it's disabled {"service": "Prometheus"}
2020-09-30T11:55:49.151Z INFO service hasn't started since it's disabled {"service": "Pprof"}
2020-09-30T11:55:49.443Z INFO starting rpc-server {"endpoint": ":30333"}
2020-09-30T11:55:49.443Z INFO node started {"blockHeight": 3, "headerHeight": 3}
_ ____________ __________
/ | / / ____/ __ \ / ____/ __ \
/ |/ / __/ / / / /_____/ / __/ / / /
/ /| / /___/ /_/ /_____/ /_/ / /_/ /
/_/ |_/_____/\____/ \____/\____/
/NEO-GO:/
2020-09-30T11:55:49.444Z INFO new peer connected {"addr": "172.23.0.5:39638", "peerCount": 1}
2020-09-30T11:55:49.444Z INFO new peer connected {"addr": "172.23.0.5:20333", "peerCount": 2}
2020-09-30T11:55:49.444Z WARN peer disconnected {"addr": "172.23.0.5:20333", "reason": "identical node id", "peerCount": 1}
2020-09-30T11:55:49.445Z WARN peer disconnected {"addr": "172.23.0.5:39638", "reason": "identical node id", "peerCount": 0}
2020-09-30T11:55:49.445Z INFO new peer connected {"addr": "172.23.0.3:20335", "peerCount": 1}
2020-09-30T11:55:49.445Z INFO new peer connected {"addr": "172.23.0.2:20334", "peerCount": 2}
2020-09-30T11:55:49.445Z INFO started protocol {"addr": "172.23.0.3:20335", "userAgent": "/NEO-GO:/", "startHeight": 3, "id": 1339919829}
2020-09-30T11:55:49.445Z INFO new peer connected {"addr": "172.23.0.4:20336", "peerCount": 3}
2020-09-30T11:55:49.445Z INFO started protocol {"addr": "172.23.0.4:20336", "userAgent": "/NEO-GO:/", "startHeight": 3, "id": 4036722359}
2020-09-30T11:55:49.445Z INFO node reached synchronized state, starting consensus
2020-09-30T11:55:49.445Z INFO started protocol {"addr": "172.23.0.2:20334", "userAgent": "/NEO-GO:/", "startHeight": 3, "id": 1557367037}
panic: runtime error: integer divide by zero
goroutine 132 [running]:
github.com/nspcc-dev/dbft.(*Context).GetPrimaryIndex(...)
github.com/nspcc-dev/dbft@v0.0.0-20200925163137-8f3b9ab3b720/context.go:83
github.com/nspcc-dev/dbft.(*Context).reset(0xc0000e0780, 0x0)
github.com/nspcc-dev/dbft@v0.0.0-20200925163137-8f3b9ab3b720/context.go:208 +0x64b
github.com/nspcc-dev/dbft.(*DBFT).InitializeConsensus(0xc0000e0780, 0x964800)
github.com/nspcc-dev/dbft@v0.0.0-20200925163137-8f3b9ab3b720/dbft.go:87 +0x51
github.com/nspcc-dev/dbft.(*DBFT).Start(0xc0000e0780)
github.com/nspcc-dev/dbft@v0.0.0-20200925163137-8f3b9ab3b720/dbft.go:81 +0x4b
github.com/nspcc-dev/neo-go/pkg/consensus.(*service).Start(0xc0001a2160)
github.com/nspcc-dev/neo-go/pkg/consensus/consensus.go:206 +0x56
github.com/nspcc-dev/neo-go/pkg/network.(*Server).tryStartConsensus(0xc0000ec500)
github.com/nspcc-dev/neo-go/pkg/network/server.go:311 +0xda
github.com/nspcc-dev/neo-go/pkg/network.(*Server).handleMessage(0xc0000ec500, 0x104d800, 0xc000222090, 0xc0000a6f10, 0x0, 0x0)
github.com/nspcc-dev/neo-go/pkg/network/server.go:781 +0xa7a
github.com/nspcc-dev/neo-go/pkg/network.(*TCPPeer).handleConn(0xc000222090)
github.com/nspcc-dev/neo-go/pkg/network/tcp_peer.go:162 +0x2e7
created by github.com/nspcc-dev/neo-go/pkg/network.(*TCPTransport).Dial
github.com/nspcc-dev/neo-go/pkg/network/tcp_transport.go:40 +0x1ac
```
This commit is contained in:
parent
6b201893fa
commit
eccf639803
2 changed files with 29 additions and 19 deletions
|
@ -253,6 +253,11 @@ func (bc *Blockchain) init() error {
|
|||
}
|
||||
}
|
||||
|
||||
err = bc.contracts.NEO.InitializeCache(bc, bc.dao)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't init cache for NEO native contract: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -204,6 +204,30 @@ func (n *NEO) Initialize(ic *interop.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// InitializeCache initializes all NEO cache with the proper values from storage.
|
||||
// Cache initialisation should be done apart from Initialize because Initialize is
|
||||
// called only when deploying native contracts.
|
||||
func (n *NEO) InitializeCache(bc blockchainer.Blockchainer, d dao.DAO) error {
|
||||
committee := keys.PublicKeys{}
|
||||
si := d.GetStorageItem(n.ContractID, prefixCommittee)
|
||||
if err := committee.DecodeBytes(si.Value); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := n.updateCache(committee, bc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var gr state.GASRecord
|
||||
si = d.GetStorageItem(n.ContractID, []byte{prefixGASPerBlock})
|
||||
if err := gr.FromBytes(si.Value); err != nil {
|
||||
return err
|
||||
}
|
||||
n.gasPerBlock.Store(gr)
|
||||
n.gasPerBlockChanged.Store(false)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NEO) updateCache(committee keys.PublicKeys, bc blockchainer.Blockchainer) error {
|
||||
n.committee.Store(committee)
|
||||
script, err := smartcontract.CreateMajorityMultiSigRedeemScript(committee.Copy())
|
||||
|
@ -247,25 +271,6 @@ func shouldUpdateCommittee(h uint32, bc blockchainer.Blockchainer) bool {
|
|||
|
||||
// OnPersist implements Contract interface.
|
||||
func (n *NEO) OnPersist(ic *interop.Context) error {
|
||||
gpb := n.gasPerBlockChanged.Load()
|
||||
if gpb == nil {
|
||||
committee := keys.PublicKeys{}
|
||||
si := ic.DAO.GetStorageItem(n.ContractID, prefixCommittee)
|
||||
if err := committee.DecodeBytes(si.Value); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := n.updateCache(committee, ic.Chain); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var gr state.GASRecord
|
||||
si = ic.DAO.GetStorageItem(n.ContractID, []byte{prefixGASPerBlock})
|
||||
if err := gr.FromBytes(si.Value); err != nil {
|
||||
return err
|
||||
}
|
||||
n.gasPerBlock.Store(gr)
|
||||
n.gasPerBlockChanged.Store(false)
|
||||
}
|
||||
if shouldUpdateCommittee(ic.Block.Index, ic.Chain) {
|
||||
if err := n.updateCommittee(ic); err != nil {
|
||||
return err
|
||||
|
|
Loading…
Reference in a new issue