arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/common/accountcreationauths.go
common/accountcreationauths.goRaw
 1package common
 2
 3import (
 4	"encoding/binary"
 5	"strconv"
 6	"time"
 7
 8	ethCommon "github.com/ethereum/go-ethereum/common"
 9	ethCrypto "github.com/ethereum/go-ethereum/crypto"
10	"github.com/iden3/go-iden3-crypto/babyjub"
11)
12
13// AccountCreationAuthMsg is the message that is signed to authorize a Hermez
14// account creation
15const AccountCreationAuthMsg = "I authorize this babyjubjub key for hermez rollup account creation"
16
17// EthMsgPrefix is the prefix for message signing at the Ethereum ecosystem
18const EthMsgPrefix = "\x19Ethereum Signed Message:\n"
19
20// AccountCreationAuth authorizations sent by users to the L2DB, to be used for
21// account creations when necessary
22type AccountCreationAuth struct {
23	EthAddr   ethCommon.Address     `meddler:"eth_addr"`
24	BJJ       babyjub.PublicKeyComp `meddler:"bjj"`
25	Signature []byte                `meddler:"signature"`
26	Timestamp time.Time             `meddler:"timestamp,utctime"`
27}
28
29func (a *AccountCreationAuth) toHash(chainID uint16,
30	hermezContractAddr ethCommon.Address) []byte {
31	var chainIDBytes [2]byte
32	binary.BigEndian.PutUint16(chainIDBytes[:], chainID)
33	// [EthPrefix | AccountCreationAuthMsg | compressedBJJ | chainID | hermezContractAddr]
34	var b []byte
35	b = append(b, []byte(AccountCreationAuthMsg)...)
36	b = append(b, SwapEndianness(a.BJJ[:])...) // for js implementation compatibility
37	b = append(b, chainIDBytes[:]...)
38	b = append(b, hermezContractAddr[:]...)
39
40	ethPrefix := EthMsgPrefix + strconv.Itoa(len(b))
41	return append([]byte(ethPrefix), b...)
42}
43
44// HashToSign returns the hash to be signed by the Etherum address to authorize
45// the account creation
46func (a *AccountCreationAuth) HashToSign(chainID uint16,
47	hermezContractAddr ethCommon.Address) ([]byte, error) {
48	b := a.toHash(chainID, hermezContractAddr)
49	return ethCrypto.Keccak256Hash(b).Bytes(), nil
50}
51
52// VerifySignature ensures that the Signature is done with the EthAddr, for the
53// chainID and hermezContractAddress passed by parameter
54func (a *AccountCreationAuth) VerifySignature(chainID uint16,
55	hermezContractAddr ethCommon.Address) bool {
56	// Calculate hash to be signed
57	msg, err := a.HashToSign(chainID, hermezContractAddr)
58	if err != nil {
59		return false
60	}
61
62	var sig [65]byte
63	copy(sig[:], a.Signature[:])
64	sig[64] -= 27
65
66	// Get public key from Signature
67	pubKBytes, err := ethCrypto.Ecrecover(msg, sig[:])
68	if err != nil {
69		return false
70	}
71	pubK, err := ethCrypto.UnmarshalPubkey(pubKBytes)
72	if err != nil {
73		return false
74	}
75	// Get addr from pubK
76	addr := ethCrypto.PubkeyToAddress(*pubK)
77	return addr == a.EthAddr
78}