github.com/ethersphere/bee/v2@v2.2.0/pkg/settlement/swap/chequebook/cheque.go (about)

     1  // Copyright 2020 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package chequebook
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"math/big"
    11  
    12  	"github.com/ethereum/go-ethereum/common"
    13  	"github.com/ethereum/go-ethereum/common/math"
    14  	"github.com/ethersphere/bee/v2/pkg/crypto"
    15  	"github.com/ethersphere/bee/v2/pkg/crypto/eip712"
    16  )
    17  
    18  // Cheque represents a cheque for a SimpleSwap chequebook
    19  type Cheque struct {
    20  	Chequebook       common.Address
    21  	Beneficiary      common.Address
    22  	CumulativePayout *big.Int
    23  }
    24  
    25  // SignedCheque represents a cheque together with its signature
    26  type SignedCheque struct {
    27  	Cheque
    28  	Signature []byte
    29  }
    30  
    31  // chequebookDomain computes chainId-dependent EIP712 domain
    32  func chequebookDomain(chainID int64) eip712.TypedDataDomain {
    33  	return eip712.TypedDataDomain{
    34  		Name:    "Chequebook",
    35  		Version: "1.0",
    36  		ChainId: math.NewHexOrDecimal256(chainID),
    37  	}
    38  }
    39  
    40  // ChequeTypes are the needed type descriptions for cheque signing
    41  var ChequeTypes = eip712.Types{
    42  	"EIP712Domain": eip712.EIP712DomainType,
    43  	"Cheque": []eip712.Type{
    44  		{
    45  			Name: "chequebook",
    46  			Type: "address",
    47  		},
    48  		{
    49  			Name: "beneficiary",
    50  			Type: "address",
    51  		},
    52  		{
    53  			Name: "cumulativePayout",
    54  			Type: "uint256",
    55  		},
    56  	},
    57  }
    58  
    59  // ChequeSigner signs cheque
    60  type ChequeSigner interface {
    61  	// Sign signs a cheque
    62  	Sign(cheque *Cheque) ([]byte, error)
    63  }
    64  
    65  type chequeSigner struct {
    66  	signer  crypto.Signer // the underlying signer used
    67  	chainID int64         // the chainID used for EIP712
    68  }
    69  
    70  // NewChequeSigner creates a new cheque signer for the given chainID.
    71  func NewChequeSigner(signer crypto.Signer, chainID int64) ChequeSigner {
    72  	return &chequeSigner{
    73  		signer:  signer,
    74  		chainID: chainID,
    75  	}
    76  }
    77  
    78  // eip712DataForCheque converts a cheque into the correct TypedData structure.
    79  func eip712DataForCheque(cheque *Cheque, chainID int64) *eip712.TypedData {
    80  	return &eip712.TypedData{
    81  		Domain: chequebookDomain(chainID),
    82  		Types:  ChequeTypes,
    83  		Message: eip712.TypedDataMessage{
    84  			"chequebook":       cheque.Chequebook.Hex(),
    85  			"beneficiary":      cheque.Beneficiary.Hex(),
    86  			"cumulativePayout": cheque.CumulativePayout.String(),
    87  		},
    88  		PrimaryType: "Cheque",
    89  	}
    90  }
    91  
    92  // Sign signs a cheque.
    93  func (s *chequeSigner) Sign(cheque *Cheque) ([]byte, error) {
    94  	return s.signer.SignTypedData(eip712DataForCheque(cheque, s.chainID))
    95  }
    96  
    97  func (cheque *Cheque) String() string {
    98  	return fmt.Sprintf("Contract: %x Beneficiary: %x CumulativePayout: %v", cheque.Chequebook, cheque.Beneficiary, cheque.CumulativePayout)
    99  }
   100  
   101  func (cheque *Cheque) Equal(other *Cheque) bool {
   102  	if cheque.Beneficiary != other.Beneficiary {
   103  		return false
   104  	}
   105  	if cheque.CumulativePayout.Cmp(other.CumulativePayout) != 0 {
   106  		return false
   107  	}
   108  	return cheque.Chequebook == other.Chequebook
   109  }
   110  
   111  func (cheque *SignedCheque) Equal(other *SignedCheque) bool {
   112  	if !bytes.Equal(cheque.Signature, other.Signature) {
   113  		return false
   114  	}
   115  	return cheque.Cheque.Equal(&other.Cheque)
   116  }