Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
return empty result when contract not deployed
Browse files Browse the repository at this point in the history
envestcc committed Aug 27, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 66edd61 commit d1fc3ab
Showing 4 changed files with 175 additions and 44 deletions.
28 changes: 28 additions & 0 deletions blockindex/contractstaking/indexer.go
Original file line number Diff line number Diff line change
@@ -81,36 +81,57 @@ func (s *Indexer) StartHeight() uint64 {

// CandidateVotes returns the candidate votes
func (s *Indexer) CandidateVotes(candidate address.Address, height uint64) (*big.Int, error) {
if s.isIgnored(height) {
return big.NewInt(0), nil
}
return s.cache.CandidateVotes(candidate, height)
}

// Buckets returns the buckets
func (s *Indexer) Buckets(height uint64) ([]*Bucket, error) {
if s.isIgnored(height) {
return []*Bucket{}, nil
}
return s.cache.Buckets(height)
}

// Bucket returns the bucket
func (s *Indexer) Bucket(id uint64, height uint64) (*Bucket, bool, error) {
if s.isIgnored(height) {
return nil, false, nil
}
return s.cache.Bucket(id, height)
}

// BucketsByIndices returns the buckets by indices
func (s *Indexer) BucketsByIndices(indices []uint64, height uint64) ([]*Bucket, error) {
if s.isIgnored(height) {
return []*Bucket{}, nil
}
return s.cache.BucketsByIndices(indices, height)
}

// BucketsByCandidate returns the buckets by candidate
func (s *Indexer) BucketsByCandidate(candidate address.Address, height uint64) ([]*Bucket, error) {
if s.isIgnored(height) {
return []*Bucket{}, nil
}
return s.cache.BucketsByCandidate(candidate, height)
}

// TotalBucketCount returns the total bucket count including active and burnt buckets
func (s *Indexer) TotalBucketCount(height uint64) (uint64, error) {
if s.isIgnored(height) {
return 0, nil
}
return s.cache.TotalBucketCount(height)
}

// BucketTypes returns the active bucket types
func (s *Indexer) BucketTypes(height uint64) ([]*BucketType, error) {
if s.isIgnored(height) {
return []*BucketType{}, nil
}
btMap, err := s.cache.ActiveBucketTypes(height)
if err != nil {
return nil, err
@@ -185,3 +206,10 @@ func (s *Indexer) reloadCache() error {
func (s *Indexer) loadFromDB() error {
return s.cache.LoadFromDB(s.kvstore)
}

// isIgnored returns true if before cotractDeployHeight.
// it aims to be compatible with blocks between feature hard-fork and contract deployed
// read interface should return empty result instead of invalid height error if it returns true
func (s *Indexer) isIgnored(height uint64) bool {
return height < s.contractDeployHeight
}
76 changes: 57 additions & 19 deletions blockindex/contractstaking/indexer_test.go
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ package contractstaking
import (
"context"
"math/big"
"strconv"
"sync"
"testing"
"time"
@@ -916,29 +917,66 @@ func TestContractStakingIndexerVotes(t *testing.T) {
r.NoError(err)
r.Len(bts, 6)
})
}

t.Run("heightRestriction", func(t *testing.T) {
cases := []struct {
height uint64
valid bool
}{
{0, true},
{height - 1, true},
{height, true},
{height + 1, false},
}
for i := range cases {
h := cases[i].height
if cases[i].valid {
func TestIndexer_ReadHeightRestriction(t *testing.T) {
r := require.New(t)

cases := []struct {
startHeight uint64
height uint64
readHeight uint64
valid bool
}{
{0, 0, 0, true},
{0, 0, 1, false},
{0, 2, 0, true},
{0, 2, 1, true},
{0, 2, 2, true},
{0, 2, 3, false},
{10, 0, 0, true},
{10, 0, 1, true},
{10, 0, 9, true},
{10, 0, 10, false},
{10, 0, 11, false},
{10, 10, 0, true},
{10, 10, 1, true},
{10, 10, 9, true},
{10, 10, 10, true},
{10, 10, 11, false},
}

for idx, c := range cases {
name := strconv.FormatInt(int64(idx), 10)
t.Run(name, func(t *testing.T) {
// Create a new Indexer
height := c.height
startHeight := c.startHeight
cfg := config.Default.DB
dbPath, err := testutil.PathOfTempFile("db")
r.NoError(err)
cfg.DbPath = dbPath
indexer, err := NewContractStakingIndexer(db.NewBoltDB(cfg), identityset.Address(1).String(), startHeight)
r.NoError(err)
r.NoError(indexer.Start(context.Background()))
defer func() {
r.NoError(indexer.Stop(context.Background()))
testutil.CleanupPath(dbPath)
}()
indexer.cache.putHeight(height)
// check read api
h := c.readHeight
delegate := identityset.Address(1)
if c.valid {
_, err = indexer.Buckets(h)
r.NoError(err)
_, err = indexer.BucketTypes(h)
r.NoError(err)
_, err = indexer.BucketsByCandidate(delegate1, h)
_, err = indexer.BucketsByCandidate(delegate, h)
r.NoError(err)
_, err = indexer.BucketsByIndices([]uint64{1, 2, 3, 4, 5, 8}, h)
r.NoError(err)
_, err = indexer.CandidateVotes(delegate1, h)
_, err = indexer.CandidateVotes(delegate, h)
r.NoError(err)
_, _, err = indexer.Bucket(1, h)
r.NoError(err)
@@ -949,19 +987,19 @@ func TestContractStakingIndexerVotes(t *testing.T) {
r.ErrorIs(err, ErrInvalidHeight)
_, err = indexer.BucketTypes(h)
r.ErrorIs(err, ErrInvalidHeight)
_, err = indexer.BucketsByCandidate(delegate1, h)
_, err = indexer.BucketsByCandidate(delegate, h)
r.ErrorIs(err, ErrInvalidHeight)
_, err = indexer.BucketsByIndices([]uint64{1, 2, 3, 4, 5, 8}, h)
r.ErrorIs(err, ErrInvalidHeight)
_, err = indexer.CandidateVotes(delegate1, h)
_, err = indexer.CandidateVotes(delegate, h)
r.ErrorIs(err, ErrInvalidHeight)
_, _, err = indexer.Bucket(1, h)
r.ErrorIs(err, ErrInvalidHeight)
_, err = indexer.TotalBucketCount(h)
r.ErrorIs(err, ErrInvalidHeight)
}
}
})
})
}
}

func TestIndexer_PutBlock(t *testing.T) {
4 changes: 4 additions & 0 deletions blockindex/sgd_indexer.go
Original file line number Diff line number Diff line change
@@ -496,6 +496,10 @@ func (sgd *sgdRegistry) validateQueryHeight(height uint64) error {
if height == 0 {
return nil
}
// Compatible with blocks between feature hard-fork and contract deployed
if height < sgd.startHeight {
return nil
}
tipHeight, err := sgd.height()
if err != nil {
return err
111 changes: 86 additions & 25 deletions blockindex/sgd_indexer_test.go
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ import (
"context"
"encoding/hex"
"math/big"
"strconv"
"sync/atomic"
"testing"

@@ -15,6 +16,8 @@ import (
"github.com/iotexproject/iotex-core/blockchain/block"
"github.com/iotexproject/iotex-core/blockchain/genesis"
"github.com/iotexproject/iotex-core/db"
"github.com/iotexproject/iotex-core/db/batch"
"github.com/iotexproject/iotex-core/pkg/util/byteutil"
"github.com/iotexproject/iotex-core/state"
"github.com/iotexproject/iotex-core/test/identityset"
"github.com/iotexproject/iotex-core/testutil"
@@ -109,31 +112,6 @@ func TestNewSGDRegistry(t *testing.T) {
r.Equal(receiverAddress, receiver)
r.True(isApproved)
r.Equal(_sgdPercentage, percentage)

t.Run("heightRestriction", func(t *testing.T) {
cases := []struct {
height uint64
isErr bool
}{
{0, false},
{1, true},
{2, false},
{3, true},
}
for i := range cases {
if cases[i].isErr {
_, err = sgdRegistry.FetchContracts(ctx, cases[i].height)
r.ErrorContains(err, "invalid height")
_, _, _, err = sgdRegistry.CheckContract(ctx, registerAddress.String(), cases[i].height)
r.ErrorContains(err, "invalid height")
} else {
_, err = sgdRegistry.FetchContracts(ctx, cases[i].height)
r.Nil(err)
_, _, _, err = sgdRegistry.CheckContract(ctx, registerAddress.String(), cases[i].height)
r.Nil(err)
}
}
})
})
t.Run("disapproveContract", func(t *testing.T) {
builder := block.NewTestingBuilder()
@@ -182,6 +160,89 @@ func TestNewSGDRegistry(t *testing.T) {
r.ErrorIs(err, state.ErrStateNotExist)
})
})
t.Run("heightRestriction", func(t *testing.T) {
cases := []struct {
startHeight uint64
height uint64
readHeight uint64
valid bool
}{
{0, 0, 0, true},
{0, 0, 1, false},
{0, 2, 0, true},
{0, 2, 1, false},
{0, 2, 2, true},
{0, 2, 3, false},
{10, 0, 0, true},
{10, 0, 1, true},
{10, 0, 9, true},
{10, 0, 10, false},
{10, 0, 11, false},
{10, 10, 0, true},
{10, 10, 1, true},
{10, 10, 9, true},
{10, 10, 10, true},
{10, 10, 11, false},
}
for i := range cases {
name := strconv.FormatInt(int64(i), 10)
t.Run(name, func(t *testing.T) {
testDBPath, err := testutil.PathOfTempFile("sgd")
r.NoError(err)
ctx := context.Background()
cfg := db.DefaultConfig
cfg.DbPath = testDBPath
kvStore := db.NewBoltDB(cfg)
sgdRegistry := &sgdRegistry{
contract: _testSGDContractAddress,
startHeight: cases[i].startHeight,
kvStore: kvStore,
}
r.NoError(sgdRegistry.Start(ctx))
defer func() {
r.NoError(sgdRegistry.Stop(ctx))
testutil.CleanupPath(testDBPath)
}()
// register
nonce := uint64(0)
registerAddress, err := address.FromHex("5b38da6a701c568545dcfcb03fcb875f56beddc4")
r.NoError(err)
builder := block.NewTestingBuilder()
event := _sgdABI.Events["ContractRegistered"]
data, _ := hex.DecodeString("0000000000000000000000005b38da6a701c568545dcfcb03fcb875f56beddc400000000000000000000000078731d3ca6b7e34ac0f824c42a7cc18a495cabab")
exec, err := action.SignedExecution(_testSGDContractAddress, identityset.PrivateKey(27), atomic.AddUint64(&nonce, 1), big.NewInt(0), 10000000, big.NewInt(9000000000000), data)
r.NoError(err)
h, _ := exec.Hash()
logs := &action.Log{
Address: _testSGDContractAddress,
Topics: []hash.Hash256{hash.Hash256(event.ID)},
Data: data,
}
expectHeight, err := sgdRegistry.expectHeight()
r.NoError(err)
blk := createTestingBlock(builder, expectHeight, h, exec, logs)
r.NoError(sgdRegistry.PutBlock(ctx, blk))
_, _, _, err = sgdRegistry.CheckContract(ctx, registerAddress.String(), 1)
r.NoError(err)
// update height
b := batch.NewBatch()
b.Put(_sgdToHeightNS, _sgdCurrentHeight, byteutil.Uint64ToBytesBigEndian(cases[i].height), "failed to put current height")
sgdRegistry.kvStore.WriteBatch(b)
// check
if !cases[i].valid {
_, err = sgdRegistry.FetchContracts(ctx, cases[i].readHeight)
r.ErrorContains(err, "invalid height")
_, _, _, err = sgdRegistry.CheckContract(ctx, registerAddress.String(), cases[i].readHeight)
r.ErrorContains(err, "invalid height")
} else {
_, err = sgdRegistry.FetchContracts(ctx, cases[i].readHeight)
r.Nil(err)
_, _, _, err = sgdRegistry.CheckContract(ctx, registerAddress.String(), cases[i].readHeight)
r.Nil(err)
}
})
}
})
}

func createTestingBlock(builder *block.TestingBuilder, height uint64, h hash.Hash256, act action.SealedEnvelope, logs *action.Log) *block.Block {

0 comments on commit d1fc3ab

Please sign in to comment.