core: don't reset NEO's gasPerBlock cache
This commit is contained in:
parent
35d160075d
commit
adec635f0e
3 changed files with 23 additions and 27 deletions
|
@ -41,10 +41,8 @@ type NEO struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type NeoCache struct {
|
type NeoCache struct {
|
||||||
// gasPerBlock represents current value of generated gas per block.
|
// gasPerBlock represents the history of generated gas per block.
|
||||||
// It is append-only and doesn't need to be copied when used.
|
|
||||||
gasPerBlock gasRecord
|
gasPerBlock gasRecord
|
||||||
gasPerBlockChanged bool
|
|
||||||
|
|
||||||
registerPrice int64
|
registerPrice int64
|
||||||
registerPriceChanged bool
|
registerPriceChanged bool
|
||||||
|
@ -131,7 +129,9 @@ func copyNeoCache(src, dst *NeoCache) {
|
||||||
dst.registerPriceChanged = src.registerPriceChanged
|
dst.registerPriceChanged = src.registerPriceChanged
|
||||||
dst.registerPrice = src.registerPrice
|
dst.registerPrice = src.registerPrice
|
||||||
|
|
||||||
dst.gasPerBlockChanged = src.gasPerBlockChanged
|
// Can't omit copying because gasPerBlock is append-only, thus to be able to
|
||||||
|
// discard cache changes in case of FAULTed transaction we need a separate
|
||||||
|
// container for updated gasPerBlock values.
|
||||||
dst.gasPerBlock = make(gasRecord, len(src.gasPerBlock))
|
dst.gasPerBlock = make(gasRecord, len(src.gasPerBlock))
|
||||||
copy(dst.gasPerBlock, src.gasPerBlock)
|
copy(dst.gasPerBlock, src.gasPerBlock)
|
||||||
|
|
||||||
|
@ -271,7 +271,6 @@ func (n *NEO) Initialize(ic *interop.Context) error {
|
||||||
|
|
||||||
gr := &gasRecord{{Index: index, GASPerBlock: *value}}
|
gr := &gasRecord{{Index: index, GASPerBlock: *value}}
|
||||||
cache.gasPerBlock = *gr
|
cache.gasPerBlock = *gr
|
||||||
cache.gasPerBlockChanged = false
|
|
||||||
ic.DAO.PutStorageItem(n.ID, []byte{prefixVotersCount}, state.StorageItem{})
|
ic.DAO.PutStorageItem(n.ID, []byte{prefixVotersCount}, state.StorageItem{})
|
||||||
|
|
||||||
setIntWithKey(n.ID, ic.DAO, []byte{prefixRegisterPrice}, DefaultRegisterPrice)
|
setIntWithKey(n.ID, ic.DAO, []byte{prefixRegisterPrice}, DefaultRegisterPrice)
|
||||||
|
@ -301,7 +300,6 @@ func (n *NEO) InitializeCache(bc interop.Ledger, d *dao.Simple) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.gasPerBlock = n.getSortedGASRecordFromDAO(d)
|
cache.gasPerBlock = n.getSortedGASRecordFromDAO(d)
|
||||||
cache.gasPerBlockChanged = false
|
|
||||||
|
|
||||||
d.Store.SetCache(n.ID, cache)
|
d.Store.SetCache(n.ID, cache)
|
||||||
return nil
|
return nil
|
||||||
|
@ -417,10 +415,6 @@ func (n *NEO) PostPersist(ic *interop.Context) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if cache.gasPerBlockChanged {
|
|
||||||
cache.gasPerBlock = n.getSortedGASRecordFromDAO(ic.DAO)
|
|
||||||
cache.gasPerBlockChanged = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if cache.registerPriceChanged {
|
if cache.registerPriceChanged {
|
||||||
p := getIntWithKey(n.ID, ic.DAO, []byte{prefixRegisterPrice})
|
p := getIntWithKey(n.ID, ic.DAO, []byte{prefixRegisterPrice})
|
||||||
|
@ -549,19 +543,14 @@ func (n *NEO) getSortedGASRecordFromDAO(d *dao.Simple) gasRecord {
|
||||||
// GetGASPerBlock returns gas generated for block with provided index.
|
// GetGASPerBlock returns gas generated for block with provided index.
|
||||||
func (n *NEO) GetGASPerBlock(d *dao.Simple, index uint32) *big.Int {
|
func (n *NEO) GetGASPerBlock(d *dao.Simple, index uint32) *big.Int {
|
||||||
cache := d.Store.GetROCache(n.ID).(*NeoCache)
|
cache := d.Store.GetROCache(n.ID).(*NeoCache)
|
||||||
var gr gasRecord
|
gr := cache.gasPerBlock
|
||||||
if cache.gasPerBlockChanged {
|
|
||||||
gr = n.getSortedGASRecordFromDAO(d)
|
|
||||||
} else {
|
|
||||||
gr = cache.gasPerBlock
|
|
||||||
}
|
|
||||||
for i := len(gr) - 1; i >= 0; i-- {
|
for i := len(gr) - 1; i >= 0; i-- {
|
||||||
if gr[i].Index <= index {
|
if gr[i].Index <= index {
|
||||||
g := gr[i].GASPerBlock
|
g := gr[i].GASPerBlock
|
||||||
return &g
|
return &g
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic("contract not initialized")
|
panic("NEO cache not initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCommitteeAddress returns address of the committee.
|
// GetCommitteeAddress returns address of the committee.
|
||||||
|
@ -595,9 +584,12 @@ func (n *NEO) SetGASPerBlock(ic *interop.Context, index uint32, gas *big.Int) er
|
||||||
if !n.checkCommittee(ic) {
|
if !n.checkCommittee(ic) {
|
||||||
return errors.New("invalid committee signature")
|
return errors.New("invalid committee signature")
|
||||||
}
|
}
|
||||||
cache := ic.DAO.Store.GetRWCache(n.ID).(*NeoCache)
|
|
||||||
cache.gasPerBlockChanged = true
|
|
||||||
n.putGASRecord(ic.DAO, index, gas)
|
n.putGASRecord(ic.DAO, index, gas)
|
||||||
|
cache := ic.DAO.Store.GetRWCache(n.ID).(*NeoCache)
|
||||||
|
cache.gasPerBlock = append(cache.gasPerBlock, gasIndexPair{
|
||||||
|
Index: index,
|
||||||
|
GASPerBlock: *gas,
|
||||||
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,13 +685,8 @@ func (n *NEO) CalculateNEOHolderReward(d *dao.Simple, value *big.Int, start, end
|
||||||
} else if value.Sign() < 0 {
|
} else if value.Sign() < 0 {
|
||||||
return nil, errors.New("negative value")
|
return nil, errors.New("negative value")
|
||||||
}
|
}
|
||||||
var gr gasRecord
|
|
||||||
cache := d.Store.GetROCache(n.ID).(*NeoCache)
|
cache := d.Store.GetROCache(n.ID).(*NeoCache)
|
||||||
if !cache.gasPerBlockChanged {
|
gr := cache.gasPerBlock
|
||||||
gr = cache.gasPerBlock
|
|
||||||
} else {
|
|
||||||
gr = n.getSortedGASRecordFromDAO(d)
|
|
||||||
}
|
|
||||||
var sum, tmp big.Int
|
var sum, tmp big.Int
|
||||||
for i := len(gr) - 1; i >= 0; i-- {
|
for i := len(gr) - 1; i >= 0; i-- {
|
||||||
if gr[i].Index >= end {
|
if gr[i].Index >= end {
|
||||||
|
|
|
@ -104,7 +104,12 @@ func testGetSetCache(t *testing.T, c *neotest.ContractInvoker, name string, defa
|
||||||
tx2 = committeeInvoker.PrepareInvoke(t, getName)
|
tx2 = committeeInvoker.PrepareInvoke(t, getName)
|
||||||
committeeInvoker.AddNewBlock(t, tx1, tx2)
|
committeeInvoker.AddNewBlock(t, tx1, tx2)
|
||||||
committeeInvoker.CheckHalt(t, tx1.Hash())
|
committeeInvoker.CheckHalt(t, tx1.Hash())
|
||||||
|
if name != "GasPerBlock" {
|
||||||
committeeInvoker.CheckHalt(t, tx2.Hash(), stackitem.Make(newVal))
|
committeeInvoker.CheckHalt(t, tx2.Hash(), stackitem.Make(newVal))
|
||||||
|
} else {
|
||||||
|
committeeInvoker.CheckHalt(t, tx2.Hash(), stackitem.Make(defaultValue))
|
||||||
|
committeeInvoker.Invoke(t, newVal, getName)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setNodesByRole(t *testing.T, designateInvoker *neotest.ContractInvoker, ok bool, r noderoles.Role, nodes keys.PublicKeys) {
|
func setNodesByRole(t *testing.T, designateInvoker *neotest.ContractInvoker, ok bool, r noderoles.Role, nodes keys.PublicKeys) {
|
||||||
|
|
|
@ -42,6 +42,10 @@ func TestNEO_GasPerBlock(t *testing.T) {
|
||||||
testGetSet(t, newNeoCommitteeClient(t, 100_0000_0000), "GasPerBlock", 5*native.GASFactor, 0, 10*native.GASFactor)
|
testGetSet(t, newNeoCommitteeClient(t, 100_0000_0000), "GasPerBlock", 5*native.GASFactor, 0, 10*native.GASFactor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNEO_GasPerBlockCache(t *testing.T) {
|
||||||
|
testGetSetCache(t, newNeoCommitteeClient(t, 100_0000_0000), "GasPerBlock", 5*native.GASFactor)
|
||||||
|
}
|
||||||
|
|
||||||
func TestNEO_RegisterPrice(t *testing.T) {
|
func TestNEO_RegisterPrice(t *testing.T) {
|
||||||
testGetSet(t, newNeoCommitteeClient(t, 100_0000_0000), "RegisterPrice", native.DefaultRegisterPrice, 1, math.MaxInt64)
|
testGetSet(t, newNeoCommitteeClient(t, 100_0000_0000), "RegisterPrice", native.DefaultRegisterPrice, 1, math.MaxInt64)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue