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.

345 lines
16 KiB

4 years ago
4 years ago
4 years ago
  1. package historydb
  2. import (
  3. "encoding/json"
  4. "math/big"
  5. "time"
  6. ethCommon "github.com/ethereum/go-ethereum/common"
  7. "github.com/hermeznetwork/hermez-node/apitypes"
  8. "github.com/hermeznetwork/hermez-node/common"
  9. "github.com/iden3/go-iden3-crypto/babyjub"
  10. "github.com/iden3/go-merkletree"
  11. )
  12. // TxAPI is a representation of a generic Tx with additional information
  13. // required by the API, and extracted by joining block and token tables
  14. type TxAPI struct {
  15. // Generic
  16. IsL1 bool `meddler:"is_l1"`
  17. TxID common.TxID `meddler:"id"`
  18. ItemID uint64 `meddler:"item_id"`
  19. Type common.TxType `meddler:"type"`
  20. Position int `meddler:"position"`
  21. FromIdx *apitypes.HezIdx `meddler:"from_idx"`
  22. FromEthAddr *apitypes.HezEthAddr `meddler:"from_eth_addr"`
  23. FromBJJ *apitypes.HezBJJ `meddler:"from_bjj"`
  24. ToIdx apitypes.HezIdx `meddler:"to_idx"`
  25. ToEthAddr *apitypes.HezEthAddr `meddler:"to_eth_addr"`
  26. ToBJJ *apitypes.HezBJJ `meddler:"to_bjj"`
  27. Amount apitypes.BigIntStr `meddler:"amount"`
  28. HistoricUSD *float64 `meddler:"amount_usd"`
  29. BatchNum *common.BatchNum `meddler:"batch_num"` // batchNum in which this tx was forged. If the tx is L2, this must be != 0
  30. EthBlockNum int64 `meddler:"eth_block_num"` // Ethereum Block Number in which this L1Tx was added to the queue
  31. // L1
  32. ToForgeL1TxsNum *int64 `meddler:"to_forge_l1_txs_num"` // toForgeL1TxsNum in which the tx was forged / will be forged
  33. UserOrigin *bool `meddler:"user_origin"` // true if the tx was originated by a user, false if it was aoriginated by a coordinator. Note that this differ from the spec for implementation simplification purpposes
  34. DepositAmount *apitypes.BigIntStr `meddler:"deposit_amount"`
  35. HistoricDepositAmountUSD *float64 `meddler:"deposit_amount_usd"`
  36. AmountSuccess bool `meddler:"amount_success"`
  37. DepositAmountSuccess bool `meddler:"deposit_amount_success"`
  38. // L2
  39. Fee *common.FeeSelector `meddler:"fee"`
  40. HistoricFeeUSD *float64 `meddler:"fee_usd"`
  41. Nonce *common.Nonce `meddler:"nonce"`
  42. // API extras
  43. Timestamp time.Time `meddler:"timestamp,utctime"`
  44. TotalItems uint64 `meddler:"total_items"`
  45. FirstItem uint64 `meddler:"first_item"`
  46. LastItem uint64 `meddler:"last_item"`
  47. TokenID common.TokenID `meddler:"token_id"`
  48. TokenItemID uint64 `meddler:"token_item_id"`
  49. TokenEthBlockNum int64 `meddler:"token_block"`
  50. TokenEthAddr ethCommon.Address `meddler:"eth_addr"`
  51. TokenName string `meddler:"name"`
  52. TokenSymbol string `meddler:"symbol"`
  53. TokenDecimals uint64 `meddler:"decimals"`
  54. TokenUSD *float64 `meddler:"usd"`
  55. TokenUSDUpdate *time.Time `meddler:"usd_update"`
  56. }
  57. // MarshalJSON is used to neast some of the fields of TxAPI
  58. // without the need of auxiliar structs
  59. func (tx TxAPI) MarshalJSON() ([]byte, error) {
  60. jsonTx := map[string]interface{}{
  61. "id": tx.TxID,
  62. "itemId": tx.ItemID,
  63. "type": tx.Type,
  64. "position": tx.Position,
  65. "fromAccountIndex": tx.FromIdx,
  66. "fromHezEthereumAddress": tx.FromEthAddr,
  67. "fromBJJ": tx.FromBJJ,
  68. "toAccountIndex": tx.ToIdx,
  69. "toHezEthereumAddress": tx.ToEthAddr,
  70. "toBJJ": tx.ToBJJ,
  71. "amount": tx.Amount,
  72. "batchNum": tx.BatchNum,
  73. "historicUSD": tx.HistoricUSD,
  74. "timestamp": tx.Timestamp,
  75. "L1Info": nil,
  76. "L2Info": nil,
  77. "token": map[string]interface{}{
  78. "id": tx.TokenID,
  79. "itemId": tx.TokenItemID,
  80. "ethereumBlockNum": tx.TokenEthBlockNum,
  81. "ethereumAddress": tx.TokenEthAddr,
  82. "name": tx.TokenName,
  83. "symbol": tx.TokenSymbol,
  84. "decimals": tx.TokenDecimals,
  85. "USD": tx.TokenUSD,
  86. "fiatUpdate": tx.TokenUSDUpdate,
  87. },
  88. }
  89. if tx.IsL1 {
  90. jsonTx["L1orL2"] = "L1"
  91. amountSuccess := tx.AmountSuccess
  92. depositAmountSuccess := tx.DepositAmountSuccess
  93. if tx.BatchNum == nil {
  94. amountSuccess = false
  95. depositAmountSuccess = false
  96. }
  97. jsonTx["L1Info"] = map[string]interface{}{
  98. "toForgeL1TransactionsNum": tx.ToForgeL1TxsNum,
  99. "userOrigin": tx.UserOrigin,
  100. "depositAmount": tx.DepositAmount,
  101. "amountSuccess": amountSuccess,
  102. "depositAmountSuccess": depositAmountSuccess,
  103. "historicDepositAmountUSD": tx.HistoricDepositAmountUSD,
  104. "ethereumBlockNum": tx.EthBlockNum,
  105. }
  106. } else {
  107. jsonTx["L1orL2"] = "L2"
  108. jsonTx["L2Info"] = map[string]interface{}{
  109. "fee": tx.Fee,
  110. "historicFeeUSD": tx.HistoricFeeUSD,
  111. "nonce": tx.Nonce,
  112. }
  113. }
  114. return json.Marshal(jsonTx)
  115. }
  116. // txWrite is an representatiion that merges common.L1Tx and common.L2Tx
  117. // in order to perform inserts into tx table
  118. // EffectiveAmount and EffectiveDepositAmount are not set since they have default values in the DB
  119. type txWrite struct {
  120. // Generic
  121. IsL1 bool `meddler:"is_l1"`
  122. TxID common.TxID `meddler:"id"`
  123. Type common.TxType `meddler:"type"`
  124. Position int `meddler:"position"`
  125. FromIdx *common.Idx `meddler:"from_idx"`
  126. ToIdx common.Idx `meddler:"to_idx"`
  127. Amount *big.Int `meddler:"amount,bigint"`
  128. AmountFloat float64 `meddler:"amount_f"`
  129. TokenID common.TokenID `meddler:"token_id"`
  130. BatchNum *common.BatchNum `meddler:"batch_num"` // batchNum in which this tx was forged. If the tx is L2, this must be != 0
  131. EthBlockNum int64 `meddler:"eth_block_num"` // Ethereum Block Number in which this L1Tx was added to the queue
  132. // L1
  133. ToForgeL1TxsNum *int64 `meddler:"to_forge_l1_txs_num"` // toForgeL1TxsNum in which the tx was forged / will be forged
  134. UserOrigin *bool `meddler:"user_origin"` // true if the tx was originated by a user, false if it was aoriginated by a coordinator. Note that this differ from the spec for implementation simplification purpposes
  135. FromEthAddr *ethCommon.Address `meddler:"from_eth_addr"`
  136. FromBJJ *babyjub.PublicKey `meddler:"from_bjj"`
  137. DepositAmount *big.Int `meddler:"deposit_amount,bigintnull"`
  138. DepositAmountFloat *float64 `meddler:"deposit_amount_f"`
  139. // L2
  140. Fee *common.FeeSelector `meddler:"fee"`
  141. Nonce *common.Nonce `meddler:"nonce"`
  142. }
  143. // TokenWithUSD add USD info to common.Token
  144. type TokenWithUSD struct {
  145. ItemID uint64 `json:"itemId" meddler:"item_id"`
  146. TokenID common.TokenID `json:"id" meddler:"token_id"`
  147. EthBlockNum int64 `json:"ethereumBlockNum" meddler:"eth_block_num"` // Ethereum block number in which this token was registered
  148. EthAddr ethCommon.Address `json:"ethereumAddress" meddler:"eth_addr"`
  149. Name string `json:"name" meddler:"name"`
  150. Symbol string `json:"symbol" meddler:"symbol"`
  151. Decimals uint64 `json:"decimals" meddler:"decimals"`
  152. USD *float64 `json:"USD" meddler:"usd"`
  153. USDUpdate *time.Time `json:"fiatUpdate" meddler:"usd_update,utctime"`
  154. TotalItems uint64 `json:"-" meddler:"total_items"`
  155. FirstItem uint64 `json:"-" meddler:"first_item"`
  156. LastItem uint64 `json:"-" meddler:"last_item"`
  157. }
  158. // ExitAPI is a representation of a exit with additional information
  159. // required by the API, and extracted by joining token table
  160. type ExitAPI struct {
  161. ItemID uint64 `meddler:"item_id"`
  162. BatchNum common.BatchNum `meddler:"batch_num"`
  163. AccountIdx apitypes.HezIdx `meddler:"account_idx"`
  164. MerkleProof *merkletree.CircomVerifierProof `meddler:"merkle_proof,json"`
  165. Balance apitypes.BigIntStr `meddler:"balance"`
  166. InstantWithdrawn *int64 `meddler:"instant_withdrawn"`
  167. DelayedWithdrawRequest *int64 `meddler:"delayed_withdraw_request"`
  168. DelayedWithdrawn *int64 `meddler:"delayed_withdrawn"`
  169. TotalItems uint64 `meddler:"total_items"`
  170. FirstItem uint64 `meddler:"first_item"`
  171. LastItem uint64 `meddler:"last_item"`
  172. TokenID common.TokenID `meddler:"token_id"`
  173. TokenItemID uint64 `meddler:"token_item_id"`
  174. TokenEthBlockNum int64 `meddler:"token_block"`
  175. TokenEthAddr ethCommon.Address `meddler:"eth_addr"`
  176. TokenName string `meddler:"name"`
  177. TokenSymbol string `meddler:"symbol"`
  178. TokenDecimals uint64 `meddler:"decimals"`
  179. TokenUSD *float64 `meddler:"usd"`
  180. TokenUSDUpdate *time.Time `meddler:"usd_update"`
  181. }
  182. // MarshalJSON is used to neast some of the fields of ExitAPI
  183. // without the need of auxiliar structs
  184. func (e ExitAPI) MarshalJSON() ([]byte, error) {
  185. siblings := []string{}
  186. for i := 0; i < len(e.MerkleProof.Siblings); i++ {
  187. siblings = append(siblings, e.MerkleProof.Siblings[i].String())
  188. }
  189. return json.Marshal(map[string]interface{}{
  190. "itemId": e.ItemID,
  191. "batchNum": e.BatchNum,
  192. "accountIndex": e.AccountIdx,
  193. "merkleProof": map[string]interface{}{
  194. "Root": e.MerkleProof.Root.String(),
  195. "Siblings": siblings,
  196. "OldKey": e.MerkleProof.OldKey.String(),
  197. "OldValue": e.MerkleProof.OldValue.String(),
  198. "IsOld0": e.MerkleProof.IsOld0,
  199. "Key": e.MerkleProof.Key.String(),
  200. "Value": e.MerkleProof.Value.String(),
  201. "Fnc": e.MerkleProof.Fnc,
  202. },
  203. "balance": e.Balance,
  204. "instantWithdrawn": e.InstantWithdrawn,
  205. "delayedWithdrawRequest": e.DelayedWithdrawRequest,
  206. "delayedWithdrawn": e.DelayedWithdrawn,
  207. "token": map[string]interface{}{
  208. "id": e.TokenID,
  209. "itemId": e.TokenItemID,
  210. "ethereumBlockNum": e.TokenEthBlockNum,
  211. "ethereumAddress": e.TokenEthAddr,
  212. "name": e.TokenName,
  213. "symbol": e.TokenSymbol,
  214. "decimals": e.TokenDecimals,
  215. "USD": e.TokenUSD,
  216. "fiatUpdate": e.TokenUSDUpdate,
  217. },
  218. })
  219. }
  220. // CoordinatorAPI is a representation of a coordinator with additional information
  221. // required by the API
  222. type CoordinatorAPI struct {
  223. ItemID uint64 `json:"itemId" meddler:"item_id"`
  224. Bidder ethCommon.Address `json:"bidderAddr" meddler:"bidder_addr"`
  225. Forger ethCommon.Address `json:"forgerAddr" meddler:"forger_addr"`
  226. EthBlockNum int64 `json:"ethereumBlock" meddler:"eth_block_num"`
  227. URL string `json:"URL" meddler:"url"`
  228. TotalItems uint64 `json:"-" meddler:"total_items"`
  229. FirstItem uint64 `json:"-" meddler:"first_item"`
  230. LastItem uint64 `json:"-" meddler:"last_item"`
  231. }
  232. // AccountAPI is a representation of a account with additional information
  233. // required by the API
  234. type AccountAPI struct {
  235. ItemID uint64 `meddler:"item_id"`
  236. Idx apitypes.HezIdx `meddler:"idx"`
  237. BatchNum common.BatchNum `meddler:"batch_num"`
  238. PublicKey apitypes.HezBJJ `meddler:"bjj"`
  239. EthAddr apitypes.HezEthAddr `meddler:"eth_addr"`
  240. Nonce common.Nonce `meddler:"-"` // max of 40 bits used
  241. Balance *apitypes.BigIntStr `meddler:"-"` // max of 192 bits used
  242. TotalItems uint64 `meddler:"total_items"`
  243. FirstItem uint64 `meddler:"first_item"`
  244. LastItem uint64 `meddler:"last_item"`
  245. TokenID common.TokenID `meddler:"token_id"`
  246. TokenItemID int `meddler:"token_item_id"`
  247. TokenEthBlockNum int64 `meddler:"token_block"`
  248. TokenEthAddr ethCommon.Address `meddler:"token_eth_addr"`
  249. TokenName string `meddler:"name"`
  250. TokenSymbol string `meddler:"symbol"`
  251. TokenDecimals uint64 `meddler:"decimals"`
  252. TokenUSD *float64 `meddler:"usd"`
  253. TokenUSDUpdate *time.Time `meddler:"usd_update"`
  254. }
  255. // MarshalJSON is used to neast some of the fields of AccountAPI
  256. // without the need of auxiliar structs
  257. func (account AccountAPI) MarshalJSON() ([]byte, error) {
  258. jsonAccount := map[string]interface{}{
  259. "itemId": account.ItemID,
  260. "accountIndex": account.Idx,
  261. "nonce": account.Nonce,
  262. "balance": account.Balance,
  263. "bjj": account.PublicKey,
  264. "hezEthereumAddress": account.EthAddr,
  265. "token": map[string]interface{}{
  266. "id": account.TokenID,
  267. "itemId": account.TokenItemID,
  268. "ethereumBlockNum": account.TokenEthBlockNum,
  269. "ethereumAddress": account.TokenEthAddr,
  270. "name": account.TokenName,
  271. "symbol": account.TokenSymbol,
  272. "decimals": account.TokenDecimals,
  273. "USD": account.TokenUSD,
  274. "fiatUpdate": account.TokenUSDUpdate,
  275. },
  276. }
  277. return json.Marshal(jsonAccount)
  278. }
  279. // BatchAPI is a representation of a batch with additional information
  280. // required by the API, and extracted by joining block table
  281. type BatchAPI struct {
  282. ItemID uint64 `json:"itemId" meddler:"item_id"`
  283. BatchNum common.BatchNum `json:"batchNum" meddler:"batch_num"`
  284. EthBlockNum int64 `json:"ethereumBlockNum" meddler:"eth_block_num"`
  285. EthBlockHash ethCommon.Hash `json:"ethereumBlockHash" meddler:"hash"`
  286. Timestamp time.Time `json:"timestamp" meddler:"timestamp,utctime"`
  287. ForgerAddr ethCommon.Address `json:"forgerAddr" meddler:"forger_addr"`
  288. CollectedFees apitypes.CollectedFees `json:"collectedFees" meddler:"fees_collected,json"`
  289. TotalFeesUSD *float64 `json:"historicTotalCollectedFeesUSD" meddler:"total_fees_usd"`
  290. StateRoot apitypes.BigIntStr `json:"stateRoot" meddler:"state_root"`
  291. NumAccounts int `json:"numAccounts" meddler:"num_accounts"`
  292. ExitRoot apitypes.BigIntStr `json:"exitRoot" meddler:"exit_root"`
  293. ForgeL1TxsNum *int64 `json:"forgeL1TransactionsNum" meddler:"forge_l1_txs_num"`
  294. SlotNum int64 `json:"slotNum" meddler:"slot_num"`
  295. TotalItems uint64 `json:"-" meddler:"total_items"`
  296. FirstItem uint64 `json:"-" meddler:"first_item"`
  297. LastItem uint64 `json:"-" meddler:"last_item"`
  298. }
  299. // Metrics define metrics of the network
  300. type Metrics struct {
  301. TransactionsPerBatch float64 `json:"transactionsPerBatch"`
  302. BatchFrequency float64 `json:"batchFrequency"`
  303. TransactionsPerSecond float64 `json:"transactionsPerSecond"`
  304. TotalAccounts int64 `json:"totalAccounts" meddler:"total_accounts"`
  305. TotalBJJs int64 `json:"totalBJJs" meddler:"total_bjjs"`
  306. AvgTransactionFee float64 `json:"avgTransactionFee"`
  307. }
  308. // MetricsTotals is used to get temporal information from HistoryDB
  309. // to calculate data to be stored into the Metrics struct
  310. type MetricsTotals struct {
  311. TotalTransactions uint64 `meddler:"total_txs"`
  312. FirstBatchNum common.BatchNum `meddler:"batch_num"`
  313. TotalBatches int64 `meddler:"total_batches"`
  314. TotalFeesUSD float64 `meddler:"total_fees"`
  315. }
  316. // BidAPI is a representation of a bid with additional information
  317. // required by the API
  318. type BidAPI struct {
  319. ItemID uint64 `json:"itemId" meddler:"item_id"`
  320. SlotNum int64 `json:"slotNum" meddler:"slot_num"`
  321. BidValue apitypes.BigIntStr `json:"bidValue" meddler:"bid_value"`
  322. EthBlockNum int64 `json:"ethereumBlockNum" meddler:"eth_block_num"`
  323. Bidder ethCommon.Address `json:"bidderAddr" meddler:"bidder_addr"`
  324. Forger ethCommon.Address `json:"forgerAddr" meddler:"forger_addr"`
  325. URL string `json:"URL" meddler:"url"`
  326. Timestamp time.Time `json:"timestamp" meddler:"timestamp,utctime"`
  327. TotalItems uint64 `json:"-" meddler:"total_items"`
  328. FirstItem uint64 `json:"-" meddler:"first_item"`
  329. LastItem uint64 `json:"-" meddler:"last_item"`
  330. }