package api
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"errors"
|
|
"math/big"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
ethCommon "github.com/ethereum/go-ethereum/common"
|
|
"github.com/hermeznetwork/hermez-node/common"
|
|
"github.com/hermeznetwork/hermez-node/db"
|
|
"github.com/hermeznetwork/hermez-node/db/historydb"
|
|
"github.com/hermeznetwork/hermez-node/eth"
|
|
"github.com/iden3/go-iden3-crypto/babyjub"
|
|
)
|
|
|
|
const exitIdx = "hez:EXIT:1"
|
|
|
|
type errorMsg struct {
|
|
Message string
|
|
}
|
|
|
|
func bjjToString(bjj *babyjub.PublicKey) string {
|
|
pkComp := [32]byte(bjj.Compress())
|
|
sum := pkComp[0]
|
|
for i := 1; i < len(pkComp); i++ {
|
|
sum += pkComp[i]
|
|
}
|
|
bjjSum := append(pkComp[:], sum)
|
|
return "hez:" + base64.RawURLEncoding.EncodeToString(bjjSum)
|
|
}
|
|
|
|
func ethAddrToHez(addr ethCommon.Address) string {
|
|
return "hez:" + addr.String()
|
|
}
|
|
|
|
func idxToHez(idx common.Idx, tokenSymbol string) string {
|
|
if idx == 1 {
|
|
return exitIdx
|
|
}
|
|
return "hez:" + tokenSymbol + ":" + strconv.Itoa(int(idx))
|
|
}
|
|
|
|
// Exit
|
|
|
|
type exitsAPI struct {
|
|
Exits []exitAPI `json:"exits"`
|
|
Pagination *db.Pagination `json:"pagination"`
|
|
}
|
|
|
|
func (e *exitsAPI) GetPagination() *db.Pagination {
|
|
if e.Exits[0].ItemID < e.Exits[len(e.Exits)-1].ItemID {
|
|
e.Pagination.FirstReturnedItem = e.Exits[0].ItemID
|
|
e.Pagination.LastReturnedItem = e.Exits[len(e.Exits)-1].ItemID
|
|
} else {
|
|
e.Pagination.LastReturnedItem = e.Exits[0].ItemID
|
|
e.Pagination.FirstReturnedItem = e.Exits[len(e.Exits)-1].ItemID
|
|
}
|
|
return e.Pagination
|
|
}
|
|
func (e *exitsAPI) Len() int { return len(e.Exits) }
|
|
|
|
type merkleProofAPI struct {
|
|
Root string
|
|
Siblings []string
|
|
OldKey string
|
|
OldValue string
|
|
IsOld0 bool
|
|
Key string
|
|
Value string
|
|
Fnc int
|
|
}
|
|
|
|
type exitAPI struct {
|
|
ItemID int `json:"itemId"`
|
|
BatchNum common.BatchNum `json:"batchNum"`
|
|
AccountIdx string `json:"accountIndex"`
|
|
MerkleProof merkleProofAPI `json:"merkleProof"`
|
|
Balance string `json:"balance"`
|
|
InstantWithdrawn *int64 `json:"instantWithdrawn"`
|
|
DelayedWithdrawRequest *int64 `json:"delayedWithdrawRequest"`
|
|
DelayedWithdrawn *int64 `json:"delayedWithdrawn"`
|
|
Token historydb.TokenWithUSD `json:"token"`
|
|
}
|
|
|
|
func historyExitsToAPI(dbExits []historydb.HistoryExit) []exitAPI {
|
|
apiExits := []exitAPI{}
|
|
for i := 0; i < len(dbExits); i++ {
|
|
exit := exitAPI{
|
|
ItemID: dbExits[i].ItemID,
|
|
BatchNum: dbExits[i].BatchNum,
|
|
AccountIdx: idxToHez(dbExits[i].AccountIdx, dbExits[i].TokenSymbol),
|
|
MerkleProof: merkleProofAPI{
|
|
Root: dbExits[i].MerkleProof.Root.String(),
|
|
OldKey: dbExits[i].MerkleProof.OldKey.String(),
|
|
OldValue: dbExits[i].MerkleProof.OldValue.String(),
|
|
IsOld0: dbExits[i].MerkleProof.IsOld0,
|
|
Key: dbExits[i].MerkleProof.Key.String(),
|
|
Value: dbExits[i].MerkleProof.Value.String(),
|
|
Fnc: dbExits[i].MerkleProof.Fnc,
|
|
},
|
|
Balance: dbExits[i].Balance.String(),
|
|
InstantWithdrawn: dbExits[i].InstantWithdrawn,
|
|
DelayedWithdrawRequest: dbExits[i].DelayedWithdrawRequest,
|
|
DelayedWithdrawn: dbExits[i].DelayedWithdrawn,
|
|
Token: historydb.TokenWithUSD{
|
|
TokenID: dbExits[i].TokenID,
|
|
EthBlockNum: dbExits[i].TokenEthBlockNum,
|
|
EthAddr: dbExits[i].TokenEthAddr,
|
|
Name: dbExits[i].TokenName,
|
|
Symbol: dbExits[i].TokenSymbol,
|
|
Decimals: dbExits[i].TokenDecimals,
|
|
USD: dbExits[i].TokenUSD,
|
|
USDUpdate: dbExits[i].TokenUSDUpdate,
|
|
},
|
|
}
|
|
siblings := []string{}
|
|
for j := 0; j < len(dbExits[i].MerkleProof.Siblings); j++ {
|
|
siblings = append(siblings, dbExits[i].MerkleProof.Siblings[j].String())
|
|
}
|
|
exit.MerkleProof.Siblings = siblings
|
|
apiExits = append(apiExits, exit)
|
|
}
|
|
return apiExits
|
|
}
|
|
|
|
// Config
|
|
|
|
type rollupConstants struct {
|
|
PublicConstants eth.RollupPublicConstants `json:"publicConstants"`
|
|
MaxFeeIdxCoordinator int `json:"maxFeeIdxCoordinator"`
|
|
ReservedIdx int `json:"reservedIdx"`
|
|
ExitIdx int `json:"exitIdx"`
|
|
LimitLoadAmount *big.Int `json:"limitLoadAmount"`
|
|
LimitL2TransferAmount *big.Int `json:"limitL2TransferAmount"`
|
|
LimitTokens int `json:"limitTokens"`
|
|
L1CoordinatorTotalBytes int `json:"l1CoordinatorTotalBytes"`
|
|
L1UserTotalBytes int `json:"l1UserTotalBytes"`
|
|
MaxL1UserTx int `json:"maxL1UserTx"`
|
|
MaxL1Tx int `json:"maxL1Tx"`
|
|
InputSHAConstantBytes int `json:"inputSHAConstantBytes"`
|
|
NumBuckets int `json:"numBuckets"`
|
|
MaxWithdrawalDelay int `json:"maxWithdrawalDelay"`
|
|
ExchangeMultiplier int `json:"exchangeMultiplier"`
|
|
}
|
|
|
|
type configAPI struct {
|
|
RollupConstants rollupConstants `json:"hermez"`
|
|
AuctionConstants eth.AuctionConstants `json:"auction"`
|
|
WDelayerConstants eth.WDelayerConstants `json:"withdrawalDelayer"`
|
|
}
|
|
|
|
// AccountCreationAuth
|
|
|
|
type accountCreationAuthAPI struct {
|
|
EthAddr string `json:"hezEthereumAddress" binding:"required"`
|
|
BJJ string `json:"bjj" binding:"required"`
|
|
Signature string `json:"signature" binding:"required"`
|
|
Timestamp time.Time `json:"timestamp"`
|
|
}
|
|
|
|
func accountCreationAuthToAPI(dbAuth *common.AccountCreationAuth) *accountCreationAuthAPI {
|
|
return &accountCreationAuthAPI{
|
|
EthAddr: ethAddrToHez(dbAuth.EthAddr),
|
|
BJJ: bjjToString(dbAuth.BJJ),
|
|
Signature: "0x" + hex.EncodeToString(dbAuth.Signature),
|
|
Timestamp: dbAuth.Timestamp,
|
|
}
|
|
}
|
|
|
|
func accountCreationAuthAPIToCommon(apiAuth *accountCreationAuthAPI) (*common.AccountCreationAuth, error) {
|
|
ethAddr, err := hezStringToEthAddr(apiAuth.EthAddr, "hezEthereumAddress")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
bjj, err := hezStringToBJJ(apiAuth.BJJ, "bjj")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
without0x := strings.TrimPrefix(apiAuth.Signature, "0x")
|
|
s, err := hex.DecodeString(without0x)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
auth := &common.AccountCreationAuth{
|
|
EthAddr: *ethAddr,
|
|
BJJ: bjj,
|
|
Signature: s,
|
|
Timestamp: apiAuth.Timestamp,
|
|
}
|
|
if !auth.VerifySignature() {
|
|
return nil, errors.New("invalid signature")
|
|
}
|
|
return auth, nil
|
|
}
|