Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(store): caching account and validator in store #513

Merged
merged 6 commits into from
Jun 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions execution/executor/sortition.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@ func (e *SortitionExecutor) joinCommittee(sb sandbox.Sandbox,
joiningPower := int64(0)
committee := sb.Committee()
currentHeight := sb.CurrentHeight()
sb.IterateValidators(func(vs *sandbox.ValidatorStatus) {
if vs.Validator.LastJoinedHeight() == currentHeight {
if !committee.Contains(vs.Validator.Address()) {
joiningPower += vs.Validator.Power()
sb.IterateValidators(func(val *validator.Validator, updated bool) {
if val.LastJoinedHeight() == currentHeight {
if !committee.Contains(val.Address()) {
joiningPower += val.Power()
joiningNum++
}
}
Expand Down
7 changes: 3 additions & 4 deletions execution/executor/sortition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (

"github.com/pactus-project/pactus/crypto"
"github.com/pactus-project/pactus/crypto/bls"
"github.com/pactus-project/pactus/sandbox"
"github.com/pactus-project/pactus/sortition"
"github.com/pactus-project/pactus/types/tx"
"github.com/pactus-project/pactus/types/validator"
Expand Down Expand Up @@ -211,9 +210,9 @@ func TestOldestDidNotPropose(t *testing.T) {
assert.NoError(t, exe.Execute(trx2, tSandbox))

joined := make([]*validator.Validator, 0)
tSandbox.IterateValidators(func(vs *sandbox.ValidatorStatus) {
if vs.Validator.LastJoinedHeight() == tSandbox.CurrentHeight() {
joined = append(joined, &vs.Validator)
tSandbox.IterateValidators(func(val *validator.Validator, updated bool) {
if val.LastJoinedHeight() == tSandbox.CurrentHeight() {
joined = append(joined, val)
}
})
tSandbox.TestCommittee.Update(0, joined)
Expand Down
4 changes: 2 additions & 2 deletions sandbox/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ type Sandbox interface {
Params() param.Params
CurrentHeight() uint32

IterateAccounts(consumer func(crypto.Address, *AccountStatus))
IterateValidators(consumer func(*ValidatorStatus))
IterateAccounts(consumer func(addr crypto.Address, acc *account.Account, updated bool))
IterateValidators(consumer func(val *validator.Validator, updated bool))
}
14 changes: 4 additions & 10 deletions sandbox/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,21 +81,15 @@ func (m *MockSandbox) Params() param.Params {
func (m *MockSandbox) RecentBlockByStamp(stamp hash.Stamp) (uint32, *block.Block) {
return m.TestStore.RecentBlockByStamp(stamp)
}
func (m *MockSandbox) IterateAccounts(consumer func(crypto.Address, *AccountStatus)) {
func (m *MockSandbox) IterateAccounts(consumer func(crypto.Address, *account.Account, bool)) {
m.TestStore.IterateAccounts(func(addr crypto.Address, acc *account.Account) bool {
consumer(addr, &AccountStatus{
Account: *acc,
Updated: true,
})
consumer(addr, acc, true)
return false
})
}
func (m *MockSandbox) IterateValidators(consumer func(*ValidatorStatus)) {
func (m *MockSandbox) IterateValidators(consumer func(*validator.Validator, bool)) {
m.TestStore.IterateValidators(func(val *validator.Validator) bool {
consumer(&ValidatorStatus{
Validator: *val,
Updated: true,
})
consumer(val, true)
return false
})
}
Expand Down
83 changes: 43 additions & 40 deletions sandbox/sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,21 @@ type sandbox struct {

store store.Reader
committee committee.Reader
accounts map[crypto.Address]*AccountStatus
validators map[crypto.Address]*ValidatorStatus
accounts map[crypto.Address]*sandboxAccount
validators map[crypto.Address]*sandboxValidator
params param.Params
totalAccounts int32
totalValidators int32
}

type ValidatorStatus struct {
Validator validator.Validator
Updated bool
type sandboxValidator struct {
validator *validator.Validator
updated bool
}

type AccountStatus struct {
Account account.Account
Updated bool
type sandboxAccount struct {
account *account.Account
updated bool
}

func NewSandbox(store store.Reader, params param.Params, committee committee.Reader) Sandbox {
Expand All @@ -47,8 +47,8 @@ func NewSandbox(store store.Reader, params param.Params, committee committee.Rea
params: params,
}

sb.accounts = make(map[crypto.Address]*AccountStatus)
sb.validators = make(map[crypto.Address]*ValidatorStatus)
sb.accounts = make(map[crypto.Address]*sandboxAccount)
sb.validators = make(map[crypto.Address]*sandboxValidator)
sb.totalAccounts = sb.store.TotalAccounts()
sb.totalValidators = sb.store.TotalValidators()

Expand Down Expand Up @@ -80,21 +80,20 @@ func (sb *sandbox) Account(addr crypto.Address) *account.Account {

s, ok := sb.accounts[addr]
if ok {
clone := new(account.Account)
*clone = s.Account
return clone
return s.account.Clone()
}

acc, err := sb.store.Account(addr)
if err != nil {
return nil
}
sb.accounts[addr] = &AccountStatus{
Account: *acc,
sb.accounts[addr] = &sandboxAccount{
account: acc,
}

return acc
return acc.Clone()
}

func (sb *sandbox) MakeNewAccount(addr crypto.Address) *account.Account {
sb.lk.Lock()
defer sb.lk.Unlock()
Expand All @@ -104,14 +103,17 @@ func (sb *sandbox) MakeNewAccount(addr crypto.Address) *account.Account {
}

acc := account.NewAccount(sb.totalAccounts)
sb.accounts[addr] = &AccountStatus{
Account: *acc,
Updated: true,
sb.accounts[addr] = &sandboxAccount{
account: acc,
updated: true,
}
sb.totalAccounts++
return acc
return acc.Clone()
}

// This function takes ownership of the account pointer.
// It is important that the caller should not modify the account data and
// keep it immutable.
func (sb *sandbox) UpdateAccount(addr crypto.Address, acc *account.Account) {
sb.lk.Lock()
defer sb.lk.Unlock()
Expand All @@ -120,8 +122,8 @@ func (sb *sandbox) UpdateAccount(addr crypto.Address, acc *account.Account) {
if !ok {
sb.shouldPanicForUnknownAddress()
}
s.Account = *acc
s.Updated = true
s.account = acc
s.updated = true
}

func (sb *sandbox) Validator(addr crypto.Address) *validator.Validator {
Expand All @@ -130,19 +132,17 @@ func (sb *sandbox) Validator(addr crypto.Address) *validator.Validator {

s, ok := sb.validators[addr]
if ok {
clone := new(validator.Validator)
*clone = s.Validator
return clone
return s.validator.Clone()
}

val, err := sb.store.Validator(addr)
if err != nil {
return nil
}
sb.validators[addr] = &ValidatorStatus{
Validator: *val,
sb.validators[addr] = &sandboxValidator{
validator: val,
}
return val
return val.Clone()
}

func (sb *sandbox) MakeNewValidator(pub *bls.PublicKey) *validator.Validator {
Expand All @@ -155,14 +155,17 @@ func (sb *sandbox) MakeNewValidator(pub *bls.PublicKey) *validator.Validator {
}

val := validator.NewValidator(pub, sb.totalValidators)
sb.validators[addr] = &ValidatorStatus{
Validator: *val,
Updated: true,
sb.validators[addr] = &sandboxValidator{
validator: val,
updated: true,
}
sb.totalValidators++
return val
return val.Clone()
}

// This function takes ownership of the validator pointer.
// It is important that the caller should not modify the validator data and
// keep it immutable.
func (sb *sandbox) UpdateValidator(val *validator.Validator) {
sb.lk.Lock()
defer sb.lk.Unlock()
Expand All @@ -173,8 +176,8 @@ func (sb *sandbox) UpdateValidator(val *validator.Validator) {
sb.shouldPanicForUnknownAddress()
}

s.Validator = *val
s.Updated = true
s.validator = val
s.updated = true
}

func (sb *sandbox) Params() param.Params {
Expand All @@ -194,21 +197,21 @@ func (sb *sandbox) currentHeight() uint32 {
return h + 1
}

func (sb *sandbox) IterateAccounts(consumer func(crypto.Address, *AccountStatus)) {
func (sb *sandbox) IterateAccounts(consumer func(crypto.Address, *account.Account, bool)) {
sb.lk.RLock()
defer sb.lk.RUnlock()

for addr, as := range sb.accounts {
consumer(addr, as)
for addr, sa := range sb.accounts {
consumer(addr, sa.account, sa.updated)
}
}

func (sb *sandbox) IterateValidators(consumer func(*ValidatorStatus)) {
func (sb *sandbox) IterateValidators(consumer func(*validator.Validator, bool)) {
sb.lk.RLock()
defer sb.lk.RUnlock()

for _, vs := range sb.validators {
consumer(vs)
for _, sv := range sb.validators {
consumer(sv.validator, sv.updated)
}
}

Expand Down
Loading