Browse Source

Merge pull request #416 from hermeznetwork/feature/update-accountcreationauth

Update AccountCreationAuth & fix auth.HashToSign
feature/sql-semaphore1
Eduard S 3 years ago
committed by GitHub
parent
commit
6a2b9474e3
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 95 additions and 36 deletions
  1. +1
    -1
      api/accountcreationauths.go
  2. +13
    -11
      api/api.go
  3. +2
    -3
      api/api_test.go
  4. +3
    -0
      api/config.go
  5. +4
    -1
      api/config_test.go
  6. +17
    -12
      common/accountcreationauths.go
  7. +41
    -0
      common/accountcreationauths_test.go
  8. +3
    -1
      db/l2db/l2db_test.go
  9. +2
    -3
      node/node.go
  10. +3
    -2
      test/l2db.go
  11. +6
    -2
      test/l2db_test.go

+ 1
- 1
api/accountcreationauths.go

@ -21,7 +21,7 @@ func (a *API) postAccountCreationAuth(c *gin.Context) {
}
// API to common + verify signature
commonAuth := accountCreationAuthAPIToCommon(&apiAuth)
if !commonAuth.VerifySignature() {
if !commonAuth.VerifySignature(a.chainID, a.hermezAddress) {
retBadReq(errors.New("invalid signature"), c)
return
}

+ 13
- 11
api/api.go

@ -4,6 +4,7 @@ import (
"errors"
"sync"
ethCommon "github.com/ethereum/go-ethereum/common"
"github.com/gin-gonic/gin"
"github.com/hermeznetwork/hermez-node/common"
"github.com/hermeznetwork/hermez-node/db/historydb"
@ -31,12 +32,13 @@ type Status struct {
// API serves HTTP requests to allow external interaction with the Hermez node
type API struct {
h *historydb.HistoryDB
cg *configAPI
s *statedb.StateDB
l2 *l2db.L2DB
status Status
chainID uint16
h *historydb.HistoryDB
cg *configAPI
s *statedb.StateDB
l2 *l2db.L2DB
status Status
chainID uint16
hermezAddress ethCommon.Address
}
// NewAPI sets the endpoints and the appropriate handlers, but doesn't start the server
@ -47,7 +49,6 @@ func NewAPI(
sdb *statedb.StateDB,
l2db *l2db.L2DB,
config *Config,
chainID uint16,
) (*API, error) {
// Check input
// TODO: is stateDB only needed for explorer endpoints or for both?
@ -65,10 +66,11 @@ func NewAPI(
AuctionConstants: config.AuctionConstants,
WDelayerConstants: config.WDelayerConstants,
},
s: sdb,
l2: l2db,
status: Status{},
chainID: chainID,
s: sdb,
l2: l2db,
status: Status{},
chainID: config.ChainID,
hermezAddress: config.HermezAddress,
}
// Add coordinator endpoints

+ 2
- 3
api/api_test.go

@ -221,7 +221,7 @@ func TestMain(m *testing.M) {
test.WipeDB(l2DB.DB()) // this will clean HistoryDB and L2DB
// Config (smart contract constants)
_config := getConfigTest()
_config := getConfigTest(chainID)
config = configAPI{
RollupConstants: *newRollupConstants(_config.RollupConstants),
AuctionConstants: _config.AuctionConstants,
@ -238,7 +238,6 @@ func TestMain(m *testing.M) {
sdb,
l2DB,
&_config,
chainID,
)
if err != nil {
panic(err)
@ -423,7 +422,7 @@ func TestMain(m *testing.M) {
exits: testExits,
poolTxsToSend: poolTxsToSend,
poolTxsToReceive: poolTxsToReceive,
auths: genTestAuths(test.GenAuths(5)),
auths: genTestAuths(test.GenAuths(5, _config.ChainID, _config.HermezAddress)),
router: router,
bids: testBids,
slots: api.genTestSlots(

+ 3
- 0
api/config.go

@ -4,6 +4,7 @@ import (
"math/big"
"net/http"
ethCommon "github.com/ethereum/go-ethereum/common"
"github.com/gin-gonic/gin"
"github.com/hermeznetwork/hermez-node/common"
)
@ -51,6 +52,8 @@ type Config struct {
RollupConstants common.RollupConstants
AuctionConstants common.AuctionConstants
WDelayerConstants common.WDelayerConstants
ChainID uint16
HermezAddress ethCommon.Address
}
type configAPI struct {

+ 4
- 1
api/config_test.go

@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/assert"
)
func getConfigTest() Config {
func getConfigTest(chainID uint16) Config {
var config Config
var rollupPublicConstants common.RollupConstants
@ -40,6 +40,9 @@ func getConfigTest() Config {
config.AuctionConstants = auctionConstants
config.WDelayerConstants = wdelayerConstants
config.ChainID = chainID
config.HermezAddress = ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
return config
}

+ 17
- 12
common/accountcreationauths.go

@ -1,15 +1,20 @@
package common
import (
"encoding/binary"
"time"
ethCommon "github.com/ethereum/go-ethereum/common"
ethCrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/hermeznetwork/tracerr"
"github.com/iden3/go-iden3-crypto/babyjub"
)
// AccountCreationAuth authorizations sent by users to the L2DB, to be used for account creations when necessary
// AccountCreationAuthMsg is the message that is signed to authorize an account
// creation
const AccountCreationAuthMsg = "I authorize this babyjubjub key for hermez rollup account creation"
// AccountCreationAuth authorizations sent by users to the L2DB, to be used for
// account creations when necessary
type AccountCreationAuth struct {
EthAddr ethCommon.Address `meddler:"eth_addr"`
BJJ babyjub.PublicKeyComp `meddler:"bjj"`
@ -18,21 +23,21 @@ type AccountCreationAuth struct {
}
// HashToSign builds the hash to be signed using BJJ pub key and the constant message
func (a *AccountCreationAuth) HashToSign() ([]byte, error) {
func (a *AccountCreationAuth) HashToSign(chainID uint16,
hermezContractAddr ethCommon.Address) ([]byte, error) {
// Calculate message to be signed
const msg = "I authorize this babyjubjub key for hermez rollup account creation"
comp, err := a.BJJ.MarshalText()
if err != nil {
return nil, tracerr.Wrap(err)
}
// Hash message (msg || compressed-bjj)
return ethCrypto.Keccak256Hash([]byte(msg), comp).Bytes(), nil
var chainIDBytes [2]byte
binary.BigEndian.PutUint16(chainIDBytes[:], chainID)
// to hash: [AccountCreationAuthMsg | compressedBJJ | chainID | hermezContractAddr]
return ethCrypto.Keccak256Hash([]byte(AccountCreationAuthMsg), a.BJJ[:], chainIDBytes[:],
hermezContractAddr[:]).Bytes(), nil
}
// VerifySignature ensures that the Signature is done with the specified EthAddr
func (a *AccountCreationAuth) VerifySignature() bool {
func (a *AccountCreationAuth) VerifySignature(chainID uint16,
hermezContractAddr ethCommon.Address) bool {
// Calculate hash to be signed
msg, err := a.HashToSign()
msg, err := a.HashToSign(chainID, hermezContractAddr)
if err != nil {
return false
}

+ 41
- 0
common/accountcreationauths_test.go

@ -0,0 +1,41 @@
package common
import (
"encoding/hex"
"testing"
ethCommon "github.com/ethereum/go-ethereum/common"
ethCrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/iden3/go-iden3-crypto/babyjub"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestAccountCreationAuth(t *testing.T) {
// Ethereum key
ethSk, err := ethCrypto.HexToECDSA("fad9c8855b740a0b7ed4c221dbad0f33a83a49cad6b3fe8d5817ac83d38b6a19")
require.NoError(t, err)
ethAddr := ethCrypto.PubkeyToAddress(ethSk.PublicKey)
// BabyJubJub key
var sk babyjub.PrivateKey
_, err = hex.Decode(sk[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
assert.NoError(t, err)
chainID := uint16(0)
hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
a := AccountCreationAuth{
EthAddr: ethAddr,
BJJ: sk.Public().Compress(),
}
msg, err := a.HashToSign(chainID, hermezContractAddr)
assert.NoError(t, err)
assert.Equal(t, "cb5a7e44329ff430c81fec49fb2ac6741f02d5ec96cbcb618a6991f0a9c80ffd", hex.EncodeToString(msg))
// sign AccountCreationAuth with eth key
sig, err := ethCrypto.Sign(msg, ethSk)
assert.NoError(t, err)
a.Signature = sig
assert.True(t, a.VerifySignature(chainID, hermezContractAddr))
}

+ 3
- 1
db/l2db/l2db_test.go

@ -611,8 +611,10 @@ func TestPurge(t *testing.T) {
func TestAuth(t *testing.T) {
test.WipeDB(l2DB.DB())
const nAuths = 5
chainID := uint16(0)
hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
// Generate authorizations
auths := test.GenAuths(nAuths)
auths := test.GenAuths(nAuths, chainID, hermezContractAddr)
for i := 0; i < len(auths); i++ {
// Add to the DB
err := l2DB.AddAccountCreationAuth(auths[i])

+ 2
- 3
node/node.go

@ -245,8 +245,9 @@ func NewNode(mode Mode, cfg *config.Node) (*Node, error) {
RollupConstants: scConsts.Rollup,
AuctionConstants: scConsts.Auction,
WDelayerConstants: scConsts.WDelayer,
ChainID: chainIDU16,
HermezAddress: cfg.SmartContracts.Rollup,
},
chainIDU16,
)
if err != nil {
return nil, tracerr.Wrap(err)
@ -301,7 +302,6 @@ func NewNodeAPI(
sdb *statedb.StateDB,
l2db *l2db.L2DB,
config *api.Config,
chainID uint16,
) (*NodeAPI, error) {
engine := gin.Default()
engine.NoRoute(handleNoRoute)
@ -313,7 +313,6 @@ func NewNodeAPI(
sdb,
l2db,
config,
chainID,
)
if err != nil {
return nil, tracerr.Wrap(err)

+ 3
- 2
test/l2db.go

@ -1,6 +1,7 @@
package test
import (
ethCommon "github.com/ethereum/go-ethereum/common"
ethCrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/hermeznetwork/hermez-node/common"
"github.com/iden3/go-iden3-crypto/babyjub"
@ -66,7 +67,7 @@ func GenPoolTxs(n int, tokens []common.Token) []*common.PoolL2Tx {
}
// GenAuths generates account creation authorizations
func GenAuths(nAuths int) []*common.AccountCreationAuth {
func GenAuths(nAuths int, chainID uint16, hermezContractAddr ethCommon.Address) []*common.AccountCreationAuth {
auths := []*common.AccountCreationAuth{}
for i := 0; i < nAuths; i++ {
// Generate keys
@ -81,7 +82,7 @@ func GenAuths(nAuths int) []*common.AccountCreationAuth {
BJJ: bjjPrivK.Public().Compress(),
}
// Sign
h, err := auth.HashToSign()
h, err := auth.HashToSign(chainID, hermezContractAddr)
if err != nil {
panic(err)
}

+ 6
- 2
test/l2db_test.go

@ -3,13 +3,17 @@ package test
import (
"testing"
ethCommon "github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/assert"
)
func TestGenAuths(t *testing.T) {
chainID := uint16(0)
hermezContractAddr := ethCommon.HexToAddress("0xc344E203a046Da13b0B4467EB7B3629D0C99F6E6")
const nAuths = 5
auths := GenAuths(nAuths)
auths := GenAuths(nAuths, chainID, hermezContractAddr)
for _, auth := range auths {
assert.True(t, auth.VerifySignature())
assert.True(t, auth.VerifySignature(chainID, hermezContractAddr))
}
}

Loading…
Cancel
Save