native: add NEP-11 tracking to management contract

This commit is contained in:
Roman Khimov 2021-11-16 13:28:59 +03:00
parent 965c3b2c13
commit 3b08b5b19b

View file

@ -33,6 +33,8 @@ type Management struct {
mtx sync.RWMutex
contracts map[util.Uint160]*state.Contract
// nep11 is a map of NEP11-compliant contracts which is updated with every PostPersist.
nep11 map[util.Uint160]struct{}
// nep17 is a map of NEP17-compliant contracts which is updated with every PostPersist.
nep17 map[util.Uint160]struct{}
}
@ -65,6 +67,7 @@ func newManagement() *Management {
var m = &Management{
ContractMD: *interop.NewContractMD(nativenames.Management, ManagementContractID),
contracts: make(map[util.Uint160]*state.Contract),
nep11: make(map[util.Uint160]struct{}),
nep17: make(map[util.Uint160]struct{}),
}
defer m.UpdateHash()
@ -453,6 +456,18 @@ func (m *Management) Metadata() *interop.ContractMD {
return &m.ContractMD
}
// updateContractCache saves contract in the common and NEP-related caches. It's
// an internal method that must be called with m.mtx lock taken.
func (m *Management) updateContractCache(cs *state.Contract) {
m.contracts[cs.Hash] = cs
if cs.Manifest.IsStandardSupported(manifest.NEP11StandardName) {
m.nep11[cs.Hash] = struct{}{}
}
if cs.Manifest.IsStandardSupported(manifest.NEP17StandardName) {
m.nep17[cs.Hash] = struct{}{}
}
}
// OnPersist implements Contract interface.
func (m *Management) OnPersist(ic *interop.Context) error {
for _, native := range ic.Natives {
@ -473,10 +488,7 @@ func (m *Management) OnPersist(ic *interop.Context) error {
return fmt.Errorf("initializing %s native contract: %w", md.Name, err)
}
m.mtx.Lock()
m.contracts[md.Hash] = cs
if md.Manifest.IsStandardSupported(manifest.NEP17StandardName) {
m.nep17[md.Hash] = struct{}{}
}
m.updateContractCache(cs)
m.mtx.Unlock()
}
@ -497,10 +509,7 @@ func (m *Management) InitializeCache(d dao.DAO) error {
if initErr != nil {
return
}
m.contracts[cs.Hash] = cs
if cs.Manifest.IsStandardSupported(manifest.NEP17StandardName) {
m.nep17[cs.Hash] = struct{}{}
}
m.updateContractCache(cs)
})
return initErr
}
@ -512,24 +521,33 @@ func (m *Management) PostPersist(ic *interop.Context) error {
if cs != nil {
continue
}
delete(m.nep11, h)
delete(m.nep17, h)
newCs, err := m.getContractFromDAO(ic.DAO, h)
if err != nil {
// Contract was destroyed.
delete(m.contracts, h)
delete(m.nep17, h)
continue
}
m.contracts[h] = newCs
if newCs.Manifest.IsStandardSupported(manifest.NEP17StandardName) {
m.nep17[h] = struct{}{}
} else {
delete(m.nep17, h)
}
m.updateContractCache(newCs)
}
m.mtx.Unlock()
return nil
}
// GetNEP11Contracts returns hashes of all deployed contracts that support NEP-11 standard. The list
// is updated every PostPersist, so until PostPersist is called, the result for the previous block
// is returned.
func (m *Management) GetNEP11Contracts() []util.Uint160 {
m.mtx.RLock()
result := make([]util.Uint160, 0, len(m.nep11))
for h := range m.nep11 {
result = append(result, h)
}
m.mtx.RUnlock()
return result
}
// GetNEP17Contracts returns hashes of all deployed contracts that support NEP17 standard. The list
// is updated every PostPersist, so until PostPersist is called, the result for the previous block
// is returned.