mirror of
https://github.com/scroll-tech/scroll.git
synced 2026-01-13 16:08:04 -05:00
222 lines
5.5 KiB
Go
222 lines
5.5 KiB
Go
package message
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
|
|
"github.com/scroll-tech/go-ethereum/common"
|
|
"github.com/scroll-tech/go-ethereum/common/hexutil"
|
|
"github.com/scroll-tech/go-ethereum/core/types"
|
|
"github.com/scroll-tech/go-ethereum/crypto"
|
|
"github.com/scroll-tech/go-ethereum/rlp"
|
|
)
|
|
|
|
// RespStatus represents status code from roller to scroll
|
|
type RespStatus uint32
|
|
|
|
const (
|
|
// StatusOk means generate proof success
|
|
StatusOk RespStatus = iota
|
|
// StatusProofError means generate proof failed
|
|
StatusProofError
|
|
)
|
|
|
|
// AuthMsg is the first message exchanged from the Roller to the Sequencer.
|
|
// It effectively acts as a registration, and makes the Roller identification
|
|
// known to the Sequencer.
|
|
type AuthMsg struct {
|
|
// Message fields
|
|
Identity *Identity `json:"message"`
|
|
// Roller signature
|
|
Signature string `json:"signature"`
|
|
}
|
|
|
|
// Identity contains all the fields to be signed by the roller.
|
|
type Identity struct {
|
|
// Roller name
|
|
Name string `json:"name"`
|
|
// Unverified Unix timestamp of message creation
|
|
Timestamp uint32 `json:"timestamp"`
|
|
// Roller public key
|
|
PublicKey string `json:"publicKey"`
|
|
// Version is common.Version+ZkVersion. Use the following to check the latest ZkVersion version.
|
|
// curl -sL https://api.github.com/repos/scroll-tech/scroll-zkevm/commits | jq -r ".[0].sha"
|
|
Version string `json:"version"`
|
|
// Random unique token generated by manager
|
|
Token string `json:"token"`
|
|
}
|
|
|
|
// GenerateToken generates token
|
|
func GenerateToken() (string, error) {
|
|
b := make([]byte, 16)
|
|
if _, err := rand.Read(b); err != nil {
|
|
return "", err
|
|
}
|
|
return hex.EncodeToString(b), nil
|
|
}
|
|
|
|
// Sign auth message
|
|
func (a *AuthMsg) Sign(priv *ecdsa.PrivateKey) error {
|
|
// Hash identity content
|
|
hash, err := a.Identity.Hash()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// Sign register message
|
|
sig, err := crypto.Sign(hash, priv)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
a.Signature = hexutil.Encode(sig)
|
|
|
|
return nil
|
|
}
|
|
|
|
// Verify verifies the message of auth.
|
|
func (a *AuthMsg) Verify() (bool, error) {
|
|
hash, err := a.Identity.Hash()
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
sig := common.FromHex(a.Signature)
|
|
// recover public key
|
|
if a.Identity.PublicKey == "" {
|
|
pk, err := crypto.SigToPub(hash, sig)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
a.Identity.PublicKey = common.Bytes2Hex(crypto.CompressPubkey(pk))
|
|
}
|
|
|
|
return crypto.VerifySignature(common.FromHex(a.Identity.PublicKey), hash, sig[:len(sig)-1]), nil
|
|
}
|
|
|
|
// PublicKey return public key from signature
|
|
func (a *AuthMsg) PublicKey() (string, error) {
|
|
if a.Identity.PublicKey == "" {
|
|
hash, err := a.Identity.Hash()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
sig := common.FromHex(a.Signature)
|
|
// recover public key
|
|
pk, err := crypto.SigToPub(hash, sig)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
a.Identity.PublicKey = common.Bytes2Hex(crypto.CompressPubkey(pk))
|
|
return a.Identity.PublicKey, nil
|
|
}
|
|
|
|
return a.Identity.PublicKey, nil
|
|
}
|
|
|
|
// Hash returns the hash of the auth message, which should be the message used
|
|
// to construct the Signature.
|
|
func (i *Identity) Hash() ([]byte, error) {
|
|
byt, err := rlp.EncodeToBytes(i)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
hash := crypto.Keccak256Hash(byt)
|
|
return hash[:], nil
|
|
}
|
|
|
|
// ProofMsg is the data structure sent to the coordinator.
|
|
type ProofMsg struct {
|
|
*ProofDetail `json:"zkProof"`
|
|
// Roller signature
|
|
Signature string `json:"signature"`
|
|
|
|
// Roller public key
|
|
publicKey string
|
|
}
|
|
|
|
// Sign signs the ProofMsg.
|
|
func (a *ProofMsg) Sign(priv *ecdsa.PrivateKey) error {
|
|
hash, err := a.ProofDetail.Hash()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
sig, err := crypto.Sign(hash, priv)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
a.Signature = hexutil.Encode(sig)
|
|
return nil
|
|
}
|
|
|
|
// Verify verifies ProofMsg.Signature.
|
|
func (a *ProofMsg) Verify() (bool, error) {
|
|
hash, err := a.ProofDetail.Hash()
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
sig := common.FromHex(a.Signature)
|
|
// recover public key
|
|
if a.publicKey == "" {
|
|
pk, err := crypto.SigToPub(hash, sig)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
a.publicKey = common.Bytes2Hex(crypto.CompressPubkey(pk))
|
|
}
|
|
|
|
return crypto.VerifySignature(common.FromHex(a.publicKey), hash, sig[:len(sig)-1]), nil
|
|
}
|
|
|
|
// PublicKey return public key from signature
|
|
func (a *ProofMsg) PublicKey() (string, error) {
|
|
if a.publicKey == "" {
|
|
hash, err := a.ProofDetail.Hash()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
sig := common.FromHex(a.Signature)
|
|
// recover public key
|
|
pk, err := crypto.SigToPub(hash, sig)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
a.publicKey = common.Bytes2Hex(crypto.CompressPubkey(pk))
|
|
return a.publicKey, nil
|
|
}
|
|
|
|
return a.publicKey, nil
|
|
}
|
|
|
|
// TaskMsg is a wrapper type around db ProveTask type.
|
|
type TaskMsg struct {
|
|
ID string `json:"id"`
|
|
Traces []*types.BlockTrace `json:"blockTraces"`
|
|
}
|
|
|
|
// ProofDetail is the message received from rollers that contains zk proof, the status of
|
|
// the proof generation succeeded, and an error message if proof generation failed.
|
|
type ProofDetail struct {
|
|
ID string `json:"id"`
|
|
Status RespStatus `json:"status"`
|
|
Proof *AggProof `json:"proof"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
// Hash return proofMsg content hash.
|
|
func (z *ProofDetail) Hash() ([]byte, error) {
|
|
byt, err := rlp.EncodeToBytes(z)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
hash := crypto.Keccak256Hash(byt)
|
|
return hash[:], nil
|
|
}
|
|
|
|
// AggProof includes the proof and public input that are required to verification and rollup.
|
|
type AggProof struct {
|
|
Proof []byte `json:"proof"`
|
|
Instance []byte `json:"instance"`
|
|
FinalPair []byte `json:"final_pair"`
|
|
Vk []byte `json:"vk"`
|
|
}
|