Skip to content

Commit

Permalink
Merge branch 'main' into draft/egoistic-funding
Browse files Browse the repository at this point in the history
  • Loading branch information
NhoxxKienn authored Jul 2, 2024
2 parents 4c96443 + 3c47eab commit 99867bb
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 1 deletion.
51 changes: 50 additions & 1 deletion channel/funder_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 - See NOTICE file for copyright holders.
// Copyright 2024 - 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.
Expand All @@ -16,6 +16,8 @@ package channel_test

import (
"context"
"fmt"
"math"
"math/big"
"math/rand"
"testing"
Expand Down Expand Up @@ -194,6 +196,53 @@ 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 < 30; i++ {
name := fmt.Sprintf("Egoistic Funding %v", i)
t.Run(name, func(t *testing.T) { testEgoisticParticipantFunding(t) })
}
}

func testEgoisticParticipantFunding(t *testing.T) {
t.Helper()
t.Parallel()
n := 2
rng := pkgtest.Prng(t, n)
EgoisticTxTimeout := 20 * time.Second
ctx, cancel := context.WithTimeout(context.Background(), EgoisticTxTimeout*time.Duration(n))
defer cancel()
_, 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
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 {
req := channel.NewFundingReq(params, &channel.State{Allocation: allocation}, channel.Index(i), agreement)
fundingRequests[i] = req
}
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("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
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
68 changes: 68 additions & 0 deletions channel/test/fund.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright 2024 - 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"
"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
Time time.Duration
}

// 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 mutex sync.Mutex

var wg sync.WaitGroup
wg.Add(len(funders))

for i := range funders {
i := i
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{
Index: i,
Time: finishTime.Sub(startTime),
}
mutex.Unlock()
}()
}

wg.Wait()
return finishTimes, nil
}

0 comments on commit 99867bb

Please sign in to comment.