good morning!!!!

Skip to content
Snippets Groups Projects
Unverified Commit 7fd50a84 authored by Jaynti Kanani's avatar Jaynti Kanani Committed by GitHub
Browse files

Merge pull request #66 from maticnetwork/mew-deposits

alter the fetch logic a bit
parents 01c9c8b4 16515758
Branches devnet-70003
Tags
No related merge requests found
...@@ -62,7 +62,6 @@ var ( ...@@ -62,7 +62,6 @@ var (
validatorHeaderBytesLength = common.AddressLength + 20 // address + power validatorHeaderBytesLength = common.AddressLength + 20 // address + power
systemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE") systemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE")
stateFetchLimit = 50
) )
// Various error messages to mark blocks invalid. These should be private to // Various error messages to mark blocks invalid. These should be private to
...@@ -221,7 +220,7 @@ type Bor struct { ...@@ -221,7 +220,7 @@ type Bor struct {
lock sync.RWMutex // Protects the signer fields lock sync.RWMutex // Protects the signer fields
ethAPI *ethapi.PublicBlockChainAPI ethAPI *ethapi.PublicBlockChainAPI
genesisContractsClient *GenesisContractsClient GenesisContractsClient *GenesisContractsClient
validatorSetABI abi.ABI validatorSetABI abi.ABI
stateReceiverABI abi.ABI stateReceiverABI abi.ABI
HeimdallClient IHeimdallClient HeimdallClient IHeimdallClient
...@@ -263,7 +262,7 @@ func New( ...@@ -263,7 +262,7 @@ func New(
signatures: signatures, signatures: signatures,
validatorSetABI: vABI, validatorSetABI: vABI,
stateReceiverABI: sABI, stateReceiverABI: sABI,
genesisContractsClient: genesisContractsClient, GenesisContractsClient: genesisContractsClient,
HeimdallClient: heimdallClient, HeimdallClient: heimdallClient,
} }
...@@ -1076,57 +1075,26 @@ func (c *Bor) CommitStates( ...@@ -1076,57 +1075,26 @@ func (c *Bor) CommitStates(
chain chainContext, chain chainContext,
) error { ) error {
number := header.Number.Uint64() number := header.Number.Uint64()
lastSync, err := c.genesisContractsClient.LastStateSyncTime(number - 1) _lastStateID, err := c.GenesisContractsClient.LastStateId(number - 1)
if err != nil { if err != nil {
return err return err
} }
from := lastSync.Add(time.Second * 1) // querying the interval [from, to)
to := time.Unix(int64(chain.Chain.GetHeaderByNumber(number-c.config.Sprint).Time), 0) to := time.Unix(int64(chain.Chain.GetHeaderByNumber(number-c.config.Sprint).Time), 0)
if !from.Before(to) { lastStateID := _lastStateID.Uint64()
return nil
}
log.Info( log.Info(
"Fetching state updates from Heimdall", "Fetching state updates from Heimdall",
"from", from.Format(time.RFC3339), "fromID", lastStateID+1,
"to", to.Format(time.RFC3339)) "to", to.Format(time.RFC3339))
eventRecords, err := c.HeimdallClient.FetchStateSyncEvents(lastStateID+1, to.Unix())
page := 1
eventRecords := make([]*EventRecordWithTime, 0)
for {
queryParams := fmt.Sprintf("from-time=%d&to-time=%d&page=%d&limit=%d", from.Unix(), to.Unix(), page, stateFetchLimit)
log.Info("Fetching state sync events", "queryParams", queryParams)
response, err := c.HeimdallClient.FetchWithRetry("clerk/event-record/list", queryParams)
if err != nil {
return err
}
var _eventRecords []*EventRecordWithTime
if response.Result == nil { // status 204
break
}
if err := json.Unmarshal(response.Result, &_eventRecords); err != nil {
return err
}
eventRecords = append(eventRecords, _eventRecords...)
if len(_eventRecords) < stateFetchLimit {
break
}
page++
}
sort.SliceStable(eventRecords, func(i, j int) bool {
return eventRecords[i].ID < eventRecords[j].ID
})
chainID := c.chainConfig.ChainID.String() chainID := c.chainConfig.ChainID.String()
for _, eventRecord := range eventRecords { for _, eventRecord := range eventRecords {
// validateEventRecord checks whether an event lies in the specified time range if eventRecord.ID <= lastStateID {
// since the events are sorted by time and if it turns out that event i lies outside the time range, continue
// it would mean all subsequent events lie outside of the time range. Hence we don't probe any further and break the loop }
if err := validateEventRecord(eventRecord, number, from, to, chainID); err != nil { if err := validateEventRecord(eventRecord, number, to, lastStateID, chainID); err != nil {
log.Error( log.Error(err.Error())
fmt.Sprintf(
"Received event %s does not lie in the time range, from %s, to %s",
eventRecord, from.Format(time.RFC3339), to.Format(time.RFC3339)))
break break
} }
...@@ -1140,17 +1108,18 @@ func (c *Bor) CommitStates( ...@@ -1140,17 +1108,18 @@ func (c *Bor) CommitStates(
c.stateDataFeed.Send(core.NewStateChangeEvent{StateData: &stateData}) c.stateDataFeed.Send(core.NewStateChangeEvent{StateData: &stateData})
}() }()
if err := c.genesisContractsClient.CommitState(eventRecord, state, header, chain); err != nil { if err := c.GenesisContractsClient.CommitState(eventRecord, state, header, chain); err != nil {
return err return err
} }
lastStateID++
} }
return nil return nil
} }
func validateEventRecord(eventRecord *EventRecordWithTime, number uint64, from, to time.Time, chainID string) error { func validateEventRecord(eventRecord *EventRecordWithTime, number uint64, to time.Time, lastStateID uint64, chainID string) error {
// event should lie in the range [from, to) // event id should be sequential and event.Time should lie in the range [from, to)
if eventRecord.ChainID != chainID || eventRecord.Time.Before(from) || !eventRecord.Time.Before(to) { if lastStateID+1 != eventRecord.ID || eventRecord.ChainID != chainID || !eventRecord.Time.Before(to) {
return &InvalidStateReceivedError{number, &from, &to, eventRecord} return &InvalidStateReceivedError{number, lastStateID, &to, eventRecord}
} }
return nil return nil
} }
...@@ -1164,28 +1133,6 @@ func (c *Bor) SetHeimdallClient(h IHeimdallClient) { ...@@ -1164,28 +1133,6 @@ func (c *Bor) SetHeimdallClient(h IHeimdallClient) {
c.HeimdallClient = h c.HeimdallClient = h
} }
func isProposeSpanAction(tx *types.Transaction, validatorContract string) bool {
// keccak256('proposeSpan()').slice(0, 4)
proposeSpanSig, _ := hex.DecodeString("4b0e4d17")
if tx.Data() == nil || len(tx.Data()) < 4 {
return false
}
return bytes.Compare(proposeSpanSig, tx.Data()[:4]) == 0 &&
tx.To().String() == validatorContract
}
func isProposeStateAction(tx *types.Transaction, stateReceiverContract string) bool {
// keccak256('proposeState(uint256)').slice(0, 4)
proposeStateSig, _ := hex.DecodeString("ede01f17")
if tx.Data() == nil || len(tx.Data()) < 4 {
return false
}
return bytes.Compare(proposeStateSig, tx.Data()[:4]) == 0 &&
tx.To().String() == stateReceiverContract
}
// //
// Private methods // Private methods
// //
......
...@@ -3,20 +3,17 @@ package bortest ...@@ -3,20 +3,17 @@ package bortest
import ( import (
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt"
"math/big" "math/big"
"testing" "testing"
"time" "time"
"github.com/maticnetwork/bor/consensus/bor"
"github.com/maticnetwork/bor/core/rawdb"
"github.com/maticnetwork/bor/crypto"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
"github.com/maticnetwork/bor/consensus/bor"
"github.com/maticnetwork/bor/core/rawdb"
"github.com/maticnetwork/bor/core/types" "github.com/maticnetwork/bor/core/types"
"github.com/maticnetwork/bor/crypto"
"github.com/maticnetwork/bor/mocks" "github.com/maticnetwork/bor/mocks"
) )
...@@ -36,7 +33,7 @@ func TestInsertingSpanSizeBlocks(t *testing.T) { ...@@ -36,7 +33,7 @@ func TestInsertingSpanSizeBlocks(t *testing.T) {
db := init.ethereum.ChainDb() db := init.ethereum.ChainDb()
block := init.genesis.ToBlock(db) block := init.genesis.ToBlock(db)
to := int64(block.Header().Time) // to := int64(block.Header().Time)
// Insert sprintSize # of blocks so that span is fetched at the start of a new sprint // Insert sprintSize # of blocks so that span is fetched at the start of a new sprint
for i := uint64(1); i <= spanSize; i++ { for i := uint64(1); i <= spanSize; i++ {
...@@ -45,7 +42,6 @@ func TestInsertingSpanSizeBlocks(t *testing.T) { ...@@ -45,7 +42,6 @@ func TestInsertingSpanSizeBlocks(t *testing.T) {
} }
assert.True(t, h.AssertCalled(t, "FetchWithRetry", spanPath, "")) assert.True(t, h.AssertCalled(t, "FetchWithRetry", spanPath, ""))
assert.True(t, h.AssertCalled(t, "FetchWithRetry", clerkPath, fmt.Sprintf(clerkQueryParams, 1, to, 1)))
validators, err := _bor.GetCurrentValidators(sprintSize, spanSize) // check validator set at the first block of new span validators, err := _bor.GetCurrentValidators(sprintSize, spanSize) // check validator set at the first block of new span
if err != nil { if err != nil {
t.Fatalf("%s", err) t.Fatalf("%s", err)
...@@ -80,39 +76,82 @@ func TestFetchStateSyncEvents(t *testing.T) { ...@@ -80,39 +76,82 @@ func TestFetchStateSyncEvents(t *testing.T) {
h.On("FetchWithRetry", spanPath, "").Return(res, nil) h.On("FetchWithRetry", spanPath, "").Return(res, nil)
// B.2 Mock State Sync events // B.2 Mock State Sync events
// read heimdall api response from file fromID := uint64(1)
res = stateSyncEventsPayload(t) // at # sprintSize, events are fetched for [fromID, (block-sprint).Time)
var _eventRecords []*bor.EventRecordWithTime to := int64(chain.GetHeaderByNumber(0).Time)
if err := json.Unmarshal(res.Result, &_eventRecords); err != nil { eventCount := 50
t.Fatalf("%s", err)
}
// use that as a sample to generate bor.stateFetchLimit events sample := getSampleEventRecord(t)
eventRecords := generateFakeStateSyncEvents(_eventRecords[0], 50) sample.Time = time.Unix(to-int64(eventCount+1), 0) // last event.Time will be just < to
_res, _ := json.Marshal(eventRecords) eventRecords := generateFakeStateSyncEvents(sample, eventCount)
response := bor.ResponseWithHeight{Height: "0"} h.On("FetchStateSyncEvents", fromID, to).Return(eventRecords, nil)
if err := json.Unmarshal(_res, &response.Result); err != nil { _bor.SetHeimdallClient(h)
t.Fatalf("%s", err)
block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor)
insertNewBlock(t, chain, block)
assert.True(t, h.AssertCalled(t, "FetchWithRetry", spanPath, ""))
assert.True(t, h.AssertCalled(t, "FetchStateSyncEvents", fromID, to))
} }
// at # sprintSize, events are fetched for the interval [from, (block-sprint).Time) func TestFetchStateSyncEvents_2(t *testing.T) {
from := 1 init := buildEthereumInstance(t, rawdb.NewMemoryDatabase())
to := int64(chain.GetHeaderByNumber(0).Time) chain := init.ethereum.BlockChain()
page := 1 engine := init.ethereum.Engine()
query1Params := fmt.Sprintf(clerkQueryParams, from, to, page) _bor := engine.(*bor.Bor)
h.On("FetchWithRetry", clerkPath, query1Params).Return(&response, nil)
// Mock /bor/span/1
res, _ := loadSpanFromFile(t)
h := &mocks.IHeimdallClient{}
h.On("FetchWithRetry", spanPath, "").Return(res, nil)
page = 2 // Mock State Sync events
query2Params := fmt.Sprintf(clerkQueryParams, from, to, page) // at # sprintSize, events are fetched for [fromID, (block-sprint).Time)
h.On("FetchWithRetry", clerkPath, query2Params).Return(&bor.ResponseWithHeight{}, nil) fromID := uint64(1)
to := int64(chain.GetHeaderByNumber(0).Time)
sample := getSampleEventRecord(t)
// First query will be from [id=1, (block-sprint).Time]
// Insert 5 events in this time range
eventRecords := []*bor.EventRecordWithTime{
buildStateEvent(sample, 1, 3), // id = 1, time = 1
buildStateEvent(sample, 2, 1), // id = 2, time = 3
buildStateEvent(sample, 3, 2), // id = 3, time = 2
// event with id 5 is missing
buildStateEvent(sample, 4, 5), // id = 4, time = 5
buildStateEvent(sample, 6, 4), // id = 6, time = 4
}
h.On("FetchStateSyncEvents", fromID, to).Return(eventRecords, nil)
_bor.SetHeimdallClient(h) _bor.SetHeimdallClient(h)
// Insert blocks for 0th sprint
db := init.ethereum.ChainDb()
block := init.genesis.ToBlock(db)
for i := uint64(1); i <= sprintSize; i++ {
block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor) block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor)
insertNewBlock(t, chain, block) insertNewBlock(t, chain, block)
}
assert.True(t, h.AssertCalled(t, "FetchWithRetry", spanPath, "")) assert.True(t, h.AssertCalled(t, "FetchWithRetry", spanPath, ""))
assert.True(t, h.AssertCalled(t, "FetchWithRetry", clerkPath, query1Params)) assert.True(t, h.AssertCalled(t, "FetchStateSyncEvents", fromID, to))
assert.True(t, h.AssertCalled(t, "FetchWithRetry", clerkPath, query2Params)) lastStateID, _ := _bor.GenesisContractsClient.LastStateId(sprintSize)
// state 6 was not written
assert.Equal(t, uint64(4), lastStateID.Uint64())
//
fromID = uint64(5)
to = int64(chain.GetHeaderByNumber(sprintSize).Time)
eventRecords = []*bor.EventRecordWithTime{
buildStateEvent(sample, 5, 7),
buildStateEvent(sample, 6, 4),
}
h.On("FetchStateSyncEvents", fromID, to).Return(eventRecords, nil)
for i := sprintSize + 1; i <= spanSize; i++ {
block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor)
insertNewBlock(t, chain, block)
}
assert.True(t, h.AssertCalled(t, "FetchStateSyncEvents", fromID, to))
lastStateID, _ = _bor.GenesisContractsClient.LastStateId(spanSize)
assert.Equal(t, uint64(6), lastStateID.Uint64())
} }
func TestOutOfTurnSigning(t *testing.T) { func TestOutOfTurnSigning(t *testing.T) {
...@@ -191,15 +230,17 @@ func getMockedHeimdallClient(t *testing.T) (*mocks.IHeimdallClient, *bor.Heimdal ...@@ -191,15 +230,17 @@ func getMockedHeimdallClient(t *testing.T) (*mocks.IHeimdallClient, *bor.Heimdal
res, heimdallSpan := loadSpanFromFile(t) res, heimdallSpan := loadSpanFromFile(t)
h := &mocks.IHeimdallClient{} h := &mocks.IHeimdallClient{}
h.On("FetchWithRetry", "bor/span/1", "").Return(res, nil) h.On("FetchWithRetry", "bor/span/1", "").Return(res, nil)
h.On("FetchWithRetry", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(stateSyncEventsPayload(t), nil) h.On(
"FetchStateSyncEvents",
mock.AnythingOfType("uint64"),
mock.AnythingOfType("int64")).Return([]*bor.EventRecordWithTime{getSampleEventRecord(t)}, nil)
return h, heimdallSpan return h, heimdallSpan
} }
func generateFakeStateSyncEvents(sample *bor.EventRecordWithTime, count int) []*bor.EventRecordWithTime { func generateFakeStateSyncEvents(sample *bor.EventRecordWithTime, count int) []*bor.EventRecordWithTime {
events := make([]*bor.EventRecordWithTime, count) events := make([]*bor.EventRecordWithTime, count)
event := *sample event := *sample
event.ID = 0 event.ID = 1
event.Time = time.Now()
events[0] = &bor.EventRecordWithTime{} events[0] = &bor.EventRecordWithTime{}
*events[0] = event *events[0] = event
for i := 1; i < count; i++ { for i := 1; i < count; i++ {
...@@ -210,3 +251,20 @@ func generateFakeStateSyncEvents(sample *bor.EventRecordWithTime, count int) []* ...@@ -210,3 +251,20 @@ func generateFakeStateSyncEvents(sample *bor.EventRecordWithTime, count int) []*
} }
return events return events
} }
func buildStateEvent(sample *bor.EventRecordWithTime, id uint64, timeStamp int64) *bor.EventRecordWithTime {
event := *sample
event.ID = id
event.Time = time.Unix(timeStamp, 0)
return &event
}
func getSampleEventRecord(t *testing.T) *bor.EventRecordWithTime {
res := stateSyncEventsPayload(t)
var _eventRecords []*bor.EventRecordWithTime
if err := json.Unmarshal(res.Result, &_eventRecords); err != nil {
t.Fatalf("%s", err)
}
_eventRecords[0].Time = time.Unix(1, 0)
return _eventRecords[0]
}
This diff is collapsed.
...@@ -127,17 +127,17 @@ func (e *WrongDifficultyError) Error() string { ...@@ -127,17 +127,17 @@ func (e *WrongDifficultyError) Error() string {
type InvalidStateReceivedError struct { type InvalidStateReceivedError struct {
Number uint64 Number uint64
From *time.Time LastStateID uint64
To *time.Time To *time.Time
Event *EventRecordWithTime Event *EventRecordWithTime
} }
func (e *InvalidStateReceivedError) Error() string { func (e *InvalidStateReceivedError) Error() string {
return fmt.Sprintf( return fmt.Sprintf(
"Received event with invalid timestamp at block %d. Requested events from %s to %s. Received %s\n", "Received invalid event %s at block %d. Requested events until %s. Last state id was %d",
e.Event,
e.Number, e.Number,
e.From.Format(time.RFC3339),
e.To.Format(time.RFC3339), e.To.Format(time.RFC3339),
e.Event, e.LastStateID,
) )
} }
...@@ -4,9 +4,7 @@ import ( ...@@ -4,9 +4,7 @@ import (
"context" "context"
"math" "math"
"math/big" "math/big"
"strings" "strings"
"time"
"github.com/maticnetwork/bor/accounts/abi" "github.com/maticnetwork/bor/accounts/abi"
"github.com/maticnetwork/bor/common" "github.com/maticnetwork/bor/common"
...@@ -30,7 +28,7 @@ type GenesisContractsClient struct { ...@@ -30,7 +28,7 @@ type GenesisContractsClient struct {
} }
const validatorsetABI = `[{"constant":true,"inputs":[],"name":"SPRINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"CHAIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FIRST_END_BLOCK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"producers","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ROUND_TYPE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"BOR_ID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spanNumbers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"VOTE_TYPE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"validators","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spans","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"startBlock","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"endBlock","type":"uint256"}],"name":"NewSpan","type":"event"},{"constant":true,"inputs":[],"name":"currentSprint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNextSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getSpanByBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentSpanNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getValidatorsTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getProducersTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"getValidatorBySigner","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct BorValidatorSet.Validator","name":"result","type":"tuple"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getBorValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitialValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newSpan","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"},{"internalType":"bytes","name":"validatorBytes","type":"bytes"},{"internalType":"bytes","name":"producerBytes","type":"bytes"}],"name":"commitSpan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"bytes","name":"sigs","type":"bytes"}],"name":"getStakePowerBySigs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"bytes32","name":"leaf","type":"bytes32"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"checkMembership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"d","type":"bytes32"}],"name":"leafNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"left","type":"bytes32"},{"internalType":"bytes32","name":"right","type":"bytes32"}],"name":"innerNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"}]` const validatorsetABI = `[{"constant":true,"inputs":[],"name":"SPRINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"CHAIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FIRST_END_BLOCK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"producers","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ROUND_TYPE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"BOR_ID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spanNumbers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"VOTE_TYPE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"validators","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spans","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"startBlock","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"endBlock","type":"uint256"}],"name":"NewSpan","type":"event"},{"constant":true,"inputs":[],"name":"currentSprint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNextSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getSpanByBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentSpanNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getValidatorsTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getProducersTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"getValidatorBySigner","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct BorValidatorSet.Validator","name":"result","type":"tuple"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getBorValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitialValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newSpan","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"},{"internalType":"bytes","name":"validatorBytes","type":"bytes"},{"internalType":"bytes","name":"producerBytes","type":"bytes"}],"name":"commitSpan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"bytes","name":"sigs","type":"bytes"}],"name":"getStakePowerBySigs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"bytes32","name":"leaf","type":"bytes32"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"checkMembership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"d","type":"bytes32"}],"name":"leafNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"left","type":"bytes32"},{"internalType":"bytes32","name":"right","type":"bytes32"}],"name":"innerNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"}]`
const stateReceiverABI = `[{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastStateSyncTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastStateId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"syncTime","type":"uint256"},{"internalType":"bytes","name":"recordBytes","type":"bytes"}],"name":"commitState","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]` const stateReceiverABI = `[{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastStateId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"syncTime","type":"uint256"},{"internalType":"bytes","name":"recordBytes","type":"bytes"}],"name":"commitState","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]`
func NewGenesisContractsClient( func NewGenesisContractsClient(
chainConfig *params.ChainConfig, chainConfig *params.ChainConfig,
...@@ -76,11 +74,11 @@ func (gc *GenesisContractsClient) CommitState( ...@@ -76,11 +74,11 @@ func (gc *GenesisContractsClient) CommitState(
return nil return nil
} }
func (gc *GenesisContractsClient) LastStateSyncTime(snapshotNumber uint64) (*time.Time, error) { func (gc *GenesisContractsClient) LastStateId(snapshotNumber uint64) (*big.Int, error) {
method := "lastStateSyncTime" method := "lastStateId"
data, err := gc.stateReceiverABI.Pack(method) data, err := gc.stateReceiverABI.Pack(method)
if err != nil { if err != nil {
log.Error("Unable to pack tx for getLastSyncTime", "error", err) log.Error("Unable to pack tx for LastStateId", "error", err)
return nil, err return nil, err
} }
...@@ -100,6 +98,5 @@ func (gc *GenesisContractsClient) LastStateSyncTime(snapshotNumber uint64) (*tim ...@@ -100,6 +98,5 @@ func (gc *GenesisContractsClient) LastStateSyncTime(snapshotNumber uint64) (*tim
if err := gc.stateReceiverABI.Unpack(ret, method, result); err != nil { if err := gc.stateReceiverABI.Unpack(ret, method, result); err != nil {
return nil, err return nil, err
} }
_time := time.Unix((*ret).Int64(), 0) return *ret, nil
return &_time, nil
} }
...@@ -6,11 +6,16 @@ import ( ...@@ -6,11 +6,16 @@ import (
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"sort"
"time" "time"
"github.com/maticnetwork/bor/log" "github.com/maticnetwork/bor/log"
) )
var (
stateFetchLimit = 50
)
// ResponseWithHeight defines a response object type that wraps an original // ResponseWithHeight defines a response object type that wraps an original
// response with a height. // response with a height.
type ResponseWithHeight struct { type ResponseWithHeight struct {
...@@ -21,6 +26,7 @@ type ResponseWithHeight struct { ...@@ -21,6 +26,7 @@ type ResponseWithHeight struct {
type IHeimdallClient interface { type IHeimdallClient interface {
Fetch(path string, query string) (*ResponseWithHeight, error) Fetch(path string, query string) (*ResponseWithHeight, error)
FetchWithRetry(path string, query string) (*ResponseWithHeight, error) FetchWithRetry(path string, query string) (*ResponseWithHeight, error)
FetchStateSyncEvents(fromID uint64, to int64) ([]*EventRecordWithTime, error)
} }
type HeimdallClient struct { type HeimdallClient struct {
...@@ -38,6 +44,35 @@ func NewHeimdallClient(urlString string) (*HeimdallClient, error) { ...@@ -38,6 +44,35 @@ func NewHeimdallClient(urlString string) (*HeimdallClient, error) {
return h, nil return h, nil
} }
func (h *HeimdallClient) FetchStateSyncEvents(fromID uint64, to int64) ([]*EventRecordWithTime, error) {
eventRecords := make([]*EventRecordWithTime, 0)
for {
queryParams := fmt.Sprintf("from-id=%d&to-time=%d&limit=%d", fromID, to, stateFetchLimit)
log.Info("Fetching state sync events", "queryParams", queryParams)
response, err := h.FetchWithRetry("clerk/event-record/list", queryParams)
if err != nil {
return nil, err
}
var _eventRecords []*EventRecordWithTime
if response.Result == nil { // status 204
break
}
if err := json.Unmarshal(response.Result, &_eventRecords); err != nil {
return nil, err
}
eventRecords = append(eventRecords, _eventRecords...)
if len(_eventRecords) < stateFetchLimit {
break
}
fromID += uint64(stateFetchLimit)
}
sort.SliceStable(eventRecords, func(i, j int) bool {
return eventRecords[i].ID < eventRecords[j].ID
})
return eventRecords, nil
}
// Fetch fetches response from heimdall // Fetch fetches response from heimdall
func (h *HeimdallClient) Fetch(rawPath string, rawQuery string) (*ResponseWithHeight, error) { func (h *HeimdallClient) Fetch(rawPath string, rawQuery string) (*ResponseWithHeight, error) {
u, err := url.Parse(h.urlString) u, err := url.Parse(h.urlString)
......
...@@ -35,6 +35,29 @@ func (_m *IHeimdallClient) Fetch(path string, query string) (*bor.ResponseWithHe ...@@ -35,6 +35,29 @@ func (_m *IHeimdallClient) Fetch(path string, query string) (*bor.ResponseWithHe
return r0, r1 return r0, r1
} }
// FetchStateSyncEvents provides a mock function with given fields: fromID, to
func (_m *IHeimdallClient) FetchStateSyncEvents(fromID uint64, to int64) ([]*bor.EventRecordWithTime, error) {
ret := _m.Called(fromID, to)
var r0 []*bor.EventRecordWithTime
if rf, ok := ret.Get(0).(func(uint64, int64) []*bor.EventRecordWithTime); ok {
r0 = rf(fromID, to)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*bor.EventRecordWithTime)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(uint64, int64) error); ok {
r1 = rf(fromID, to)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// FetchWithRetry provides a mock function with given fields: path, query // FetchWithRetry provides a mock function with given fields: path, query
func (_m *IHeimdallClient) FetchWithRetry(path string, query string) (*bor.ResponseWithHeight, error) { func (_m *IHeimdallClient) FetchWithRetry(path string, query string) (*bor.ResponseWithHeight, error) {
ret := _m.Called(path, query) ret := _m.Called(path, query)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment