You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

299 lines
12 KiB

4 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
3 years ago
3 years ago
Redo coordinator structure, connect API to node - API: - Modify the constructor so that hardcoded rollup constants don't need to be passed (introduce a `Config` and use `configAPI` internally) - Common: - Update rollup constants with proper *big.Int when required - Add BidCoordinator and Slot structs used by the HistoryDB and Synchronizer. - Add helper methods to AuctionConstants - AuctionVariables: Add column `DefaultSlotSetBidSlotNum` (in the SQL table: `default_slot_set_bid_slot_num`), which indicates at which slotNum does the `DefaultSlotSetBid` specified starts applying. - Config: - Move coordinator exclusive configuration from the node config to the coordinator config - Coordinator: - Reorganize the code towards having the goroutines started and stopped from the coordinator itself instead of the node. - Remove all stop and stopped channels, and use context.Context and sync.WaitGroup instead. - Remove BatchInfo setters and assing variables directly - In ServerProof and ServerProofPool use context instead stop channel. - Use message passing to notify the coordinator about sync updates and reorgs - Introduce the Pipeline, which can be started and stopped by the Coordinator - Introduce the TxManager, which manages ethereum transactions (the TxManager is also in charge of making the forge call to the rollup smart contract). The TxManager keeps ethereum transactions and: 1. Waits for the transaction to be accepted 2. Waits for the transaction to be confirmed for N blocks - In forge logic, first prepare a batch and then wait for an available server proof to have all work ready once the proof server is ready. - Remove the `isForgeSequence` method which was querying the smart contract, and instead use notifications sent by the Synchronizer to figure out if it's forging time. - Update test (which is a minimal test to manually see if the coordinator starts) - HistoryDB: - Add method to get the number of batches in a slot (used to detect when a slot has passed the bid winner forging deadline) - Add method to get the best bid and associated coordinator of a slot (used to detect the forgerAddress that can forge the slot) - General: - Rename some instances of `currentBlock` to `lastBlock` to be more clear. - Node: - Connect the API to the node and call the methods to update cached state when the sync advances blocks. - Call methods to update Coordinator state when the sync advances blocks and finds reorgs. - Synchronizer: - Add Auction field in the Stats, which contain the current slot with info about highest bidder and other related info required to know who can forge in the current block. - Better organization of cached state: - On Sync, update the internal cached state - On Init or Reorg, load the state from HistoryDB into the internal cached state.
4 years ago
Redo coordinator structure, connect API to node - API: - Modify the constructor so that hardcoded rollup constants don't need to be passed (introduce a `Config` and use `configAPI` internally) - Common: - Update rollup constants with proper *big.Int when required - Add BidCoordinator and Slot structs used by the HistoryDB and Synchronizer. - Add helper methods to AuctionConstants - AuctionVariables: Add column `DefaultSlotSetBidSlotNum` (in the SQL table: `default_slot_set_bid_slot_num`), which indicates at which slotNum does the `DefaultSlotSetBid` specified starts applying. - Config: - Move coordinator exclusive configuration from the node config to the coordinator config - Coordinator: - Reorganize the code towards having the goroutines started and stopped from the coordinator itself instead of the node. - Remove all stop and stopped channels, and use context.Context and sync.WaitGroup instead. - Remove BatchInfo setters and assing variables directly - In ServerProof and ServerProofPool use context instead stop channel. - Use message passing to notify the coordinator about sync updates and reorgs - Introduce the Pipeline, which can be started and stopped by the Coordinator - Introduce the TxManager, which manages ethereum transactions (the TxManager is also in charge of making the forge call to the rollup smart contract). The TxManager keeps ethereum transactions and: 1. Waits for the transaction to be accepted 2. Waits for the transaction to be confirmed for N blocks - In forge logic, first prepare a batch and then wait for an available server proof to have all work ready once the proof server is ready. - Remove the `isForgeSequence` method which was querying the smart contract, and instead use notifications sent by the Synchronizer to figure out if it's forging time. - Update test (which is a minimal test to manually see if the coordinator starts) - HistoryDB: - Add method to get the number of batches in a slot (used to detect when a slot has passed the bid winner forging deadline) - Add method to get the best bid and associated coordinator of a slot (used to detect the forgerAddress that can forge the slot) - General: - Rename some instances of `currentBlock` to `lastBlock` to be more clear. - Node: - Connect the API to the node and call the methods to update cached state when the sync advances blocks. - Call methods to update Coordinator state when the sync advances blocks and finds reorgs. - Synchronizer: - Add Auction field in the Stats, which contain the current slot with info about highest bidder and other related info required to know who can forge in the current block. - Better organization of cached state: - On Sync, update the internal cached state - On Init or Reorg, load the state from HistoryDB into the internal cached state.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
Redo coordinator structure, connect API to node - API: - Modify the constructor so that hardcoded rollup constants don't need to be passed (introduce a `Config` and use `configAPI` internally) - Common: - Update rollup constants with proper *big.Int when required - Add BidCoordinator and Slot structs used by the HistoryDB and Synchronizer. - Add helper methods to AuctionConstants - AuctionVariables: Add column `DefaultSlotSetBidSlotNum` (in the SQL table: `default_slot_set_bid_slot_num`), which indicates at which slotNum does the `DefaultSlotSetBid` specified starts applying. - Config: - Move coordinator exclusive configuration from the node config to the coordinator config - Coordinator: - Reorganize the code towards having the goroutines started and stopped from the coordinator itself instead of the node. - Remove all stop and stopped channels, and use context.Context and sync.WaitGroup instead. - Remove BatchInfo setters and assing variables directly - In ServerProof and ServerProofPool use context instead stop channel. - Use message passing to notify the coordinator about sync updates and reorgs - Introduce the Pipeline, which can be started and stopped by the Coordinator - Introduce the TxManager, which manages ethereum transactions (the TxManager is also in charge of making the forge call to the rollup smart contract). The TxManager keeps ethereum transactions and: 1. Waits for the transaction to be accepted 2. Waits for the transaction to be confirmed for N blocks - In forge logic, first prepare a batch and then wait for an available server proof to have all work ready once the proof server is ready. - Remove the `isForgeSequence` method which was querying the smart contract, and instead use notifications sent by the Synchronizer to figure out if it's forging time. - Update test (which is a minimal test to manually see if the coordinator starts) - HistoryDB: - Add method to get the number of batches in a slot (used to detect when a slot has passed the bid winner forging deadline) - Add method to get the best bid and associated coordinator of a slot (used to detect the forgerAddress that can forge the slot) - General: - Rename some instances of `currentBlock` to `lastBlock` to be more clear. - Node: - Connect the API to the node and call the methods to update cached state when the sync advances blocks. - Call methods to update Coordinator state when the sync advances blocks and finds reorgs. - Synchronizer: - Add Auction field in the Stats, which contain the current slot with info about highest bidder and other related info required to know who can forge in the current block. - Better organization of cached state: - On Sync, update the internal cached state - On Init or Reorg, load the state from HistoryDB into the internal cached state.
4 years ago
Update coordinator, call all api update functions - Common: - Rename Block.EthBlockNum to Block.Num to avoid unneeded repetition - API: - Add UpdateNetworkInfoBlock to update just block information, to be used when the node is not yet synchronized - Node: - Call API.UpdateMetrics and UpdateRecommendedFee in a loop, with configurable time intervals - Synchronizer: - When mapping events by TxHash, use an array to support the possibility of multiple calls of the same function happening in the same transaction (for example, a smart contract in a single transaction could call withdraw with delay twice, which would generate 2 withdraw events, and 2 deposit events). - In Stats, keep entire LastBlock instead of just the blockNum - In Stats, add lastL1BatchBlock - Test Stats and SCVars - Coordinator: - Enable writing the BatchInfo in every step of the pipeline to disk (with JSON text files) for debugging purposes. - Move the Pipeline functionality from the Coordinator to its own struct (Pipeline) - Implement shouldL1lL2Batch - In TxManager, implement logic to perform several attempts when doing ethereum node RPC calls before considering the error. (Both for calls to forgeBatch and transaction receipt) - In TxManager, reorganize the flow and note the specific points in which actions are made when err != nil - HistoryDB: - Implement GetLastL1BatchBlockNum: returns the blockNum of the latest forged l1Batch, to help the coordinator decide when to forge an L1Batch. - EthereumClient and test.Client: - Update EthBlockByNumber to return the last block when the passed number is -1.
4 years ago
Update missing parts, improve til, and more - Node - Updated configuration to initialize the interface to all the smart contracts - Common - Moved BlockData and BatchData types to common so that they can be shared among: historydb, til and synchronizer - Remove hash.go (it was never used) - Remove slot.go (it was never used) - Remove smartcontractparams.go (it was never used, and appropriate structs are defined in `eth/`) - Comment state / status method until requirements of this method are properly defined, and move it to Synchronizer - Synchronizer - Simplify `Sync` routine to only sync one block per call, and return useful information. - Use BlockData and BatchData from common - Check that events belong to the expected block hash - In L1Batch, query L1UserTxs from HistoryDB - Fill ERC20 token information - Test AddTokens with test.Client - HistryDB - Use BlockData and BatchData from common - Add `GetAllTokens` method - Uncomment and update GetL1UserTxs (with corresponding tests) - Til - Rename all instances of RegisterToken to AddToken (to follow the smart contract implementation naming) - Use BlockData and BatchData from common - Move testL1CoordinatorTxs and testL2Txs to a separate struct from BatchData in Context - Start Context with BatchNum = 1 (which the protocol defines to be the first batchNum) - In every Batch, set StateRoot and ExitRoot to a non-nil big.Int (zero). - In all L1Txs, if LoadAmount is not used, set it to 0; if Amount is not used, set it to 0; so that no *big.Int is nil. - In L1UserTx, don't set BatchNum, because when L1UserTxs are created and obtained by the synchronizer, the BatchNum is not known yet (it's a synchronizer job to set it) - In L1UserTxs, set `UserOrigin` and set `ToForgeL1TxsNum`.
4 years ago
  1. package config
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "math/big"
  6. "time"
  7. "github.com/BurntSushi/toml"
  8. ethCommon "github.com/ethereum/go-ethereum/common"
  9. "github.com/hermeznetwork/hermez-node/common"
  10. "github.com/hermeznetwork/tracerr"
  11. "github.com/iden3/go-iden3-crypto/babyjub"
  12. "gopkg.in/go-playground/validator.v9"
  13. )
  14. // Duration is a wrapper type that parses time duration from text.
  15. type Duration struct {
  16. time.Duration `validate:"required"`
  17. }
  18. // UnmarshalText unmarshalls time duration from text.
  19. func (d *Duration) UnmarshalText(data []byte) error {
  20. duration, err := time.ParseDuration(string(data))
  21. if err != nil {
  22. return tracerr.Wrap(err)
  23. }
  24. d.Duration = duration
  25. return nil
  26. }
  27. // ServerProof is the server proof configuration data.
  28. type ServerProof struct {
  29. // URL is the server proof API URL
  30. URL string `validate:"required"`
  31. }
  32. // Coordinator is the coordinator specific configuration.
  33. type Coordinator struct {
  34. // ForgerAddress is the address under which this coordinator is forging
  35. ForgerAddress ethCommon.Address `validate:"required"`
  36. // FeeAccount is the Hermez account that the coordinator uses to receive fees
  37. FeeAccount struct {
  38. // Address is the ethereum address of the account to receive fees
  39. Address ethCommon.Address `validate:"required"`
  40. // BJJ is the baby jub jub public key of the account to receive fees
  41. BJJ babyjub.PublicKeyComp `validate:"required"`
  42. } `validate:"required"`
  43. // ConfirmBlocks is the number of confirmation blocks to wait for sent
  44. // ethereum transactions before forgetting about them
  45. ConfirmBlocks int64 `validate:"required"`
  46. // L1BatchTimeoutPerc is the portion of the range before the L1Batch
  47. // timeout that will trigger a schedule to forge an L1Batch
  48. L1BatchTimeoutPerc float64 `validate:"required"`
  49. // StartSlotBlocksDelay is the number of blocks of delay to wait before
  50. // starting the pipeline when we reach a slot in which we can forge.
  51. StartSlotBlocksDelay int64
  52. // ScheduleBatchBlocksAheadCheck is the number of blocks ahead in which
  53. // the forger address is checked to be allowed to forge (apart from
  54. // checking the next block), used to decide when to stop scheduling new
  55. // batches (by stopping the pipeline).
  56. // For example, if we are at block 10 and ScheduleBatchBlocksAheadCheck
  57. // is 5, eventhough at block 11 we canForge, the pipeline will be
  58. // stopped if we can't forge at block 15.
  59. // This value should be the expected number of blocks it takes between
  60. // scheduling a batch and having it mined.
  61. ScheduleBatchBlocksAheadCheck int64
  62. // SendBatchBlocksMarginCheck is the number of margin blocks ahead in
  63. // which the coordinator is also checked to be allowed to forge, apart
  64. // from the next block; used to decide when to stop sending batches to
  65. // the smart contract.
  66. // For example, if we are at block 10 and SendBatchBlocksMarginCheck is
  67. // 5, eventhough at block 11 we canForge, the batch will be discarded
  68. // if we can't forge at block 15.
  69. SendBatchBlocksMarginCheck int64
  70. // ProofServerPollInterval is the waiting interval between polling the
  71. // ProofServer while waiting for a particular status
  72. ProofServerPollInterval Duration `validate:"required"`
  73. // ForgeRetryInterval is the waiting interval between calls forge a
  74. // batch after an error
  75. ForgeRetryInterval Duration `validate:"required"`
  76. // SyncRetryInterval is the waiting interval between calls to the main
  77. // handler of a synced block after an error
  78. SyncRetryInterval Duration `validate:"required"`
  79. // L2DB is the DB that holds the pool of L2Txs
  80. L2DB struct {
  81. // SafetyPeriod is the number of batches after which
  82. // non-pending L2Txs are deleted from the pool
  83. SafetyPeriod common.BatchNum `validate:"required"`
  84. // MaxTxs is the number of L2Txs that once reached triggers
  85. // deletion of old L2Txs
  86. MaxTxs uint32 `validate:"required"`
  87. // TTL is the Time To Live for L2Txs in the pool. Once MaxTxs
  88. // L2Txs is reached, L2Txs older than TTL will be deleted.
  89. TTL Duration `validate:"required"`
  90. // PurgeBatchDelay is the delay between batches to purge outdated transactions
  91. PurgeBatchDelay int64 `validate:"required"`
  92. // InvalidateBatchDelay is the delay between batches to mark invalid transactions
  93. InvalidateBatchDelay int64 `validate:"required"`
  94. // PurgeBlockDelay is the delay between blocks to purge outdated transactions
  95. PurgeBlockDelay int64 `validate:"required"`
  96. // InvalidateBlockDelay is the delay between blocks to mark invalid transactions
  97. InvalidateBlockDelay int64 `validate:"required"`
  98. } `validate:"required"`
  99. TxSelector struct {
  100. // Path where the TxSelector StateDB is stored
  101. Path string `validate:"required"`
  102. } `validate:"required"`
  103. BatchBuilder struct {
  104. // Path where the BatchBuilder StateDB is stored
  105. Path string `validate:"required"`
  106. } `validate:"required"`
  107. ServerProofs []ServerProof `validate:"required"`
  108. Circuit struct {
  109. // MaxTx is the maximum number of txs supported by the circuit
  110. MaxTx int64 `validate:"required"`
  111. // NLevels is the maximum number of merkle tree levels
  112. // supported by the circuit
  113. NLevels int64 `validate:"required"`
  114. } `validate:"required"`
  115. EthClient struct {
  116. // CallGasLimit is the default gas limit set for ethereum
  117. // calls, except for methods where a particular gas limit is
  118. // harcoded because it's known to be a big value
  119. CallGasLimit uint64 `validate:"required"`
  120. // MaxGasPrice is the maximum gas price allowed for ethereum
  121. // transactions
  122. MaxGasPrice *big.Int `validate:"required"`
  123. // GasPriceDiv is the gas price division
  124. GasPriceDiv uint64 `validate:"required"`
  125. // CheckLoopInterval is the waiting interval between receipt
  126. // checks of ethereum transactions in the TxManager
  127. CheckLoopInterval Duration `validate:"required"`
  128. // Attempts is the number of attempts to do an eth client RPC
  129. // call before giving up
  130. Attempts int `validate:"required"`
  131. // AttemptsDelay is delay between attempts do do an eth client
  132. // RPC call
  133. AttemptsDelay Duration `validate:"required"`
  134. // TxResendTimeout is the timeout after which a non-mined
  135. // ethereum transaction will be resent (reusing the nonce) with
  136. // a newly calculated gas price
  137. TxResendTimeout Duration `validate:"required"`
  138. // NoReuseNonce disables reusing nonces of pending transactions for
  139. // new replacement transactions
  140. NoReuseNonce bool
  141. // Keystore is the ethereum keystore where private keys are kept
  142. Keystore struct {
  143. // Path to the keystore
  144. Path string `validate:"required"`
  145. // Password used to decrypt the keys in the keystore
  146. Password string `validate:"required"`
  147. } `validate:"required"`
  148. } `validate:"required"`
  149. API struct {
  150. // Coordinator enables the coordinator API endpoints
  151. Coordinator bool
  152. } `validate:"required"`
  153. Debug struct {
  154. // BatchPath if set, specifies the path where batchInfo is stored
  155. // in JSON in every step/update of the pipeline
  156. BatchPath string
  157. // LightScrypt if set, uses light parameters for the ethereum
  158. // keystore encryption algorithm.
  159. LightScrypt bool
  160. // RollupVerifierIndex is the index of the verifier to use in
  161. // the Rollup smart contract. The verifier chosen by index
  162. // must match with the Circuit parameters.
  163. RollupVerifierIndex *int
  164. }
  165. }
  166. // Node is the hermez node configuration.
  167. type Node struct {
  168. PriceUpdater struct {
  169. // Interval between price updater calls
  170. Interval Duration `valudate:"required"`
  171. // URL of the token prices provider
  172. URL string `valudate:"required"`
  173. // Type of the API of the token prices provider
  174. Type string `valudate:"required"`
  175. } `validate:"required"`
  176. StateDB struct {
  177. // Path where the synchronizer StateDB is stored
  178. Path string `validate:"required"`
  179. // Keep is the number of checkpoints to keep
  180. Keep int `validate:"required"`
  181. } `validate:"required"`
  182. PostgreSQL struct {
  183. // Port of the PostgreSQL server
  184. Port int `validate:"required"`
  185. // Host of the PostgreSQL server
  186. Host string `validate:"required"`
  187. // User of the PostgreSQL server
  188. User string `validate:"required"`
  189. // Password of the PostgreSQL server
  190. Password string `validate:"required"`
  191. // Name of the PostgreSQL server database
  192. Name string `validate:"required"`
  193. } `validate:"required"`
  194. Web3 struct {
  195. // URL is the URL of the web3 ethereum-node RPC server
  196. URL string `validate:"required"`
  197. } `validate:"required"`
  198. Synchronizer struct {
  199. // SyncLoopInterval is the interval between attempts to
  200. // synchronize a new block from an ethereum node
  201. SyncLoopInterval Duration `validate:"required"`
  202. // StatsRefreshPeriod is the interval between updates of the
  203. // synchronizer state Eth parameters (`Eth.LastBlock` and
  204. // `Eth.LastBatch`). This value only affects the reported % of
  205. // synchronization of blocks and batches, nothing else.
  206. StatsRefreshPeriod Duration `validate:"required"`
  207. } `validate:"required"`
  208. SmartContracts struct {
  209. // Rollup is the address of the Hermez.sol smart contract
  210. Rollup ethCommon.Address `validate:"required"`
  211. // Rollup is the address of the HermezAuctionProtocol.sol smart
  212. // contract
  213. Auction ethCommon.Address `validate:"required"`
  214. // WDelayer is the address of the WithdrawalDelayer.sol smart
  215. // contract
  216. WDelayer ethCommon.Address `validate:"required"`
  217. // TokenHEZ is the address of the HEZTokenFull.sol smart
  218. // contract
  219. TokenHEZ ethCommon.Address `validate:"required"`
  220. // TokenHEZName is the name of the HEZ token deployed at
  221. // TokenHEZ address
  222. TokenHEZName string `validate:"required"`
  223. } `validate:"required"`
  224. API struct {
  225. // Address where the API will listen if set
  226. Address string
  227. // Explorer enables the Explorer API endpoints
  228. Explorer bool
  229. // UpdateMetricsInterval is the interval between updates of the
  230. // API metrics
  231. UpdateMetricsInterval Duration
  232. // UpdateRecommendedFeeInterval is the interval between updates of the
  233. // recommended fees
  234. UpdateRecommendedFeeInterval Duration
  235. // Maximum concurrent connections allowed between API and SQL
  236. MaxSQLConnections int `validate:"required"`
  237. // SQLConnectionTimeout is the maximum amount of time that an API request
  238. // can wait to stablish a SQL connection
  239. SQLConnectionTimeout Duration
  240. } `validate:"required"`
  241. Debug struct {
  242. // APIAddress is the address where the debugAPI will listen if
  243. // set
  244. APIAddress string
  245. // MeddlerLogs enables meddler debug mode, where unused columns and struct
  246. // fields will be logged
  247. MeddlerLogs bool
  248. }
  249. Coordinator Coordinator `validate:"-"`
  250. }
  251. // Load loads a generic config.
  252. func Load(path string, cfg interface{}) error {
  253. bs, err := ioutil.ReadFile(path) //nolint:gosec
  254. if err != nil {
  255. return tracerr.Wrap(err)
  256. }
  257. cfgToml := string(bs)
  258. if _, err := toml.Decode(cfgToml, cfg); err != nil {
  259. return tracerr.Wrap(err)
  260. }
  261. return nil
  262. }
  263. // LoadCoordinator loads the Coordinator configuration from path.
  264. func LoadCoordinator(path string) (*Node, error) {
  265. var cfg Node
  266. if err := Load(path, &cfg); err != nil {
  267. return nil, tracerr.Wrap(fmt.Errorf("error loading node configuration file: %w", err))
  268. }
  269. validate := validator.New()
  270. if err := validate.Struct(cfg); err != nil {
  271. return nil, tracerr.Wrap(fmt.Errorf("error validating configuration file: %w", err))
  272. }
  273. if err := validate.Struct(cfg.Coordinator); err != nil {
  274. return nil, tracerr.Wrap(fmt.Errorf("error validating configuration file: %w", err))
  275. }
  276. return &cfg, nil
  277. }
  278. // LoadNode loads the Node configuration from path.
  279. func LoadNode(path string) (*Node, error) {
  280. var cfg Node
  281. if err := Load(path, &cfg); err != nil {
  282. return nil, tracerr.Wrap(fmt.Errorf("error loading node configuration file: %w", err))
  283. }
  284. validate := validator.New()
  285. if err := validate.Struct(cfg); err != nil {
  286. return nil, tracerr.Wrap(fmt.Errorf("error validating configuration file: %w", err))
  287. }
  288. return &cfg, nil
  289. }