sapphire

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 6, 2022 License: Apache-2.0 Imports: 27 Imported by: 0

README

Sapphire ParaTime Compat Lib

@oasisprotocol/sapphire-paratime makes it easy to port your dapp to the Sapphire ParaTime. You can port over a Go Ethereum application by using a sapphire.WrappedBackend or by packing native Ethereum transactions Sapphire style.

If your dapp doesn't port in under 10 minutes, it's a bug!

If you have more than a little trouble, please file an issue. There should be no reason not to use the Sapphire ParaTime!

Building

Sapphire Paratime compatibility library works with Go version 1.17 or later and the latest comparable go-ethereum version.

To build and test locally, import the Go package.

Usage

Go-Ethereum ABI

After generating the Go bindings for a particular Solidity contract, you can use dial an Ethereum client with the Sapphire Paratime gateway URL and instantiate a sapphire.WrappedBackend as a drop in replacement.

// key := private key
c, _ := ethclient.Dial(sapphire.Networks[SapphireChainID.Uint64()].DefaultGateway)
cipher, _ := sapphire.NewCipher(SapphireChainID.Uint64())
wb := sapphire.NewWrappedBackend(c, *SapphireChainID, cipher, func(digest [32]byte)([]byte, error) {
  // Pass in a custom signing function to interact with the signer
  return crypto.Sign(digest[:], key)
})

Generated contract functions such as Deploy{type} will work now after passing in wb.

// Deploy the contract passing the newly created `auth` and `wb` vars
address, tx, instance, err := storage.DeployStorage(auth, wb)
Bring Your Own Signer

You can also package an Ethereum transaction for Sapphire by:

sapphire.PackTx(tx, sapphire.NewCipher(SapphireChainID.Uint64()))

and sending it with an Ethereum client

ethclient.SendTransaction(ctx, signedTx)

See Also

Documentation

Index

Constants

View Source
const (
	Plain          = iota
	X25519DeoxysII = 1
)
View Source
const (
	DefaultGasPrice = 100_000_000_000
	// DefaultGasLimit is set on all transactions without explicit gas limit to avoid being set on signed queries by the web3 gateway.
	DefaultGasLimit   = 30_000_000
	DefaultBlockRange = 15
)
View Source
const ZeroAddress = "0x0000000000000000000000000000000000000000"

Variables

View Source
var (
	ErrCallFailed       = errors.New("call failed in module")
	ErrCallResultDecode = errors.New("could not decode call result")
)
View Source
var Networks = map[uint64]NetworkParams{
	0x5aff: {
		Name:           "testnet",
		ChainID:        *big.NewInt(0x5aff),
		DefaultGateway: "https://testnet.sapphire.oasis.dev",
		RuntimeID:      "0x000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c",
	},
	0x5afe: {
		Name:           "mainnet",
		ChainID:        *big.NewInt(0x5afe),
		DefaultGateway: "https://sapphire.oasis.dev",
		RuntimeID:      "0x0000000000000000000000000000000000000000000000000000000000000000",
	},
}

Functions

func GetRuntimePublicKey

func GetRuntimePublicKey(chainID uint64) (*[32]byte, error)

GetRuntimePublicKey fetches the runtime calldata public key from the default Sapphire gateway.

func PackCall

func PackCall(msg ethereum.CallMsg, cipher Cipher) (*ethereum.CallMsg, error)

PackCall prepares `msg` for being sent to Sapphire. The call will be end-to-end encrypted, but the `from` address will be zero.

func PackSignedCall

func PackSignedCall(msg ethereum.CallMsg, cipher Cipher, sign SignerFn, chainID big.Int, leash Leash) (*ethereum.CallMsg, error)

PackSignedCall prepares `msg` in-place for being sent to Sapphire. The call will be end-to-end encrypted and a signature will be used to authenticate the `from` address.

func PackTx

func PackTx(tx types.Transaction, cipher Cipher) (*types.Transaction, error)

PackTx prepares a regular Eth transaction for Sapphire. The transaction returned from this function is what must be signed.

Types

type Body

type Body struct {
	PK    []byte `json:"pk"`
	Data  []byte `json:"data"`
	Nonce []byte `json:"nonce"`
}

type CallResult

type CallResult struct {
	Fail    *Failure `json:"failure,omitempty"`
	OK      []byte   `json:"ok,omitempty"`
	Unknown *Unknown `json:"unknown,omitempty"`
}

type Cipher

type Cipher interface {
	Kind() uint64
	Encrypt(plaintext []byte) (ciphertext []byte, nonce []byte)
	Decrypt(nonce []byte, ciphertext []byte) (plaintext []byte, err error)
	EncryptEncode(plaintext []byte) []byte
	DecryptEncoded(result []byte) ([]byte, error)
	DecryptCallResult(result []byte) ([]byte, error)
}

func NewCipher

func NewCipher(chainID uint64) (Cipher, error)

NewCipher creates a default cipher.

type Curve25519KeyPair

type Curve25519KeyPair struct {
	PublicKey [curve25519.PointSize]byte
	SecretKey [curve25519.ScalarSize]byte
}

func NewCurve25519KeyPair

func NewCurve25519KeyPair() (*Curve25519KeyPair, error)

NewCurve25519KeyPair generates a random keypair suitable for use with the X25519DeoxysII cipher.

type Data

type Data struct {
	Body []byte `json:"body"`
}

Data is the plain data in the datapack.

type DataEnvelope

type DataEnvelope struct {
	Body   []byte `json:"body"`
	Format uint64 `json:"format,omitempty"` // reuse for now, TODO swap later
}

DataEnvelope is an oasis-sdk `Call` without optional fields.

type EncryptedBodyEnvelope

type EncryptedBodyEnvelope struct {
	Body   Body   `json:"body"`
	Format uint64 `json:"format"`
}

EncryptedBodyEnvelope is an oasis-sdk `Call` with optional fields.

type Error

type Error struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Data    interface{} `json:"data,omitempty"`
}

type Failure

type Failure struct {
	Module  string `json:"module"`
	Code    uint64 `json:"code"`
	Message string `json:"message,omitempty"`
}

type Inner

type Inner struct {
	Fail *Failure `json:"fail"`
	OK   []byte   `json:"ok"`
}

type Kind

type Kind uint64

type Leash

type Leash struct {
	Nonce       uint64 `json:"nonce"`
	BlockNumber uint64 `json:"block_number"`
	BlockHash   []byte `json:"block_hash"`
	BlockRange  uint64 `json:"block_range"`
}

func NewLeash

func NewLeash(nonce uint64, blockNumber uint64, blockHash []byte, blockRange uint64) Leash

type NetworkParams

type NetworkParams struct {
	Name           string
	ChainID        big.Int
	DefaultGateway string
	RuntimeID      string
}

type PlainCipher

type PlainCipher struct{}

func NewPlainCipher

func NewPlainCipher() PlainCipher

func (PlainCipher) Decrypt

func (c PlainCipher) Decrypt(nonce []byte, ciphertext []byte) (plaintext []byte, err error)

func (PlainCipher) DecryptCallResult

func (c PlainCipher) DecryptCallResult(response []byte) ([]byte, error)

func (PlainCipher) DecryptEncoded

func (c PlainCipher) DecryptEncoded(response []byte) ([]byte, error)

func (PlainCipher) Encrypt

func (c PlainCipher) Encrypt(plaintext []byte) (ciphertext []byte, nonce []byte)

func (PlainCipher) EncryptEncode

func (c PlainCipher) EncryptEncode(plaintext []byte) []byte

func (PlainCipher) EncryptEnvelope

func (c PlainCipher) EncryptEnvelope(plaintext []byte) *DataEnvelope

func (PlainCipher) Kind

func (c PlainCipher) Kind() uint64

type Request

type Request struct {
	Version string      `json:"jsonrpc"`
	Method  string      `json:"method"`
	Params  interface{} `json:"params"`
	ID      int         `json:"id"`
}

type Response

type Response struct {
	Error  *Error          `json:"error"`
	ID     int             `json:"id"`
	Result json.RawMessage `json:"result,omitempty"`
}

type SignedCallDataPack

type SignedCallDataPack struct {
	Data      Data   `json:"data"`
	Leash     Leash  `json:"leash"`
	Signature []byte `json:"signature"`
}

SignedCallDataPack defines a signed call.

It should be encoded and sent in the `data` field of an Ethereum call.

func NewDataPack

func NewDataPack(sign SignerFn, chainID uint64, caller, callee []byte, gasLimit uint64, gasPrice, value *big.Int, data []byte, leash Leash) (*SignedCallDataPack, error)

NewDataPack returns a SignedCallDataPack.

This method does not encrypt `data`, so that should be done afterwards.

func (SignedCallDataPack) Encode

func (p SignedCallDataPack) Encode() []byte

func (SignedCallDataPack) EncryptEncode

func (p SignedCallDataPack) EncryptEncode(cipher Cipher) []byte

type SignerFn

type SignerFn = func(digest [32]byte) ([]byte, error)

SignerFn is a function that produces secp256k1 signatures in RSV format.

type Unknown

type Unknown struct {
	Nonce []byte `json:"nonce"`
	Data  []byte `json:"data"`
}

type WrappedBackend

type WrappedBackend struct {
	// contains filtered or unexported fields
}

func NewWrappedBackend

func NewWrappedBackend(backend bind.ContractBackend, chainID big.Int, cipher Cipher, sign SignerFn) WrappedBackend

func WrapClient

func WrapClient(c ethclient.Client, sign SignerFn) (*WrappedBackend, error)

WrapClient wraps an ethclient.Client so that it can talk to Sapphire.

func (WrappedBackend) CallContract

func (b WrappedBackend) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error)

CallContract implements ContractCaller.

func (WrappedBackend) CodeAt

func (b WrappedBackend) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error)

CodeAt implements ContractCaller.

func (WrappedBackend) EstimateGas

func (b WrappedBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error)

EstimateGas implements ContractTransactor.

func (WrappedBackend) FilterLogs

func (b WrappedBackend) FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error)

FilterLogs implements ContractFilterer.

func (WrappedBackend) HeaderByNumber

func (b WrappedBackend) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)

HeaderByNumber implements ContractTransactor.

func (WrappedBackend) PendingCodeAt

func (b WrappedBackend) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error)

PendingCodeAt implements ContractTransactor.

func (WrappedBackend) PendingNonceAt

func (b WrappedBackend) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error)

PendingNonceAt implements ContractTransactor.

func (WrappedBackend) SendTransaction

func (b WrappedBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error

SendTransaction implements ContractTransactor.

func (WrappedBackend) SubscribeFilterLogs

func (b WrappedBackend) SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error)

SubscribeFilterLogs implements ContractFilterer.

func (WrappedBackend) SuggestGasPrice

func (b WrappedBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error)

SuggestGasPrice implements ContractTransactor.

func (WrappedBackend) SuggestGasTipCap

func (b WrappedBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error)

SuggestGasTipCap implements ContractTransactor.

func (WrappedBackend) Transactor

func (b WrappedBackend) Transactor(from common.Address) *bind.TransactOpts

Transactor returns a TransactOpts that can be used with Sapphire.

type X25519DeoxysIICipher

type X25519DeoxysIICipher struct {
	// contains filtered or unexported fields
}

X25519DeoxysIICipher is the default cipher that does what it says on the tin.

func NewX25519DeoxysIICipher

func NewX25519DeoxysIICipher(keypair Curve25519KeyPair, peerPublicKey [curve25519.PointSize]byte) (*X25519DeoxysIICipher, error)

func (X25519DeoxysIICipher) Decrypt

func (c X25519DeoxysIICipher) Decrypt(nonce []byte, ciphertext []byte) ([]byte, error)

func (X25519DeoxysIICipher) DecryptCallResult

func (c X25519DeoxysIICipher) DecryptCallResult(response []byte) ([]byte, error)

func (X25519DeoxysIICipher) DecryptEncoded

func (c X25519DeoxysIICipher) DecryptEncoded(response []byte) ([]byte, error)

func (X25519DeoxysIICipher) Encrypt

func (c X25519DeoxysIICipher) Encrypt(plaintext []byte) (ciphertext []byte, nonce []byte)

func (X25519DeoxysIICipher) EncryptEncode

func (c X25519DeoxysIICipher) EncryptEncode(plaintext []byte) []byte

func (X25519DeoxysIICipher) EncryptEnvelope

func (c X25519DeoxysIICipher) EncryptEnvelope(plaintext []byte) *EncryptedBodyEnvelope

func (X25519DeoxysIICipher) Kind

func (c X25519DeoxysIICipher) Kind() uint64

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL