Merge pull request #720 from nspcc-dev/fix-keycache-concurrent-access

core: protect (*Blockchain).keyCache with a lock
This commit is contained in:
Roman Khimov 2020-03-05 11:46:23 +03:00 committed by GitHub
commit 2032dd8e9f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -110,6 +110,8 @@ type Blockchain struct {
memPool mempool.Pool memPool mempool.Pool
// This lock protects concurrent access to keyCache.
keyCacheLock sync.RWMutex
// cache for block verification keys. // cache for block verification keys.
keyCache map[util.Uint160]map[string]*keys.PublicKey keyCache map[util.Uint160]map[string]*keys.PublicKey
@ -1846,8 +1848,12 @@ func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transa
vm.SetCheckedHash(checkedHash.BytesBE()) vm.SetCheckedHash(checkedHash.BytesBE())
vm.LoadScript(verification) vm.LoadScript(verification)
vm.LoadScript(witness.InvocationScript) vm.LoadScript(witness.InvocationScript)
if useKeys && bc.keyCache[hash] != nil { if useKeys {
vm.SetPublicKeys(bc.keyCache[hash]) bc.keyCacheLock.RLock()
if bc.keyCache[hash] != nil {
vm.SetPublicKeys(bc.keyCache[hash])
}
bc.keyCacheLock.RUnlock()
} }
err = vm.Run() err = vm.Run()
if vm.HasFailed() { if vm.HasFailed() {
@ -1862,8 +1868,15 @@ func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transa
if !res { if !res {
return errors.Errorf("signature check failed") return errors.Errorf("signature check failed")
} }
if useKeys && bc.keyCache[hash] == nil { if useKeys {
bc.keyCache[hash] = vm.GetPublicKeys() bc.keyCacheLock.RLock()
_, ok := bc.keyCache[hash]
bc.keyCacheLock.RUnlock()
if !ok {
bc.keyCacheLock.Lock()
bc.keyCache[hash] = vm.GetPublicKeys()
bc.keyCacheLock.Unlock()
}
} }
} else { } else {
return errors.Errorf("no result returned from the script") return errors.Errorf("no result returned from the script")