diff --git a/packages/eventindexer/http/get_stats_test.go b/packages/eventindexer/http/get_stats_test.go index 08161dedd2..a4c5c6000f 100644 --- a/packages/eventindexer/http/get_stats_test.go +++ b/packages/eventindexer/http/get_stats_test.go @@ -2,6 +2,7 @@ package http import ( "context" + "math/big" "net/http" "net/http/httptest" "testing" @@ -15,13 +16,13 @@ import ( func Test_GetStats(t *testing.T) { srv := newTestServer("") - var proofTime uint64 = 5 + var proofTime = big.NewInt(5) - var proofReward uint64 = 7 + var proofReward = big.NewInt(7) _, err := srv.statRepo.Save(context.Background(), eventindexer.SaveStatOpts{ - ProofTime: &proofTime, - ProofReward: &proofReward, + ProofTime: proofTime, + ProofReward: proofReward, }) assert.Equal(t, nil, err) @@ -36,7 +37,7 @@ func Test_GetStats(t *testing.T) { "success", "0x123", http.StatusOK, - []string{`{"id":1,"averageProofTime":5,"averageProofReward":7,"numProofs":1,"numVerifiedBlocks":1}`}, + []string{`{"id":1,"averageProofTime":"5","averageProofReward":"7","numProofs":1,"numVerifiedBlocks":1}`}, }, } diff --git a/packages/eventindexer/indexer/save_block_proven_event.go b/packages/eventindexer/indexer/save_block_proven_event.go index 2c7eab4c0d..ecc1167c4c 100644 --- a/packages/eventindexer/indexer/save_block_proven_event.go +++ b/packages/eventindexer/indexer/save_block_proven_event.go @@ -104,10 +104,19 @@ func (svc *Service) updateAverageProofTime(ctx context.Context, event *taikol1.T proofTime := provenAt - proposedAt - newAverageProofTime := calcNewAverage(stat.AverageProofTime, stat.NumProofs, proofTime) + avg, ok := new(big.Int).SetString(stat.AverageProofTime, 10) + if !ok { + return errors.New("unable to convert average proof time to string") + } + + newAverageProofTime := calcNewAverage( + avg, + new(big.Int).SetUint64(stat.NumProofs), + new(big.Int).SetUint64(proofTime), + ) _, err = svc.statRepo.Save(ctx, eventindexer.SaveStatOpts{ - ProofTime: &newAverageProofTime, + ProofTime: newAverageProofTime, }) if err != nil { return errors.Wrap(err, "svc.statRepo.Save") @@ -116,6 +125,9 @@ func (svc *Service) updateAverageProofTime(ctx context.Context, event *taikol1.T return nil } -func calcNewAverage(a, t, new uint64) uint64 { - return ((a * t) + new) / (t + 1) +func calcNewAverage(a, t, n *big.Int) *big.Int { + m := new(big.Int).Mul(a, t) + added := new(big.Int).Add(m, n) + + return new(big.Int).Div(added, t.Add(t, big.NewInt(1))) } diff --git a/packages/eventindexer/indexer/save_block_verified_event.go b/packages/eventindexer/indexer/save_block_verified_event.go index 6ee3fe9244..e242b1ee54 100644 --- a/packages/eventindexer/indexer/save_block_verified_event.go +++ b/packages/eventindexer/indexer/save_block_verified_event.go @@ -80,10 +80,19 @@ func (svc *Service) updateAverageBlockReward(ctx context.Context, event *taikol1 return errors.Wrap(err, "svc.statRepo.Find") } - newAverageProofReward := calcNewAverage(stat.AverageProofReward, stat.NumVerifiedBlocks, reward) + avg, ok := new(big.Int).SetString(stat.AverageProofReward, 10) + if !ok { + return errors.New("unable to convert average proof reward to string") + } + + newAverageProofReward := calcNewAverage( + avg, + new(big.Int).SetUint64(stat.NumVerifiedBlocks), + new(big.Int).SetUint64(reward), + ) _, err = svc.statRepo.Save(ctx, eventindexer.SaveStatOpts{ - ProofReward: &newAverageProofReward, + ProofReward: newAverageProofReward, }) if err != nil { return errors.Wrap(err, "svc.statRepo.Save") diff --git a/packages/eventindexer/migrations/1666650701_create_stats_table.sql b/packages/eventindexer/migrations/1666650701_create_stats_table.sql index 3d3c9c5f44..9a8ea8a6e9 100644 --- a/packages/eventindexer/migrations/1666650701_create_stats_table.sql +++ b/packages/eventindexer/migrations/1666650701_create_stats_table.sql @@ -2,8 +2,8 @@ -- +goose StatementBegin CREATE TABLE IF NOT EXISTS stats ( id int NOT NULL PRIMARY KEY AUTO_INCREMENT, - average_proof_time int NOT NULL DEFAULT 0, - average_proof_reward int NOT NULL DEFAULT 0, + average_proof_time VARCHAR(255) NOT NULL DEFAULT "0", + average_proof_reward VARCHAR(255) NOT NULL DEFAULT "0", num_proofs int NOT NULL default 0, num_verified_blocks int NOT NULL default 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP , diff --git a/packages/eventindexer/mock/stat_repository.go b/packages/eventindexer/mock/stat_repository.go index 4645af5652..f49d29b01f 100644 --- a/packages/eventindexer/mock/stat_repository.go +++ b/packages/eventindexer/mock/stat_repository.go @@ -14,10 +14,20 @@ func NewStatRepository() *StatRepository { return &StatRepository{} } func (r *StatRepository) Save(ctx context.Context, opts eventindexer.SaveStatOpts) (*eventindexer.Stat, error) { + proofReward := "" + if opts.ProofReward != nil { + proofReward = opts.ProofReward.String() + } + + proofTime := "" + if opts.ProofTime != nil { + proofTime = opts.ProofTime.String() + } + r.stats = &eventindexer.Stat{ ID: 1, - AverageProofTime: *opts.ProofTime, - AverageProofReward: *opts.ProofReward, + AverageProofTime: proofTime, + AverageProofReward: proofReward, NumProofs: 1, NumVerifiedBlocks: 1, } diff --git a/packages/eventindexer/repo/stat.go b/packages/eventindexer/repo/stat.go index 711091bd03..65174abb91 100644 --- a/packages/eventindexer/repo/stat.go +++ b/packages/eventindexer/repo/stat.go @@ -33,12 +33,12 @@ func (r *StatRepository) Save(ctx context.Context, opts eventindexer.SaveStatOpt if opts.ProofReward != nil { s.NumVerifiedBlocks++ - s.AverageProofReward = *opts.ProofReward + s.AverageProofReward = opts.ProofReward.String() } if opts.ProofTime != nil { s.NumProofs++ - s.AverageProofTime = *opts.ProofTime + s.AverageProofTime = opts.ProofTime.String() } if err := r.db.GormDB().Save(s).Error; err != nil { @@ -58,5 +58,13 @@ func (r *StatRepository) Find(ctx context.Context) (*eventindexer.Stat, error) { return nil, errors.Wrap(err, "r.db.gormDB.FirstOrCreate") } + if s.AverageProofReward == "" { + s.AverageProofReward = "0" + } + + if s.AverageProofTime == "" { + s.AverageProofTime = "0" + } + return s, nil } diff --git a/packages/eventindexer/repo/stat_test.go b/packages/eventindexer/repo/stat_test.go index 1a5d4364eb..1c7d9128c3 100644 --- a/packages/eventindexer/repo/stat_test.go +++ b/packages/eventindexer/repo/stat_test.go @@ -2,6 +2,7 @@ package repo import ( "context" + "math/big" "testing" "github.com/davecgh/go-spew/spew" @@ -18,7 +19,7 @@ func TestIntegration_Stat_Save(t *testing.T) { statRepo, err := NewStatRepository(db) assert.Equal(t, nil, err) - var proofReward uint64 = 4 + var proofReward = big.NewInt(4) tests := []struct { name string @@ -28,7 +29,7 @@ func TestIntegration_Stat_Save(t *testing.T) { { "successProofReward", eventindexer.SaveStatOpts{ - ProofReward: &proofReward, + ProofReward: proofReward, }, nil, }, @@ -51,10 +52,10 @@ func TestIntegration_Stat_Find(t *testing.T) { statRepo, err := NewStatRepository(db) assert.Equal(t, nil, err) - var proofReward uint64 = 4 + var proofReward = big.NewInt(4) _, err = statRepo.Save(context.Background(), eventindexer.SaveStatOpts{ - ProofReward: &proofReward, + ProofReward: proofReward, }) assert.Equal(t, nil, err) @@ -68,8 +69,8 @@ func TestIntegration_Stat_Find(t *testing.T) { "success", &eventindexer.Stat{ ID: 1, - AverageProofReward: 4, - AverageProofTime: 0, + AverageProofReward: proofReward.String(), + AverageProofTime: "0", NumProofs: 0, NumVerifiedBlocks: 1, }, diff --git a/packages/eventindexer/stat.go b/packages/eventindexer/stat.go index 57dc57ff1f..58752298b6 100644 --- a/packages/eventindexer/stat.go +++ b/packages/eventindexer/stat.go @@ -2,6 +2,7 @@ package eventindexer import ( "context" + "math/big" ) // Event represents a stored EVM event. The fields will be serialized @@ -9,16 +10,16 @@ import ( // dependant on the name of the event type Stat struct { ID int `json:"id"` - AverageProofTime uint64 `json:"averageProofTime"` - AverageProofReward uint64 `json:"averageProofReward"` + AverageProofTime string `json:"averageProofTime"` + AverageProofReward string `json:"averageProofReward"` NumProofs uint64 `json:"numProofs"` NumVerifiedBlocks uint64 `json:"numVerifiedBlocks"` } // SaveStatOpts type SaveStatOpts struct { - ProofTime *uint64 - ProofReward *uint64 + ProofTime *big.Int + ProofReward *big.Int } // StatRepository is used to interact with stats in the store