Skip to content

Commit

Permalink
fix: get recent blocks by stamp (#509)
Browse files Browse the repository at this point in the history
* fix: get recent blocks by stamp

* chore: updating store mock
  • Loading branch information
vlasfama authored Jun 15, 2023
1 parent d0474b1 commit fd9e749
Show file tree
Hide file tree
Showing 11 changed files with 80 additions and 176 deletions.
4 changes: 2 additions & 2 deletions execution/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (exe *Execution) checkLockTime(trx *tx.Tx, sb sandbox.Sandbox) error {

func (exe *Execution) checkStamp(trx *tx.Tx, sb sandbox.Sandbox) error {
curHeight := sb.CurrentHeight()
height, ok := sb.FindBlockHeightByStamp(trx.Stamp())
height, _ := sb.RecentBlockByStamp(trx.Stamp())
interval := sb.Params().TransactionToLiveInterval

if trx.IsSubsidyTx() {
Expand All @@ -109,7 +109,7 @@ func (exe *Execution) checkStamp(trx *tx.Tx, sb sandbox.Sandbox) error {
interval = sb.Params().SortitionInterval
}

if !ok || curHeight-height > interval {
if curHeight-height > interval {
return errors.Errorf(errors.ErrInvalidTx, "invalid stamp")
}

Expand Down
4 changes: 2 additions & 2 deletions sandbox/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/pactus-project/pactus/crypto/hash"
"github.com/pactus-project/pactus/sortition"
"github.com/pactus-project/pactus/types/account"
"github.com/pactus-project/pactus/types/block"
"github.com/pactus-project/pactus/types/param"
"github.com/pactus-project/pactus/types/validator"
)
Expand All @@ -22,8 +23,7 @@ type Sandbox interface {

VerifyProof(hash.Stamp, sortition.Proof, *validator.Validator) bool
Committee() committee.Reader
FindBlockHashByStamp(stamp hash.Stamp) (hash.Hash, bool)
FindBlockHeightByStamp(stamp hash.Stamp) (uint32, bool)
RecentBlockByStamp(stamp hash.Stamp) (uint32, *block.Block)

Params() param.Params
CurrentHeight() uint32
Expand Down
8 changes: 3 additions & 5 deletions sandbox/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/pactus-project/pactus/sortition"
"github.com/pactus-project/pactus/store"
"github.com/pactus-project/pactus/types/account"
"github.com/pactus-project/pactus/types/block"
"github.com/pactus-project/pactus/types/param"
"github.com/pactus-project/pactus/types/validator"
)
Expand Down Expand Up @@ -77,11 +78,8 @@ func (m *MockSandbox) CurrentHeight() uint32 {
func (m *MockSandbox) Params() param.Params {
return m.TestParams
}
func (m *MockSandbox) FindBlockHashByStamp(stamp hash.Stamp) (hash.Hash, bool) {
return m.TestStore.FindBlockHashByStamp(stamp)
}
func (m *MockSandbox) FindBlockHeightByStamp(stamp hash.Stamp) (uint32, bool) {
return m.TestStore.FindBlockHeightByStamp(stamp)
func (m *MockSandbox) RecentBlockByStamp(stamp hash.Stamp) (uint32, *block.Block) {
return m.TestStore.RecentBlockByStamp(stamp)
}
func (m *MockSandbox) IterateAccounts(consumer func(crypto.Address, *AccountStatus)) {
m.TestStore.IterateAccounts(func(addr crypto.Address, acc *account.Account) bool {
Expand Down
25 changes: 6 additions & 19 deletions sandbox/sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/pactus-project/pactus/sortition"
"github.com/pactus-project/pactus/store"
"github.com/pactus-project/pactus/types/account"
"github.com/pactus-project/pactus/types/block"
"github.com/pactus-project/pactus/types/param"
"github.com/pactus-project/pactus/types/validator"
"github.com/pactus-project/pactus/util/logger"
Expand Down Expand Up @@ -211,18 +212,8 @@ func (sb *sandbox) IterateValidators(consumer func(*ValidatorStatus)) {
}
}

func (sb *sandbox) FindBlockHashByStamp(stamp hash.Stamp) (hash.Hash, bool) {
sb.lk.RLock()
defer sb.lk.RUnlock()

return sb.store.FindBlockHashByStamp(stamp)
}

func (sb *sandbox) FindBlockHeightByStamp(stamp hash.Stamp) (uint32, bool) {
sb.lk.RLock()
defer sb.lk.RUnlock()

return sb.store.FindBlockHeightByStamp(stamp)
func (sb *sandbox) RecentBlockByStamp(stamp hash.Stamp) (uint32, *block.Block) {
return sb.store.RecentBlockByStamp(stamp)
}

func (sb *sandbox) Committee() committee.Reader {
Expand All @@ -232,15 +223,11 @@ func (sb *sandbox) Committee() committee.Reader {
// TODO: write test for me.
// VerifyProof verifies proof of a sortition transaction.
func (sb *sandbox) VerifyProof(stamp hash.Stamp, proof sortition.Proof, val *validator.Validator) bool {
height, ok := sb.store.FindBlockHeightByStamp(stamp)
if !ok {
return false
}
storedBlock, err := sb.store.Block(height)
if err != nil {
_, b := sb.store.RecentBlockByStamp(stamp)
if b == nil {
return false
}
seed := storedBlock.ToBlock().Header().SortitionSeed()
seed := b.Header().SortitionSeed()
total := int64(0) // TODO: we can get it from state
sb.store.IterateValidators(func(val *validator.Validator) bool {
total += val.Power()
Expand Down
28 changes: 7 additions & 21 deletions sandbox/sandbox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,30 +326,16 @@ func TestDeepCopy(t *testing.T) {
assert.NotEqual(t, val2.Hash(), val3.Validator.Hash())
}

func TestBlockHeightByStamp(t *testing.T) {
func TestRecentBlockByStamp(t *testing.T) {
setup(t)

height, ok := tSandbox.FindBlockHeightByStamp(hash.GenerateTestStamp())
assert.Zero(t, height)
assert.False(t, ok)
h, b := tSandbox.RecentBlockByStamp(hash.GenerateTestStamp())
assert.Zero(t, h)
assert.Nil(t, b)

lastHeight, _ := tStore.LastCertificate()
lastHash := tSandbox.store.BlockHash(lastHeight)
height, ok = tSandbox.FindBlockHeightByStamp(lastHash.Stamp())
assert.Equal(t, height, lastHeight)
assert.True(t, ok)
}

func TestBlockHashByStamp(t *testing.T) {
setup(t)

h, ok := tSandbox.FindBlockHashByStamp(hash.GenerateTestStamp())
assert.True(t, h.IsUndef())
assert.False(t, ok)

lastHeight, _ := tStore.LastCertificate()
lastHash := tSandbox.store.BlockHash(lastHeight)
h, ok = tSandbox.FindBlockHashByStamp(lastHash.Stamp())
assert.True(t, h.EqualsTo(lastHash))
assert.True(t, ok)
h, b = tSandbox.RecentBlockByStamp(lastHash.Stamp())
assert.Equal(t, h, lastHeight)
assert.Equal(t, b.Hash(), lastHash)
}
1 change: 0 additions & 1 deletion store/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ func newAccountStore(db *leveldb.DB) *accountStore {
as := &accountStore{
db: db,
}
// TODO: better way to get total accout number?
total := int32(0)
as.iterateAccounts(func(_ crypto.Address, _ *account.Account) bool {
total++
Expand Down
2 changes: 1 addition & 1 deletion store/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (bs *blockStore) block(height uint32) ([]byte, error) {
return data, nil
}

func (bs *blockStore) BlockHeight(hash hash.Hash) uint32 {
func (bs *blockStore) blockHeight(hash hash.Hash) uint32 {
data, err := tryGet(bs.db, blockHashKey(hash))
if err != nil {
return 0
Expand Down
5 changes: 1 addition & 4 deletions store/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,7 @@ type Reader interface {
Block(height uint32) (*StoredBlock, error)
BlockHeight(hash hash.Hash) uint32
BlockHash(height uint32) hash.Hash
// It only remembers most recent stamps
FindBlockHashByStamp(stamp hash.Stamp) (hash.Hash, bool)
// It only remembers most recent stamps
FindBlockHeightByStamp(stamp hash.Stamp) (uint32, bool)
RecentBlockByStamp(stamp hash.Stamp) (uint32, *block.Block)
Transaction(id tx.ID) (*StoredTx, error)
HasAccount(crypto.Address) bool
Account(addr crypto.Address) (*account.Account, error)
Expand Down
23 changes: 4 additions & 19 deletions store/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,29 +150,14 @@ func (m *MockStore) LastCertificate() (uint32, *block.Certificate) {
}
return m.LastHeight, m.LastCert
}
func (m *MockStore) FindBlockHashByStamp(stamp hash.Stamp) (hash.Hash, bool) {
if stamp.EqualsTo(hash.UndefHash.Stamp()) {
return hash.UndefHash, true
}
for _, b := range m.Blocks {
if b.Stamp().EqualsTo(stamp) {
return b.Hash(), true
}
}

return hash.UndefHash, false
}
func (m *MockStore) FindBlockHeightByStamp(stamp hash.Stamp) (uint32, bool) {
if stamp.EqualsTo(hash.UndefHash.Stamp()) {
return 0, true
}
for i, b := range m.Blocks {
func (m *MockStore) RecentBlockByStamp(stamp hash.Stamp) (uint32, *block.Block) {
for h, b := range m.Blocks {
if b.Stamp().EqualsTo(stamp) {
return i, true
return h, &b
}
}

return 0, false
return 0, nil
}
func (m *MockStore) WriteBatch() error {
return nil
Expand Down
58 changes: 21 additions & 37 deletions store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ func tryGet(db *leveldb.DB, key []byte) ([]byte, error) {
return data, nil
}

type hashPair struct {
type blockHeightPair struct {
Height uint32
Hash hash.Hash
Block *block.Block
}

type store struct {
Expand All @@ -57,7 +57,7 @@ type store struct {
txStore *txStore
accountStore *accountStore
validatorStore *validatorStore
stampLookup *linkedmap.LinkedMap[hash.Stamp, hashPair]
stampLookup *linkedmap.LinkedMap[hash.Stamp, blockHeightPair]
}

func NewStore(conf *Config, stampLookupCapacity int) (Store, error) {
Expand All @@ -69,7 +69,7 @@ func NewStore(conf *Config, stampLookupCapacity int) (Store, error) {
if err != nil {
return nil, err
}

stampLookup := linkedmap.NewLinkedMap[hash.Stamp, blockHeightPair](stampLookupCapacity)
s := &store{
config: conf,
db: db,
Expand All @@ -78,32 +78,35 @@ func NewStore(conf *Config, stampLookupCapacity int) (Store, error) {
txStore: newTxStore(db),
accountStore: newAccountStore(db),
validatorStore: newValidatorStore(db),
stampLookup: linkedmap.NewLinkedMap[hash.Stamp, hashPair](stampLookupCapacity),
stampLookup: stampLookup,
}

lastHeight, _ := s.LastCertificate()
height := uint32(0)
height := uint32(1)
if lastHeight > uint32(stampLookupCapacity) {
height = lastHeight - uint32(stampLookupCapacity)
}
for ; height <= lastHeight; height++ {
hash := s.BlockHash(height)
s.appendStamp(hash, height)
storedBlock, _ := s.Block(height)
s.updateStampLookup(height, storedBlock.ToBlock())
}

return s, nil
}

func (s *store) Close() error {
s.lk.Lock()
defer s.lk.Unlock()

return s.db.Close()
}

func (s *store) appendStamp(hash hash.Hash, height uint32) {
pair := hashPair{
func (s *store) updateStampLookup(height uint32, block *block.Block) {
pair := blockHeightPair{
Height: height,
Hash: hash,
Block: block,
}
s.stampLookup.PushBack(hash.Stamp(), pair)
s.stampLookup.PushBack(block.Stamp(), pair)
}

func (s *store) SaveBlock(height uint32, block *block.Block, cert *block.Certificate) {
Expand All @@ -128,8 +131,8 @@ func (s *store) SaveBlock(height uint32, block *block.Block, cert *block.Certifi

s.batch.Put(lastInfoKey, w.Bytes())

// Update stamp to height lookup
s.appendStamp(block.Hash(), height)
// Update stamp lookup
s.updateStampLookup(height, block)
}

func (s *store) Block(height uint32) (*StoredBlock, error) {
Expand Down Expand Up @@ -157,7 +160,7 @@ func (s *store) BlockHeight(hash hash.Hash) uint32 {
s.lk.Lock()
defer s.lk.Unlock()

return s.blockStore.BlockHeight(hash)
return s.blockStore.blockHeight(hash)
}

func (s *store) BlockHash(height uint32) hash.Hash {
Expand All @@ -173,34 +176,15 @@ func (s *store) BlockHash(height uint32) hash.Hash {
return hash.UndefHash
}

func (s *store) FindBlockHashByStamp(stamp hash.Stamp) (hash.Hash, bool) {
func (s *store) RecentBlockByStamp(stamp hash.Stamp) (uint32, *block.Block) {
s.lk.RLock()
defer s.lk.RUnlock()

if stamp.EqualsTo(hash.UndefHash.Stamp()) {
return hash.UndefHash, true
}

n := s.stampLookup.GetNode(stamp)
if n != nil {
return n.Data.Value.Hash, true
}
return hash.UndefHash, false
}

func (s *store) FindBlockHeightByStamp(stamp hash.Stamp) (uint32, bool) {
s.lk.RLock()
defer s.lk.RUnlock()

if stamp.EqualsTo(hash.UndefHash.Stamp()) {
return 0, true
}

n := s.stampLookup.GetNode(stamp)
if n != nil {
return n.Data.Value.Height, true
return n.Data.Value.Height, n.Data.Value.Block
}
return 0, false
return 0, nil
}

func (s *store) Transaction(id tx.ID) (*StoredTx, error) {
Expand Down
Loading

0 comments on commit fd9e749

Please sign in to comment.