diff --git a/channel/funder_test.go b/channel/funder_test.go index 530cbfc..c7225a3 100644 --- a/channel/funder_test.go +++ b/channel/funder_test.go @@ -198,59 +198,20 @@ func testFunderCrossOverFunding(t *testing.T, n int) { func TestEgoisticParticipantFunding(t *testing.T) { // Peers will randomly fund for each other. - for i := 0; i < 5; i++ { + for i := 0; i < 30; i++ { name := fmt.Sprintf("Egoistic Funding %v", i) t.Run(name, func(t *testing.T) { testEgoisticParticipantFunding(t) }) } } func testEgoisticParticipantFunding(t *testing.T) { - EgoisticTxTimeout := 10 * time.Second - n := 2 t.Helper() t.Parallel() - ctx, cancel := context.WithTimeout(context.Background(), EgoisticTxTimeout*time.Duration(n)) - defer cancel() - rng := pkgtest.Prng(t, n) - _, funders, params, alloc := newNFunders(ctx, t, rng, n) - egoisticIndex := rng.Intn(2) - balances := [][]*big.Int{ - {big.NewInt(1), big.NewInt(0)}, - {big.NewInt(0), big.NewInt(2)}, - } - allocation := channel.Allocation{Assets: alloc.Assets, Balances: balances, Locked: alloc.Locked} - egoisticParts := make([]bool, n) - funders[egoisticIndex].SetEgoisticPart(channel.Index(egoisticIndex), n) - egoisticParts[egoisticIndex] = true - - agreement := channeltest.ShuffleBalances(rng, allocation.Balances) - require.Equal(t, agreement.Sum(), allocation.Balances.Sum()) - - fundingRequests := make([]*channel.FundingReq, n) - for i, _ := range funders { - req := channel.NewFundingReq(params, &channel.State{Allocation: allocation}, channel.Index(i), agreement) - fundingRequests[i] = req - } - finishTimes, err := test.FundAll(ctx, funders, fundingRequests) - require.True(t, len(finishTimes) == n, "Length of indexes must be n") - require.NoError(t, err) - - t.Logf("Finish Times: %v", finishTimes) - // Check if finish time of egoistic funder is larger than finish time of non-egoistic funder. - correct := finishTimes[egoisticIndex].Time > finishTimes[int(math.Abs(float64(1-egoisticIndex)))].Time - // Use require.True to compare the finish times - require.True(t, correct, "Non-egoistic funders finish earlier than egoistic funders") - assert.NoError(t, compareOnChainAlloc(ctx, params, agreement, allocation.Assets, &funders[0].ContractBackend)) -} - -func TestEgoisticChainFunding(t *testing.T) { - EgoisticTxTimeout := 10 * time.Second n := 2 - t.Helper() - t.Parallel() + rng := pkgtest.Prng(t, n) + EgoisticTxTimeout := 20 * time.Second ctx, cancel := context.WithTimeout(context.Background(), EgoisticTxTimeout*time.Duration(n)) defer cancel() - rng := pkgtest.Prng(t, n) _, funders, params, alloc := newNFunders(ctx, t, rng, n) egoisticIndex := rng.Intn(2) balances := [][]*big.Int{ @@ -261,20 +222,20 @@ func TestEgoisticChainFunding(t *testing.T) { egoisticParts := make([]bool, n) funders[egoisticIndex].SetEgoisticPart(channel.Index(egoisticIndex), n) egoisticParts[egoisticIndex] = true - - agreement := channeltest.ShuffleBalances(rng, allocation.Balances) + t.Logf("Egoistic Participants: %v", egoisticParts) + agreement := allocation.Balances require.Equal(t, agreement.Sum(), allocation.Balances.Sum()) fundingRequests := make([]*channel.FundingReq, n) - for i, _ := range funders { + for i := range funders { req := channel.NewFundingReq(params, &channel.State{Allocation: allocation}, channel.Index(i), agreement) fundingRequests[i] = req } - finishTimes, err := test.FundAll(ctx, funders, fundingRequests) + finishTimes, err := test.FundAll(ctx, t, funders, fundingRequests, egoisticIndex) require.True(t, len(finishTimes) == n, "Length of indexes must be n") require.NoError(t, err) - t.Logf("Finish Times: %v", finishTimes) + t.Logf("finishTimes: %v", finishTimes) // Check if finish time of egoistic funder is larger than finish time of non-egoistic funder. correct := finishTimes[egoisticIndex].Time > finishTimes[int(math.Abs(float64(1-egoisticIndex)))].Time // Use require.True to compare the finish times diff --git a/channel/test/fund.go b/channel/test/fund.go index c9d2bb3..4f27741 100644 --- a/channel/test/fund.go +++ b/channel/test/fund.go @@ -1,32 +1,58 @@ +// Copyright 2020 - See NOTICE file for copyright holders. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package test import ( "context" - "github.com/perun-network/perun-eth-backend/channel" - pchannel "perun.network/go-perun/channel" - pkgerrors "polycry.pt/poly-go/errors" "sync" + "testing" "time" + + "github.com/perun-network/perun-eth-backend/channel" + "github.com/stretchr/testify/require" + pchannel "perun.network/go-perun/channel" ) +// waitTime is the time to wait before funding a channel when the funder is not egoistic. +const waitTime = 2 * time.Second + +// FunderFinishTime is the returned type of FundAll which includes the process time of each funder. type FunderFinishTime struct { - Index int // Funder ID - Time time.Duration // Time when Fund method returned + Index int + Time time.Duration } -func FundAll(ctx context.Context, funders []*channel.Funder, reqs []*pchannel.FundingReq) ([]FunderFinishTime, error) { - g := pkgerrors.NewGatherer() +// FundAll calls fund for all funders simultaneously. +func FundAll(ctx context.Context, t *testing.T, funders []*channel.Funder, reqs []*pchannel.FundingReq, egoisticIndex int) ([]FunderFinishTime, error) { + t.Helper() finishTimes := make([]FunderFinishTime, len(funders)) - var wg sync.WaitGroup var mutex sync.Mutex + var wg sync.WaitGroup wg.Add(len(funders)) + for i := range funders { i := i - g.Go(func() error { + go func() { defer wg.Done() + if i != egoisticIndex { + time.Sleep(waitTime) + } startTime := time.Now() err := funders[i].Fund(ctx, *reqs[i]) + require.NoError(t, err) finishTime := time.Now() mutex.Lock() finishTimes[i] = FunderFinishTime{ @@ -34,10 +60,9 @@ func FundAll(ctx context.Context, funders []*channel.Funder, reqs []*pchannel.Fu Time: finishTime.Sub(startTime), } mutex.Unlock() - return err - }) + }() } - wg.Wait() + wg.Wait() return finishTimes, nil } diff --git a/client/multiledger_test.go b/client/multiledger_test.go index f7dc560..46262f9 100644 --- a/client/multiledger_test.go +++ b/client/multiledger_test.go @@ -44,11 +44,3 @@ func TestMultiLedgerDispute(t *testing.T) { mlt := test.SetupMultiLedgerTest(t, testDuration) ctest.TestMultiLedgerDispute(ctx, t, mlt, challengeDuration) } - -func TestEgoisticMultiLedger(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), testDuration) - defer cancel() - - mlt := test.EgoisticTest(t, testDuration) - ctest.TestMultiLedgerDispute(ctx, t, mlt, challengeDuration) -} diff --git a/client/test/multiledger.go b/client/test/multiledger.go index 4f1650c..711e631 100644 --- a/client/test/multiledger.go +++ b/client/test/multiledger.go @@ -92,56 +92,6 @@ func SetupMultiLedgerTest(t *testing.T, testDuration time.Duration) ctest.MultiL } } -// EgoisticTest creates a egoistic multi-ledger test setup and tests egoistic functions. -func EgoisticTest(t *testing.T, testDuration time.Duration) ctest.MultiLedgerSetup { - t.Helper() - rng := test.Prng(t) - - ctx, cancel := context.WithTimeout(context.Background(), testDuration) - defer cancel() - - l1 := setupLedger(ctx, t, rng, big.NewInt(1337)) //nolint:gomnd - l2 := setupLedger(ctx, t, rng, big.NewInt(1338)) //nolint:gomnd - l3 := setupLedger(ctx, t, rng, big.NewInt(134)) //nolint:gomnd - - // Setup message bus. - bus := wire.NewLocalBus() - - // Setup clients. - c1 := setupClient(t, rng, l1, l2, bus) - c2 := setupClient(t, rng, l1, l2, bus) - - // Setup clients. - testEgoisticLedger(t, rng, l1, l2, l3) - - // Fund accounts. - l1.simSetup.SimBackend.FundAddress(ctx, wallet.AsEthAddr(c1.WalletAddress)) - l1.simSetup.SimBackend.FundAddress(ctx, wallet.AsEthAddr(c2.WalletAddress)) - l2.simSetup.SimBackend.FundAddress(ctx, wallet.AsEthAddr(c1.WalletAddress)) - l2.simSetup.SimBackend.FundAddress(ctx, wallet.AsEthAddr(c2.WalletAddress)) - - //nolint:gomnd - return ctest.MultiLedgerSetup{ - Client1: c1, - Client2: c2, - Asset1: l1.asset, - Asset2: l2.asset, - InitBalances: channel.Balances{ - {EtherToWei(8), EtherToWei(2)}, // Asset 1. - {EtherToWei(2), EtherToWei(8)}, // Asset 2. - }, - UpdateBalances1: channel.Balances{ - {EtherToWei(5), EtherToWei(5)}, // Asset 1. - {EtherToWei(3), EtherToWei(7)}, // Asset 2. - }, - UpdateBalances2: channel.Balances{ - {EtherToWei(1), EtherToWei(9)}, // Asset 1. - {EtherToWei(5), EtherToWei(5)}, // Asset 2. - }, - BalanceDelta: EtherToWei(0.00012), - } -} - type testLedger struct { simSetup *chtest.SimSetup adjudicator common.Address @@ -204,7 +154,6 @@ func setupClient(t *testing.T, rng *rand.Rand, l1, l2 testLedger, bus wire.Bus) multiFunder := multi.NewFunder() funderL1 := ethchannel.NewFunder(cb1) funderL2 := ethchannel.NewFunder(cb2) - registered := funderL1.RegisterAsset(*l1.asset, ethchannel.NewETHDepositor(defaultETHGasLimit), acc.Account) require.True(registered) registered = funderL1.RegisterAsset(*l2.asset, ethchannel.NewNoOpDepositor(), acc.Account) @@ -252,71 +201,6 @@ func setupClient(t *testing.T, rng *rand.Rand, l1, l2 testLedger, bus wire.Bus) } } -func testEgoisticLedger(t *testing.T, rng *rand.Rand, l1, l2, l3 testLedger) { - t.Helper() - require := require.New(t) - - // Setup wallet and account. - w := wtest.RandomWallet().(*keystore.Wallet) - acc := w.NewRandomAccount(rng).(*keystore.Account) - - // Setup contract backends. - signer1 := l1.simSetup.SimBackend.Signer - cb1 := ethchannel.NewContractBackend( - l1.simSetup.CB, - l1.ChainID(), - keystore.NewTransactor(*w, signer1), - l1.simSetup.CB.TxFinalityDepth(), - ) - signer2 := l2.simSetup.SimBackend.Signer - cb2 := ethchannel.NewContractBackend( - l2.simSetup.CB, - l2.ChainID(), - keystore.NewTransactor(*w, signer2), - l2.simSetup.CB.TxFinalityDepth(), - ) - - signer3 := l3.simSetup.SimBackend.Signer - cb3 := ethchannel.NewContractBackend( - l3.simSetup.CB, - l3.ChainID(), - keystore.NewTransactor(*w, signer3), - l3.simSetup.CB.TxFinalityDepth(), - ) - - // Setup funder. - multiFunder := multi.NewFunder() - funderL1 := ethchannel.NewFunder(cb1) - funderL2 := ethchannel.NewFunder(cb2) - funderL3 := ethchannel.NewFunder(cb3) - signers := 3 - egoisticPart := make([]bool, signers) - egoisticPart[1] = true - funderL2.SetEgoisticPart(1, signers) - require.Equal(egoisticPart, funderL2.EgoisticPart) - - egoisticChains := make(map[multi.LedgerIDMapKey]bool) - egoisticChains[funderL2.ChainID().MapKey()] = true - multiFunder.SetEgoisticChain(funderL2.ChainID(), true) - require.Equal(egoisticChains, multiFunder.EgoisticChains) - - registered := funderL1.RegisterAsset(*l1.asset, ethchannel.NewETHDepositor(defaultETHGasLimit), acc.Account) - require.True(registered) - registered = funderL1.RegisterAsset(*l2.asset, ethchannel.NewNoOpDepositor(), acc.Account) - require.True(registered) - registered = funderL2.RegisterAsset(*l1.asset, ethchannel.NewNoOpDepositor(), acc.Account) - require.True(registered) - registered = funderL2.RegisterAsset(*l2.asset, ethchannel.NewETHDepositor(defaultETHGasLimit), acc.Account) - require.True(registered) - registered = funderL3.RegisterAsset(*l1.asset, ethchannel.NewNoOpDepositor(), acc.Account) - require.True(registered) - registered = funderL3.RegisterAsset(*l2.asset, ethchannel.NewETHDepositor(defaultETHGasLimit), acc.Account) - require.True(registered) - multiFunder.RegisterFunder(l1.ChainID(), funderL1) - multiFunder.RegisterFunder(l2.ChainID(), funderL2) - multiFunder.RegisterFunder(l3.ChainID(), funderL3) -} - // EtherToWei converts eth to wei. func EtherToWei(eth float64) *big.Int { weiFloat := new(big.Float).Mul(big.NewFloat(eth), new(big.Float).SetFloat64(params.Ether))