Skip to content

Commit

Permalink
feat(fund): Add fundAll function that funds all funders and returns a…
Browse files Browse the repository at this point in the history
… list of times, each funder took to finish.

feat(TestEgoisticParticipantFunding): Add Test that sets one participant as egoistic, funds and checks if egoistic funder funds last.

Signed-off-by: Sophia Koehler <[email protected]>

refactor(multiledger): Add comment, rename function.

Signed-off-by: Sophia Koehler <[email protected]>

refactor(multiledger): Add var for participants length.

Signed-off-by: Sophia Koehler <[email protected]>
  • Loading branch information
sophia1ch committed Apr 2, 2024
1 parent 9e2368d commit cbc555e
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 5 deletions.
88 changes: 88 additions & 0 deletions channel/funder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ package channel_test

import (
"context"
"fmt"
"math"
"math/big"
"math/rand"
"testing"
Expand Down Expand Up @@ -194,6 +196,92 @@ func testFunderCrossOverFunding(t *testing.T, n int) {
assert.NoError(t, compareOnChainAlloc(ctx, params, agreement, alloc.Assets, &funders[0].ContractBackend))
}

func TestEgoisticParticipantFunding(t *testing.T) {
// Peers will randomly fund for each other.
for i := 0; i < 5; 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()
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 TestFunder_ZeroBalance(t *testing.T) {
t.Run("1 Participant", func(t *testing.T) { testFunderZeroBalance(t, 1) })
t.Run("2 Participant", func(t *testing.T) { testFunderZeroBalance(t, 2) })
Expand Down
43 changes: 43 additions & 0 deletions channel/test/fund.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
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"
"time"
)

type FunderFinishTime struct {
Index int // Funder ID
Time time.Duration // Time when Fund method returned
}

func FundAll(ctx context.Context, funders []*channel.Funder, reqs []*pchannel.FundingReq) ([]FunderFinishTime, error) {
g := pkgerrors.NewGatherer()
finishTimes := make([]FunderFinishTime, len(funders))
var wg sync.WaitGroup
var mutex sync.Mutex

wg.Add(len(funders))
for i := range funders {
i := i
g.Go(func() error {
defer wg.Done()
startTime := time.Now()
err := funders[i].Fund(ctx, *reqs[i])
finishTime := time.Now()
mutex.Lock()
finishTimes[i] = FunderFinishTime{
Index: i,
Time: finishTime.Sub(startTime),
}
mutex.Unlock()
return err
})
}
wg.Wait()

return finishTimes, nil
}
11 changes: 6 additions & 5 deletions client/test/multiledger.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func SetupMultiLedgerTest(t *testing.T, testDuration time.Duration) ctest.MultiL
}
}

// SetupMultiLedgerTest creates a multi-ledger test setup.
// 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)
Expand All @@ -112,7 +112,7 @@ func EgoisticTest(t *testing.T, testDuration time.Duration) ctest.MultiLedgerSet
c2 := setupClient(t, rng, l1, l2, bus)

// Setup clients.
TestEgoisticLedger(t, rng, l1, l2, l3)
testEgoisticLedger(t, rng, l1, l2, l3)

// Fund accounts.
l1.simSetup.SimBackend.FundAddress(ctx, wallet.AsEthAddr(c1.WalletAddress))
Expand Down Expand Up @@ -252,7 +252,7 @@ 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) {
func testEgoisticLedger(t *testing.T, rng *rand.Rand, l1, l2, l3 testLedger) {
t.Helper()
require := require.New(t)

Expand Down Expand Up @@ -289,9 +289,10 @@ func TestEgoisticLedger(t *testing.T, rng *rand.Rand, l1, l2, l3 testLedger) {
funderL1 := ethchannel.NewFunder(cb1)
funderL2 := ethchannel.NewFunder(cb2)
funderL3 := ethchannel.NewFunder(cb3)
egoisticPart := make([]bool, 3)
signers := 3
egoisticPart := make([]bool, signers)
egoisticPart[1] = true
funderL2.SetEgoisticPart(1, 3)
funderL2.SetEgoisticPart(1, signers)
require.Equal(egoisticPart, funderL2.EgoisticPart)

egoisticChains := make(map[multi.LedgerIDMapKey]bool)
Expand Down

0 comments on commit cbc555e

Please sign in to comment.