1414// You should have received a copy of the GNU Lesser General Public License
1515// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
1616
17- package les
17+ // Package checkpointoracle is a wrapper of checkpoint oracle contract with
18+ // additional rules defined. This package can be used both in LES client or
19+ // server side for offering oracle related APIs.
20+ package checkpointoracle
1821
1922import (
2023 "encoding/binary"
@@ -28,19 +31,19 @@ import (
2831 "github.com/ethereum/go-ethereum/params"
2932)
3033
31- // checkpointOracle is responsible for offering the latest stable checkpoint
32- // generated and announced by the contract admins on-chain. The checkpoint is
33- // verified by clients locally during the checkpoint syncing.
34- type checkpointOracle struct {
34+ // CheckpointOracle is responsible for offering the latest stable checkpoint
35+ // generated and announced by the contract admins on-chain. The checkpoint can
36+ // be verified by clients locally during the checkpoint syncing.
37+ type CheckpointOracle struct {
3538 config * params.CheckpointOracleConfig
3639 contract * checkpointoracle.CheckpointOracle
3740
3841 running int32 // Flag whether the contract backend is set or not
3942 getLocal func (uint64 ) params.TrustedCheckpoint // Function used to retrieve local checkpoint
4043}
4144
42- // newCheckpointOracle returns a checkpoint registrar handler.
43- func newCheckpointOracle (config * params.CheckpointOracleConfig , getLocal func (uint64 ) params.TrustedCheckpoint ) * checkpointOracle {
45+ // New creates a checkpoint oracle handler with given configs and callback .
46+ func New (config * params.CheckpointOracleConfig , getLocal func (uint64 ) params.TrustedCheckpoint ) * CheckpointOracle {
4447 if config == nil {
4548 log .Info ("Checkpoint registrar is not enabled" )
4649 return nil
@@ -51,61 +54,65 @@ func newCheckpointOracle(config *params.CheckpointOracleConfig, getLocal func(ui
5154 }
5255 log .Info ("Configured checkpoint registrar" , "address" , config .Address , "signers" , len (config .Signers ), "threshold" , config .Threshold )
5356
54- return & checkpointOracle {
57+ return & CheckpointOracle {
5558 config : config ,
5659 getLocal : getLocal ,
5760 }
5861}
5962
60- // start binds the registrar contract and start listening to the
61- // newCheckpointEvent for the server side .
62- func (reg * checkpointOracle ) start (backend bind.ContractBackend ) {
63- contract , err := checkpointoracle .NewCheckpointOracle (reg .config .Address , backend )
63+ // Start binds the contract backend, initializes the oracle instance
64+ // and marks the status as available .
65+ func (oracle * CheckpointOracle ) Start (backend bind.ContractBackend ) {
66+ contract , err := checkpointoracle .NewCheckpointOracle (oracle .config .Address , backend )
6467 if err != nil {
6568 log .Error ("Oracle contract binding failed" , "err" , err )
6669 return
6770 }
68- if ! atomic .CompareAndSwapInt32 (& reg .running , 0 , 1 ) {
71+ if ! atomic .CompareAndSwapInt32 (& oracle .running , 0 , 1 ) {
6972 log .Error ("Already bound and listening to registrar" )
7073 return
7174 }
72- reg .contract = contract
75+ oracle .contract = contract
7376}
7477
75- // isRunning returns an indicator whether the registrar is running.
76- func (reg * checkpointOracle ) isRunning () bool {
77- return atomic .LoadInt32 (& reg .running ) == 1
78+ // IsRunning returns an indicator whether the oracle is running.
79+ func (oracle * CheckpointOracle ) IsRunning () bool {
80+ return atomic .LoadInt32 (& oracle .running ) == 1
7881}
7982
80- // stableCheckpoint returns the stable checkpoint which was generated by local
83+ // Contract returns the underlying raw checkpoint oracle contract.
84+ func (oracle * CheckpointOracle ) Contract () * checkpointoracle.CheckpointOracle {
85+ return oracle .contract
86+ }
87+
88+ // StableCheckpoint returns the stable checkpoint which was generated by local
8189// indexers and announced by trusted signers.
82- func (reg * checkpointOracle ) stableCheckpoint () (* params.TrustedCheckpoint , uint64 ) {
90+ func (oracle * CheckpointOracle ) StableCheckpoint () (* params.TrustedCheckpoint , uint64 ) {
8391 // Retrieve the latest checkpoint from the contract, abort if empty
84- latest , hash , height , err := reg .contract .Contract ().GetLatestCheckpoint (nil )
92+ latest , hash , height , err := oracle .contract .Contract ().GetLatestCheckpoint (nil )
8593 if err != nil || (latest == 0 && hash == [32 ]byte {}) {
8694 return nil , 0
8795 }
88- local := reg .getLocal (latest )
96+ local := oracle .getLocal (latest )
8997
9098 // The following scenarios may occur:
9199 //
92100 // * local node is out of sync so that it doesn't have the
93101 // checkpoint which registered in the contract.
94102 // * local checkpoint doesn't match with the registered one.
95103 //
96- // In both cases, server won't send the **stable** checkpoint
97- // to the client(no worry, client can use hardcoded one instead).
98- if local .HashEqual (common .Hash (hash )) {
104+ // In both cases, no stable checkpoint will be returned.
105+ if local .HashEqual (hash ) {
99106 return & local , height .Uint64 ()
100107 }
101108 return nil , 0
102109}
103110
104- // verifySigners recovers the signer addresses according to the signature and
111+ // VerifySigners recovers the signer addresses according to the signature and
105112// checks whether there are enough approvals to finalize the checkpoint.
106- func (reg * checkpointOracle ) verifySigners (index uint64 , hash [32 ]byte , signatures [][]byte ) (bool , []common.Address ) {
113+ func (oracle * CheckpointOracle ) VerifySigners (index uint64 , hash [32 ]byte , signatures [][]byte ) (bool , []common.Address ) {
107114 // Short circuit if the given signatures doesn't reach the threshold.
108- if len (signatures ) < int (reg .config .Threshold ) {
115+ if len (signatures ) < int (oracle .config .Threshold ) {
109116 return false , nil
110117 }
111118 var (
@@ -128,7 +135,7 @@ func (reg *checkpointOracle) verifySigners(index uint64, hash [32]byte, signatur
128135 // hash = keccak256(checkpoint_index, section_head, cht_root, bloom_root)
129136 buf := make ([]byte , 8 )
130137 binary .BigEndian .PutUint64 (buf , index )
131- data := append ([]byte {0x19 , 0x00 }, append (reg .config .Address .Bytes (), append (buf , hash [:]... )... )... )
138+ data := append ([]byte {0x19 , 0x00 }, append (oracle .config .Address .Bytes (), append (buf , hash [:]... )... )... )
132139 signatures [i ][64 ] -= 27 // Transform V from 27/28 to 0/1 according to the yellow paper for verification.
133140 pubkey , err := crypto .Ecrecover (crypto .Keccak256 (data ), signatures [i ])
134141 if err != nil {
@@ -139,14 +146,14 @@ func (reg *checkpointOracle) verifySigners(index uint64, hash [32]byte, signatur
139146 if _ , exist := checked [signer ]; exist {
140147 continue
141148 }
142- for _ , s := range reg .config .Signers {
149+ for _ , s := range oracle .config .Signers {
143150 if s == signer {
144151 signers = append (signers , signer )
145152 checked [signer ] = struct {}{}
146153 }
147154 }
148155 }
149- threshold := reg .config .Threshold
156+ threshold := oracle .config .Threshold
150157 if uint64 (len (signers )) < threshold {
151158 log .Warn ("Not enough signers to approve checkpoint" , "signers" , len (signers ), "threshold" , threshold )
152159 return false , nil
0 commit comments