@@ -7,12 +7,80 @@ import (
77 "context"
88 "errors"
99 "fmt"
10+ "math/big"
1011
1112 . "github.com/cartesi/rollups-node/internal/model"
13+ "github.com/cartesi/rollups-node/pkg/contracts/iinputbox"
1214 "github.com/ethereum/go-ethereum/accounts/abi/bind"
1315 "github.com/ethereum/go-ethereum/common"
16+ "github.com/ethereum/go-ethereum/ethclient"
1417)
1518
19+ // checkApplicationsWithNoInputAndSync is an optimization that updates the lastProcessedBlock of applications with
20+ // no inputs to the mostRecentBlockNumber, no need to check block ranges.
21+ // NOTE(mpolitzer): Ideally this only gets called when new applications are created or registered.
22+ func (r * Service ) syncApplicationsWithNoInput (
23+ ctx context.Context ,
24+ applications []appContracts ,
25+ iclient EthClientInterface ,
26+ mostRecentBlockNumber uint64 ,
27+ ) []error {
28+ errs := []error {}
29+
30+ // we need the concrete client type to interact with the contracts so we type assert
31+ // that works via a type switch
32+ var client * ethclient.Client
33+ switch unwrapped := iclient .(type ) {
34+ case * ethclient.Client :
35+ client = unwrapped
36+ default :
37+ return []error {fmt .Errorf ("error: unexpected type for ethclient" )}
38+ }
39+
40+ callOpts := bind.CallOpts {Context : ctx }
41+ zero := big .NewInt (0 )
42+ for _ , app := range applications {
43+ r .Logger .Debug ("Check application for fast sync" ,
44+ "application" , app .application .Name ,
45+ "last_input_check_block" , app .application .LastInputCheckBlock ,
46+ "input_box_block" , app .application .IInputBoxBlock ,
47+ )
48+
49+ // Only for input box
50+ if ! app .application .HasDataAvailabilitySelector (DataAvailability_InputBox ) {
51+ continue
52+ }
53+
54+ // and for applications that have not been synced yet
55+ if app .application .LastInputCheckBlock > app .application .IInputBoxBlock {
56+ continue
57+ }
58+
59+ iib , err := iinputbox .NewIInputBox (app .application .IInputBoxAddress , client )
60+ if err != nil {
61+ errs = append (errs , fmt .Errorf ("error: syncApplicationsWithNoInput failed to instantiate iinput box for application: %v" , app .application .IApplicationAddress ))
62+ continue
63+ }
64+
65+ nInputs , err := iib .GetNumberOfInputs (& callOpts , app .application .IApplicationAddress )
66+ if err != nil {
67+ errs = append (errs , fmt .Errorf ("error: syncApplicationsWithNoInput failed retrieve the number of inputs for application: %v" , app .application .IApplicationAddress ))
68+ continue
69+ }
70+
71+ if nInputs .Cmp (zero ) == 0 {
72+ r .Logger .Info ("Fast sync last input block" ,
73+ "application" , app .application .Name ,
74+ "from" , app .application .LastInputCheckBlock ,
75+ "to" , mostRecentBlockNumber )
76+
77+ // leave DB interaction to checkForNewInputs
78+ app .application .LastInputCheckBlock = mostRecentBlockNumber - 1
79+ }
80+ }
81+ return nil
82+ }
83+
1684// checkForNewInputs checks if is there new Inputs for all running Applications
1785func (r * Service ) checkForNewInputs (
1886 ctx context.Context ,
0 commit comments