@@ -7,12 +7,54 @@ import (
77 "context"
88 "errors"
99 "fmt"
10+ "math/big"
1011
1112 . "github.com/cartesi/rollups-node/internal/model"
1213 "github.com/ethereum/go-ethereum/accounts/abi/bind"
1314 "github.com/ethereum/go-ethereum/common"
1415)
1516
17+ func findSafeFirstInputBlockToScan (app * appContracts , mostRecentBlockNumber uint64 , mostRecentBlockNumberCallOpts * bind.CallOpts ) uint64 {
18+ var noiBig * big.Int
19+ var err error
20+
21+ // find if the application has ever received any input. sync to present if not
22+ noiBig , err = app .inputSource .GetNumberOfInputs (
23+ mostRecentBlockNumberCallOpts ,
24+ app .application .IApplicationAddress ,
25+ )
26+ if err != nil {
27+ return app .application .LastInputCheckBlock
28+ }
29+ if noiBig .Uint64 () == 0 {
30+ return mostRecentBlockNumber
31+ }
32+
33+ // find if the application has received an input since its deployment. sync to that block if not
34+ // we'll need its deployment block number to do that
35+ deploymentBlockNumberBig , err := app .applicationContract .GetDeploymentBlockNumber (mostRecentBlockNumberCallOpts )
36+ if err != nil {
37+ return app .application .LastInputCheckBlock
38+ }
39+
40+ noiBig , err = app .inputSource .GetNumberOfInputs (& bind.CallOpts {
41+ BlockNumber : deploymentBlockNumberBig ,
42+ },
43+ app .application .IApplicationAddress ,
44+ )
45+ if err != nil {
46+ return app .application .LastInputCheckBlock
47+ }
48+ if noiBig .Uint64 () == 0 {
49+ return deploymentBlockNumberBig .Uint64 ()
50+ }
51+
52+ // TODO(mpolitzer): Applicaiton has inputs previous to its deployment. We can reduce the number of blocks to scan by
53+ // doing a binary search over GetNumberOfInputs and finding the block where 0 -> 1 transition happens. As a simpler,
54+ // also correct implementation. We return the first possible block an input could appear on.
55+ return app .application .IInputBoxBlock
56+ }
57+
1658// checkForNewInputs checks if is there new Inputs for all running Applications
1759func (r * Service ) checkForNewInputs (
1860 ctx context.Context ,
@@ -25,6 +67,10 @@ func (r *Service) checkForNewInputs(
2567
2668 r .Logger .Debug ("Checking for new inputs" )
2769
70+ mostRecentBlockNumberCallOpts := & bind.CallOpts {
71+ BlockNumber : new (big.Int ).SetUint64 (mostRecentBlockNumber ),
72+ }
73+
2874 appsByInputBox := map [common.Address ][]appContracts {}
2975 for _ , app := range applications {
3076 if ! app .application .HasDataAvailabilitySelector (DataAvailability_InputBox ) {
@@ -39,18 +85,27 @@ func (r *Service) checkForNewInputs(
3985 "inputbox_address" , inputBoxAddress ,
4086 "most recent block" , mostRecentBlockNumber ,
4187 )
42- appsByLastInputCheckBlock := indexApps (byLastInputCheckBlock , inputBoxApps )
88+
89+ appsByLastInputCheckBlock := make (map [uint64 ][]appContracts )
90+ for _ , app := range inputBoxApps {
91+ lastInputCheckBlock := app .application .LastInputCheckBlock
92+ if lastInputCheckBlock == 0 { // New application. Find a safe start block to scan for inputs
93+ lastInputCheckBlock = findSafeFirstInputBlockToScan (& app ,
94+ mostRecentBlockNumber ,
95+ mostRecentBlockNumberCallOpts ,
96+ ) - 1
97+ r .Logger .Info ("Fast sync application inputs" ,
98+ "application" , app .application .Name ,
99+ "start_block" , lastInputCheckBlock ,
100+ )
101+ app .application .LastInputCheckBlock = lastInputCheckBlock
102+ }
103+ appsByLastInputCheckBlock [lastInputCheckBlock ] = append (appsByLastInputCheckBlock [lastInputCheckBlock ], app )
104+ }
43105
44106 for lastProcessedBlock , apps := range appsByLastInputCheckBlock {
45107 appAddresses := appsToAddresses (apps )
46108
47- // Only check blocks starting from the block where the InputBox
48- // contract was deployed as Inputs can be added to that same block
49- inputBoxDeploymentBlock := apps [0 ].application .IInputBoxBlock
50- if lastProcessedBlock < inputBoxDeploymentBlock {
51- lastProcessedBlock = inputBoxDeploymentBlock - 1
52- }
53-
54109 if mostRecentBlockNumber > lastProcessedBlock {
55110
56111 r .Logger .Debug ("Checking inputs for applications" ,
@@ -340,8 +395,3 @@ func (r *Service) readInputsFromBlockchain(
340395 }
341396 return appInputsMap , nil
342397}
343-
344- // byLastInputCheckBlock key extractor function intended to be used with `indexApps` function
345- func byLastInputCheckBlock (app appContracts ) uint64 {
346- return app .application .LastInputCheckBlock
347- }
0 commit comments