Skip to content

Commit

Permalink
Merge branch 'add-ckb-example' into payment-channel-ckb
Browse files Browse the repository at this point in the history
  • Loading branch information
tinnendo authored Oct 23, 2024
2 parents 6e78a06 + 91e65f9 commit 74c3499
Show file tree
Hide file tree
Showing 69 changed files with 2,730 additions and 2,887 deletions.
27 changes: 17 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: 1.17
go-version: '1.22'

- uses: actions/cache@v3
with:
Expand All @@ -22,8 +22,8 @@ jobs:
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Pull ganache image
- name: Pull ganache-cli image
run: docker pull ${{ env.ganache-image }}

- name: Simple Client
Expand All @@ -45,14 +45,15 @@ jobs:
BALANCE: "10000000000000000000"
run: |
docker run --rm --name ganache --detach --publish 8545:8545 ${{ env.ganache-image }} --wallet.accounts $KEY_DEPLOYER,$BALANCE $KEY_ALICE,$BALANCE $KEY_BOB,$BALANCE --b=5
sleep 5
go run .
docker stop ganache
- name: Payment Channel DOT
working-directory: payment-channel-dot
run: |
docker run --name polkadot --detach --rm -it -p 9944:9944 ghcr.io/perun-network/polkadot-test-node
docker run --name polkadot --detach --rm -it -p 9944:9944 ghcr.io/perun-network/polkadot-test-node:0.4.0
sleep 5
go run .
docker stop polkadot
Expand All @@ -66,14 +67,20 @@ jobs:
BALANCE: "10000000000000000000"
run: |
docker run --rm --name ganache --detach --publish 8545:8545 ${{ env.ganache-image }} --wallet.accounts $KEY_DEPLOYER,$BALANCE $KEY_ALICE,$BALANCE $KEY_BOB,$BALANCE --b=5
sleep 5
go run .
docker stop ganache
- name: Collateralized Channels
working-directory: collateralized-channels
env:
GANACHE_CMD: "docker run --name ganache --rm --publish 8545:8545 ${{ env.ganache-image }}"
- name: Payment Channel XLM
working-directory: payment-channel-xlm
run: |
go test -v -timeout 60s .
docker stop ganache || true # Cleanup
chmod +x ./testdata/docker/build.sh
./testdata/docker/build.sh
chmod +x ./quickstart.sh
./quickstart.sh standalone &
sleep 30
go run ./
8 changes: 6 additions & 2 deletions app-channel/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ func (a *TicTacToeApp) Def() wallet.Address {
return a.Addr
}

func (a *TicTacToeApp) NewData() channel.Data {
return &TicTacToeAppData{}
}

func (a *TicTacToeApp) InitData(firstActor channel.Index) *TicTacToeAppData {
return &TicTacToeAppData{
NextActor: uint8(firstActor),
Expand Down Expand Up @@ -93,9 +97,9 @@ func (a *TicTacToeApp) ValidInit(p *channel.Params, s *channel.State) error {

// ValidTransition is called whenever the channel state transitions.
func (a *TicTacToeApp) ValidTransition(params *channel.Params, from, to *channel.State, idx channel.Index) error {
err := channel.AssetsAssertEqual(from.Assets, to.Assets)
err := channel.AssertAssetsEqual(from.Assets, to.Assets)
if err != nil {
return fmt.Errorf("Invalid assets: %v", err)
return fmt.Errorf("invalid assets: %v", err)
}

fromData, ok := from.Data.(*TicTacToeAppData)
Expand Down
21 changes: 21 additions & 0 deletions app-channel/app/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,27 @@ func (d *TicTacToeAppData) String() string {
return b.String()
}

func (d *TicTacToeAppData) MarshalBinary() ([]byte, error) {
var b bytes.Buffer
err := d.Encode(&b)
return b.Bytes(), err
}

func (d *TicTacToeAppData) UnmarshalBinary(data []byte) error {
var err error
buffer := bytes.NewBuffer(data)
d.NextActor, err = readUInt8(buffer)
if err != nil {
return errors.WithMessage(err, "reading actor")
}
grid, err := readUInt8Array(buffer, len(d.Grid))
if err != nil {
return errors.WithMessage(err, "reading grid")
}
copy(d.Grid[:], makeFieldValueArray(grid))
return nil
}

// Encode encodes app data onto an io.Writer.
func (d *TicTacToeAppData) Encode(w io.Writer) error {
err := writeUInt8(w, d.NextActor)
Expand Down
9 changes: 6 additions & 3 deletions app-channel/client/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@ func newTicTacToeChannel(ch *client.Channel) *TicTacToeChannel {

// Set sends a game move to the channel peer.
func (g *TicTacToeChannel) Set(x, y int) {
err := g.ch.UpdateBy(context.TODO(), func(state *channel.State) error {
err := g.ch.Update(context.TODO(), func(state *channel.State) {
app, ok := state.App.(*app.TicTacToeApp)
if !ok {
return fmt.Errorf("invalid app type: %T", app)
panic(fmt.Errorf("invalid app type: %T", app))
}

return app.Set(state, x, y, g.ch.Idx())
err := app.Set(state, x, y, g.ch.Idx())
if err != nil {
panic(err)
}
})
if err != nil {
panic(err) // We panic on error to keep the code simple.
Expand Down
31 changes: 19 additions & 12 deletions app-channel/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ package client
import (
"context"
"fmt"
"math/big"

ethchannel "github.com/perun-network/perun-eth-backend/channel"
ethwallet "github.com/perun-network/perun-eth-backend/wallet"
swallet "github.com/perun-network/perun-eth-backend/wallet/simple"
ethwire "github.com/perun-network/perun-eth-backend/wire"

ethchannel "perun.network/go-perun/backend/ethereum/channel"
ethwallet "perun.network/go-perun/backend/ethereum/wallet"
swallet "perun.network/go-perun/backend/ethereum/wallet/simple"
"perun.network/go-perun/channel"
"perun.network/go-perun/client"
"perun.network/go-perun/wallet"
Expand All @@ -39,8 +42,9 @@ const (

// AppClient is an app channel client.
type AppClient struct {
perunClient *client.Client // The core Perun client.
account wallet.Address // The account we use for on-chain and off-chain transactions.
perunClient *client.Client // The core Perun client.
account wallet.Address // The account we use for on-chain and off-chain transactions.
waddress wire.Address
currency channel.Asset // The currency we expect to get paid in.
stake channel.Bal // The amount we put at stake.
app *app.TicTacToeApp // The app definition.
Expand All @@ -52,10 +56,11 @@ func SetupAppClient(
bus wire.Bus, // bus is used of off-chain communication.
w *swallet.Wallet, // w is the wallet used for signing transactions.
acc common.Address, // acc is the address of the account to be used for signing transactions.
eaddress *ethwallet.Address, // eaddress is the address of the Ethereum account to be used for signing transactions.
nodeURL string, // nodeURL is the URL of the blockchain node.
chainID uint64, // chainID is the identifier of the blockchain.
adjudicator common.Address, // adjudicator is the address of the adjudicator.
asset ethwallet.Address, // asset is the address of the asset holder for our app channels.
assetaddr ethwallet.Address, // asset is the address of the asset holder for our app channels.
app *app.TicTacToeApp, // app is the channel app we want to set up the client with.
stake channel.Bal, // stake is the balance the client is willing to fund the channel with.
) (*AppClient, error) {
Expand All @@ -70,7 +75,7 @@ func SetupAppClient(
if err != nil {
return nil, fmt.Errorf("validating adjudicator: %w", err)
}
err = ethchannel.ValidateAssetHolderETH(context.TODO(), cb, common.Address(asset), adjudicator)
err = ethchannel.ValidateAssetHolderETH(context.TODO(), cb, common.Address(assetaddr), adjudicator)
if err != nil {
return nil, fmt.Errorf("validating adjudicator: %w", err)
}
Expand All @@ -79,7 +84,8 @@ func SetupAppClient(
funder := ethchannel.NewFunder(cb)
dep := ethchannel.NewETHDepositor()
ethAcc := accounts.Account{Address: acc}
funder.RegisterAsset(asset, dep, ethAcc)
asset := ethchannel.NewAsset(big.NewInt(int64(chainID)), common.Address(assetaddr))
funder.RegisterAsset(*asset, dep, ethAcc)

// Setup adjudicator.
adj := ethchannel.NewAdjudicator(cb, adjudicator, acc, ethAcc)
Expand All @@ -91,7 +97,7 @@ func SetupAppClient(
}

// Setup Perun client.
waddr := ethwallet.AsWalletAddr(acc)
waddr := &ethwire.Address{Address: eaddress}
perunClient, err := client.New(waddr, bus, funder, adj, w, watcher)
if err != nil {
return nil, errors.WithMessage(err, "creating client")
Expand All @@ -100,8 +106,9 @@ func SetupAppClient(
// Create client and start request handler.
c := &AppClient{
perunClient: perunClient,
account: waddr,
currency: &asset,
account: eaddress,
waddress: waddr,
currency: asset,
stake: stake,
app: app,
channels: make(chan *TicTacToeChannel, 1),
Expand All @@ -115,7 +122,7 @@ func SetupAppClient(

// OpenAppChannel opens a new app channel with the specified peer.
func (c *AppClient) OpenAppChannel(peer wire.Address) *TicTacToeChannel {
participants := []wire.Address{c.account, peer}
participants := []wire.Address{c.waddress, peer}

// We create an initial allocation which defines the starting balances.
initAlloc := channel.NewAllocation(2, c.currency)
Expand Down
23 changes: 12 additions & 11 deletions app-channel/client/handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,41 +18,42 @@ import (
"context"
"fmt"
"log"

"perun.network/go-perun/channel"
"perun.network/go-perun/client"
)

// HandleProposal is the callback for incoming channel proposals.
func (c *AppClient) HandleProposal(p client.ChannelProposal, r *client.ProposalResponder) {
lcp, err := func() (*client.LedgerChannelProposal, error) {
lcp, err := func() (*client.LedgerChannelProposalMsg, error) {
// Ensure that we got a ledger channel proposal.
lcp, ok := p.(*client.LedgerChannelProposal)
lcp, ok := p.(*client.LedgerChannelProposalMsg)
if !ok {
return nil, fmt.Errorf("Invalid proposal type: %T\n", p)
return nil, fmt.Errorf("invalid proposal type: %T", p)
}

// Ensure the ledger channel proposal includes the expected app.
if !lcp.App.Def().Equals(c.app.Def()) {
return nil, fmt.Errorf("Invalid app type ")
if !lcp.App.Def().Equal(c.app.Def()) {
return nil, fmt.Errorf("invalid app type ")
}

// Check that we have the correct number of participants.
if lcp.NumPeers() != 2 {
return nil, fmt.Errorf("Invalid number of participants: %d", lcp.NumPeers())
return nil, fmt.Errorf("invalid number of participants: %d", lcp.NumPeers())
}

// Check that the channel has the expected assets.
err := channel.AssetsAssertEqual(lcp.InitBals.Assets, []channel.Asset{c.currency})
err := channel.AssertAssetsEqual(lcp.InitBals.Assets, []channel.Asset{c.currency})
if err != nil {
return nil, fmt.Errorf("Invalid assets: %v\n", err)
return nil, fmt.Errorf("invalid assets: %v", err)
}

// Check that the channel has the expected assets and funding balances.
const assetIdx, peerIdx = 0, 1
if err := channel.AssetsAssertEqual(lcp.InitBals.Assets, []channel.Asset{c.currency}); err != nil {
return nil, fmt.Errorf("Invalid assets: %v\n", err)
if err := channel.AssertAssetsEqual(lcp.InitBals.Assets, []channel.Asset{c.currency}); err != nil {
return nil, fmt.Errorf("invalid assets: %v", err)
} else if lcp.FundingAgreement[assetIdx][peerIdx].Cmp(c.stake) != 0 {
return nil, fmt.Errorf("Invalid funding balance")
return nil, fmt.Errorf("invalid funding balance")
}
return lcp, nil
}()
Expand Down
13 changes: 7 additions & 6 deletions app-channel/client/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ package client

import (
"math/big"

"perun.network/go-perun/wire"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
ethchannel "perun.network/go-perun/backend/ethereum/channel"
ethwallet "perun.network/go-perun/backend/ethereum/wallet"
swallet "perun.network/go-perun/backend/ethereum/wallet/simple"
ethchannel "github.com/perun-network/perun-eth-backend/channel"
ethwallet "github.com/perun-network/perun-eth-backend/wallet"
swallet "github.com/perun-network/perun-eth-backend/wallet/simple"
)

// CreateContractBackend creates a new contract backend.
Expand All @@ -32,15 +33,15 @@ func CreateContractBackend(
chainID uint64,
w *swallet.Wallet,
) (ethchannel.ContractBackend, error) {
signer := types.NewEIP155Signer(new(big.Int).SetUint64(chainID))
signer := types.LatestSignerForChainID(new(big.Int).SetUint64(chainID))
transactor := swallet.NewTransactor(w, signer)

ethClient, err := ethclient.Dial(nodeURL)
if err != nil {
return ethchannel.ContractBackend{}, err
}

return ethchannel.NewContractBackend(ethClient, transactor, txFinalityDepth), nil
return ethchannel.NewContractBackend(ethClient, ethchannel.MakeChainID(big.NewInt(int64(chainID))), transactor, txFinalityDepth), nil
}

// WalletAddress returns the wallet address of the client.
Expand All @@ -50,7 +51,7 @@ func (c *AppClient) WalletAddress() common.Address {

// WireAddress returns the wire address of the client.
func (c *AppClient) WireAddress() wire.Address {
return c.account
return c.waddress
}

// EthToWei converts a given amount in ETH to Wei.
Expand Down
5 changes: 2 additions & 3 deletions app-channel/contracts/TicTacToeApp.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@

// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.7.0;
pragma experimental ABIEncoderV2;
pragma solidity ^0.8.0;

import "./perun-eth-contracts/contracts/App.sol";

Expand Down Expand Up @@ -71,7 +70,7 @@ contract TicTacToeApp is App {
// Test final state.
(bool isFinal, bool hasWinner, uint8 winner) = checkFinal(to.appData);
require(to.isFinal == isFinal, "final flag");
Array.requireEqualAddressArray(to.outcome.assets, from.outcome.assets);
Channel.requireEqualAssetArray(to.outcome.assets, from.outcome.assets);
Channel.requireEqualSubAllocArray(to.outcome.locked, from.outcome.locked);
uint256[][] memory expectedBalances = from.outcome.balances;
if (hasWinner) {
Expand Down
Loading

0 comments on commit 74c3499

Please sign in to comment.