Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EIP-712 messages as confidential requests #164

Closed
wants to merge 11 commits into from
Closed
1 change: 1 addition & 0 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
return nil, err
}
if st.gasRemaining < gas {
fmt.Println("from", msg.From)
return nil, fmt.Errorf("%w: have %d, want %d", ErrIntrinsicGas, st.gasRemaining, gas)
}
st.gasRemaining -= gas
Expand Down
216 changes: 125 additions & 91 deletions core/types/confidential.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package types

import (
"encoding/json"
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/suave/apitypes"
)

type ConfidentialComputeRecord struct {
Expand All @@ -18,122 +22,99 @@ type ConfidentialComputeRecord struct {
ConfidentialInputsHash common.Hash

ChainID *big.Int
V, R, S *big.Int
}

// copy creates a deep copy of the transaction data and initializes all fields.
func (tx *ConfidentialComputeRecord) copy() TxData {
cpy := &ConfidentialComputeRecord{
Nonce: tx.Nonce,
To: copyAddressPtr(tx.To),
Data: common.CopyBytes(tx.Data),
Gas: tx.Gas,
KettleAddress: tx.KettleAddress,
ConfidentialInputsHash: tx.ConfidentialInputsHash,

Value: new(big.Int),
GasPrice: new(big.Int),

ChainID: new(big.Int),
V: new(big.Int),
R: new(big.Int),
S: new(big.Int),
}
type ConfidentialComputeRequest2 struct {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a transaction type, we could say that is the EIP-712 transaction type. Record is only the message type, like the Suave intent-format.

// Message is the message we are signed with the EIP-712 envelope
Message json.RawMessage `json:"message"`
// Signature is the signature of the message with the EIP-712 envelope
Signature []byte `json:"signature"`
}

if tx.Value != nil {
cpy.Value.Set(tx.Value)
}
if tx.GasPrice != nil {
cpy.GasPrice.Set(tx.GasPrice)
}
if tx.ChainID != nil {
cpy.ChainID.Set(tx.ChainID)
}
if tx.V != nil {
cpy.V.Set(tx.V)
}
if tx.R != nil {
cpy.R.Set(tx.R)
func (c *ConfidentialComputeRequest2) txType() byte {
return 0x69
}

func (c *ConfidentialComputeRequest2) copy() TxData {
// lets be lazy here for now
raw, err := json.Marshal(c)
if err != nil {
panic(err)
}
if tx.S != nil {
cpy.S.Set(tx.S)
cpy := &ConfidentialComputeRequest2{}
err = json.Unmarshal(raw, cpy)
if err != nil {
panic(err)
}

return cpy
}

func (tx *ConfidentialComputeRecord) txType() byte { return ConfidentialComputeRecordTxType }
func (tx *ConfidentialComputeRecord) chainID() *big.Int { return tx.ChainID }
func (tx *ConfidentialComputeRecord) accessList() AccessList { return nil }
func (tx *ConfidentialComputeRecord) data() []byte { return tx.Data }
func (tx *ConfidentialComputeRecord) gas() uint64 { return tx.Gas }
func (tx *ConfidentialComputeRecord) gasPrice() *big.Int { return tx.GasPrice }
func (tx *ConfidentialComputeRecord) gasTipCap() *big.Int { return tx.GasPrice }
func (tx *ConfidentialComputeRecord) gasFeeCap() *big.Int { return tx.GasPrice }
func (tx *ConfidentialComputeRecord) value() *big.Int { return tx.Value }
func (tx *ConfidentialComputeRecord) nonce() uint64 { return tx.Nonce }
func (tx *ConfidentialComputeRecord) to() *common.Address { return tx.To }
func (tx *ConfidentialComputeRecord) blobGas() uint64 { return 0 }
func (tx *ConfidentialComputeRecord) blobGasFeeCap() *big.Int { return nil }
func (tx *ConfidentialComputeRecord) blobHashes() []common.Hash { return nil }

func (tx *ConfidentialComputeRecord) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
return dst.Set(tx.GasPrice)
func (c *ConfidentialComputeRequest2) GetRecord() ConfidentialComputeRecord {
var record ConfidentialComputeRecord
if err := json.Unmarshal(c.Message, &record); err != nil {
panic(err)
}
return record
}

func (tx *ConfidentialComputeRecord) rawSignatureValues() (v, r, s *big.Int) {
return tx.V, tx.R, tx.S
func (c *ConfidentialComputeRequest2) chainID() *big.Int {
return big.NewInt(1)
}

func (tx *ConfidentialComputeRecord) setSignatureValues(chainID, v, r, s *big.Int) {
tx.ChainID, tx.V, tx.R, tx.S = chainID, v, r, s
func (c *ConfidentialComputeRequest2) accessList() AccessList {
return AccessList{}
}

type ConfidentialComputeRequest struct {
ConfidentialComputeRecord
ConfidentialInputs []byte
func (c *ConfidentialComputeRequest2) data() []byte {
return c.GetRecord().Data
}

// copy creates a deep copy of the transaction data and initializes all fields.
func (tx *ConfidentialComputeRequest) copy() TxData {
cpy := &ConfidentialComputeRequest{
ConfidentialComputeRecord: *(tx.ConfidentialComputeRecord.copy().(*ConfidentialComputeRecord)),
ConfidentialInputs: tx.ConfidentialInputs,
}

return cpy
func (c *ConfidentialComputeRequest2) gas() uint64 {
return c.GetRecord().Gas
}

func (tx *ConfidentialComputeRequest) txType() byte { return ConfidentialComputeRequestTxType }
func (tx *ConfidentialComputeRequest) chainID() *big.Int { return tx.ChainID }
func (tx *ConfidentialComputeRequest) accessList() AccessList { return nil }
func (tx *ConfidentialComputeRequest) data() []byte { return tx.Data }
func (tx *ConfidentialComputeRequest) gas() uint64 { return tx.Gas }
func (tx *ConfidentialComputeRequest) gasPrice() *big.Int { return tx.GasPrice }
func (tx *ConfidentialComputeRequest) gasTipCap() *big.Int { return tx.GasPrice }
func (tx *ConfidentialComputeRequest) gasFeeCap() *big.Int { return tx.GasPrice }
func (tx *ConfidentialComputeRequest) value() *big.Int { return tx.Value }
func (tx *ConfidentialComputeRequest) nonce() uint64 { return tx.Nonce }
func (tx *ConfidentialComputeRequest) to() *common.Address { return tx.To }
func (tx *ConfidentialComputeRequest) blobGas() uint64 { return 0 }
func (tx *ConfidentialComputeRequest) blobGasFeeCap() *big.Int { return nil }
func (tx *ConfidentialComputeRequest) blobHashes() []common.Hash { return nil }

func (tx *ConfidentialComputeRequest) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
return dst.Set(tx.GasPrice)
func (c *ConfidentialComputeRequest2) gasPrice() *big.Int {
return c.GetRecord().GasPrice
}

func (tx *ConfidentialComputeRequest) rawSignatureValues() (v, r, s *big.Int) {
return tx.V, tx.R, tx.S
func (c *ConfidentialComputeRequest2) gasTipCap() *big.Int {
return big.NewInt(1)
}
func (c *ConfidentialComputeRequest2) gasFeeCap() *big.Int {
return big.NewInt(1)
}
func (c *ConfidentialComputeRequest2) value() *big.Int {
return c.GetRecord().Value
}
func (c *ConfidentialComputeRequest2) nonce() uint64 {
return c.GetRecord().Nonce
}
func (c *ConfidentialComputeRequest2) to() *common.Address {
return c.GetRecord().To
}
func (c *ConfidentialComputeRequest2) blobGas() uint64 {
return 0
}
func (c *ConfidentialComputeRequest2) blobGasFeeCap() *big.Int {
return nil
}
func (c *ConfidentialComputeRequest2) blobHashes() []common.Hash {
return nil
}

func (tx *ConfidentialComputeRequest) setSignatureValues(chainID, v, r, s *big.Int) {
tx.ChainID, tx.V, tx.R, tx.S = chainID, v, r, s
func (c *ConfidentialComputeRequest2) rawSignatureValues() (v, r, s *big.Int) {
panic("it should not happen")
}
func (c *ConfidentialComputeRequest2) setSignatureValues(chainID, v, r, s *big.Int) {
panic("it should not happen")
}
func (c *ConfidentialComputeRequest2) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
panic("it should not happen")
}

type SuaveTransaction struct {
ConfidentialComputeRequest ConfidentialComputeRecord `json:"confidentialComputeRequest" gencodec:"required"`
ConfidentialComputeResult []byte `json:"confidentialComputeResult" gencodec:"required"`
ConfidentialComputeRequest ConfidentialComputeRequest2 `json:"confidentialComputeRequest" gencodec:"required"`
ConfidentialComputeResult []byte `json:"confidentialComputeResult" gencodec:"required"`

// request KettleAddress's signature
ChainID *big.Int
Expand Down Expand Up @@ -216,3 +197,56 @@ func (tx *SuaveTransaction) rawSignatureValues() (v, r, s *big.Int) {
func (tx *SuaveTransaction) setSignatureValues(chainID, v, r, s *big.Int) {
tx.ChainID, tx.V, tx.R, tx.S = chainID, v, r, s
}

func (msg *ConfidentialComputeRecord) Recover(signature []byte) (common.Address, error) {
signHash, _, err := apitypes.TypedDataAndHash(msg.BuildConfidentialRecordEIP712Envelope())
if err != nil {
return common.Address{}, err
}
result, err := crypto.Ecrecover(signHash, signature)
if err != nil {
return common.Address{}, err
}

var signer common.Address
copy(signer[:], crypto.Keccak256(result[1:])[12:])

return signer, nil
}

func (msg *ConfidentialComputeRecord) BuildConfidentialRecordEIP712Envelope() apitypes.TypedData {
typ := apitypes.TypedData{
Types: apitypes.Types{
"EIP712Domain": []apitypes.Type{
{Name: "name", Type: "string"},
{Name: "chainId", Type: "uint256"},
},
"ConfidentialRecord": []apitypes.Type{
{Name: "nonce", Type: "uint64"},
{Name: "gasPrice", Type: "uint256"},
{Name: "gas", Type: "uint64"},
{Name: "to", Type: "address"},
{Name: "value", Type: "uint256"},
{Name: "data", Type: "bytes"},
{Name: "kettleAddress", Type: "address"},
{Name: "confidentialInputsHash", Type: "bytes32"},
},
},
Domain: apitypes.TypedDataDomain{
Name: "ConfidentialRecord",
ChainId: math.NewHexOrDecimal256(msg.ChainID.Int64()),
},
PrimaryType: "ConfidentialRecord",
Message: apitypes.TypedDataMessage{
"nonce": msg.Nonce,
"gasPrice": msg.GasPrice,
"gas": msg.Gas,
"to": msg.To,
"value": msg.Value,
"data": msg.Data,
"kettleAddress": msg.KettleAddress,
"confidentialInputsHash": msg.ConfidentialInputsHash,
},
}
return typ
}
13 changes: 4 additions & 9 deletions core/types/confidential_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
package types

import (
"math/big"
"testing"

"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/require"
)

/*
func TestCCRequestToRecord(t *testing.T) {
testKey, err := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
require.NoError(t, err)
Expand Down Expand Up @@ -84,7 +77,8 @@ func TestSuaveTx(t *testing.T) {
}), signer, testKey)
require.NoError(t, err)

signedInnerCCR, ok := CastTxInner[*ConfidentialComputeRecord](signedCCR)
// TODO-FIX
signedInnerCCR, ok := CastTxInner[*ConfidentialComputeRequest2](signedCCR)
require.True(t, ok)

unsignedTx := NewTx(&SuaveTransaction{
Expand All @@ -109,3 +103,4 @@ func TestSuaveTx(t *testing.T) {

require.Equal(t, crypto.PubkeyToAddress(testKey.PublicKey), recoveredUnmarshalledSender)
}
*/
7 changes: 3 additions & 4 deletions core/types/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ import (
"bytes"
"container/heap"
"errors"
"fmt"
"io"
"math/big"
"reflect"
"sync/atomic"
"time"

Expand Down Expand Up @@ -203,10 +205,6 @@ func (tx *Transaction) decodeTyped(b []byte) (TxData, error) {
var inner BlobTx
err := rlp.DecodeBytes(b[1:], &inner)
return &inner, err
case ConfidentialComputeRequestTxType:
var inner ConfidentialComputeRequest
err := rlp.DecodeBytes(b[1:], &inner)
return &inner, err
case SuaveTxType:
var inner SuaveTransaction
err := rlp.DecodeBytes(b[1:], &inner)
Expand Down Expand Up @@ -276,6 +274,7 @@ func (tx *Transaction) Type() uint8 {
}

func CastTxInner[T any](tx *Transaction) (T, bool) {
fmt.Println(reflect.TypeOf(tx.inner))
t, ok := tx.inner.(T)
return t, ok
}
Expand Down
Loading
Loading