Skip to content

Commit

Permalink
Merge pull request #1619 from statechannels/challenge-registered-test
Browse files Browse the repository at this point in the history
Enhance simulated backend chain service test to cover detecting `ChallengeRegistered` events
  • Loading branch information
geoknee authored Sep 1, 2023
2 parents 3d7fa89 + 9a9f020 commit 6f6e2c4
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 28 deletions.
22 changes: 22 additions & 0 deletions node/engine/chainservice/adjudicator/typeconversions.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,25 @@ func ConvertSignature(s nc.Signature) INitroTypesSignature {
copy(sig.S[:], s.S) // TODO we should just use 32 byte types, which would remove the need for this func
return sig
}

func ConvertSignedStateToFixedPartAndSignedVariablePart(s state.SignedState) (INitroTypesFixedPart, INitroTypesSignedVariablePart) {
fp := ConvertFixedPart(s.State().FixedPart())
svp := INitroTypesSignedVariablePart{
VariablePart: ConvertVariablePart(s.State().VariablePart()),
Sigs: make([]INitroTypesSignature, 0, len(s.Signatures())),
}
for _, sig := range s.Signatures() {
svp.Sigs = append(svp.Sigs, ConvertSignature(sig))
}

return fp, svp
}

func ConvertSignedStatesToProof(ss []state.SignedState) []INitroTypesSignedVariablePart {
svps := make([]INitroTypesSignedVariablePart, 0, len(ss))
for _, s := range ss {
_, svp := ConvertSignedStateToFixedPartAndSignedVariablePart(s)
svps = append(svps, svp)
}
return svps
}
19 changes: 12 additions & 7 deletions node/engine/chainservice/eth_chainservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
ethTypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"

"github.com/statechannels/go-nitro/channel/state"
"github.com/statechannels/go-nitro/internal/logging"
Expand All @@ -25,11 +24,12 @@ import (
)

var (
allocationUpdatedTopic = crypto.Keccak256Hash([]byte("AllocationUpdated(bytes32,uint256,uint256,uint256)"))
concludedTopic = crypto.Keccak256Hash([]byte("Concluded(bytes32,uint48)"))
depositedTopic = crypto.Keccak256Hash([]byte("Deposited(bytes32,address,uint256)"))
challengeRegisteredTopic = crypto.Keccak256Hash([]byte("ChallengeRegistered(bytes32 indexed channelId, uint48 turnNumRecord, uint48 finalizesAt, bool isFinal, (address[],uint64,address,uint48) fixedPart, (((address,(uint8,bytes),(bytes32,uint256,uint8,bytes)[])[],bytes,uint48,bool),(uint8,bytes32,bytes32)[])[] proof, (((address,(uint8,bytes),(bytes32,uint256,uint8,bytes)[])[],bytes,uint48,bool),(uint8,bytes32,bytes32)[]) candidate)"))
challengeClearedTopic = crypto.Keccak256Hash([]byte("ChallengeCleared(bytes32 indexed channelId, uint48 newTurnNumRecord)"))
naAbi, _ = NitroAdjudicator.NitroAdjudicatorMetaData.GetAbi()
concludedTopic = naAbi.Events["Concluded"].ID
allocationUpdatedTopic = naAbi.Events["AllocationUpdated"].ID
depositedTopic = naAbi.Events["Deposited"].ID
challengeRegisteredTopic = naAbi.Events["ChallengeRegistered"].ID
challengeClearedTopic = naAbi.Events["ChallengeCleared"].ID
)

var topicsToWatch = []common.Hash{
Expand Down Expand Up @@ -212,7 +212,12 @@ func (ecs *EthChainService) SendTransaction(tx protocols.ChainTransaction) error
}
_, err := ecs.na.ConcludeAndTransferAllAssets(ecs.defaultTxOpts(), nitroFixedPart, candidate)
return err

case protocols.ChallengeTransaction:
fp, candidate := NitroAdjudicator.ConvertSignedStateToFixedPartAndSignedVariablePart(tx.Candidate)
proof := NitroAdjudicator.ConvertSignedStatesToProof(tx.Proof)
challengerSig := NitroAdjudicator.ConvertSignature(tx.ChallengerSig)
_, err := ecs.na.Challenge(ecs.defaultTxOpts(), fp, proof, candidate, challengerSig)
return err
default:
return fmt.Errorf("unexpected transaction type %T", tx)
}
Expand Down
65 changes: 44 additions & 21 deletions node/engine/chainservice/simulated_backend_chainservice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ import (
"github.com/statechannels/go-nitro/channel/state"
"github.com/statechannels/go-nitro/channel/state/outcome"
"github.com/statechannels/go-nitro/internal/testactors"
NitroAdjudicator "github.com/statechannels/go-nitro/node/engine/chainservice/adjudicator"
"github.com/statechannels/go-nitro/protocols"
"github.com/statechannels/go-nitro/types"
)

var (
Alice = testactors.Alice
Bob = testactors.Bob
CHALLENGE_DURATION = uint32(1000) // 1000 seconds. Much longer than the duration of the test
Alice = testactors.Alice
Bob = testactors.Bob
)

var concludeOutcome = outcome.Exit{
Expand All @@ -36,12 +38,6 @@ var concludeOutcome = outcome.Exit{
},
}

type NoopLogger struct{}

func (l NoopLogger) Write(p []byte) (n int, err error) {
return 0, nil
}

func TestSimulatedBackendChainService(t *testing.T) {
one := big.NewInt(1)
three := big.NewInt(3)
Expand All @@ -65,21 +61,52 @@ func TestSimulatedBackendChainService(t *testing.T) {
},
ChannelNonce: 37140676580,
AppDefinition: bindings.ConsensusApp.Address,
ChallengeDuration: 0,
ChallengeDuration: CHALLENGE_DURATION,
AppData: []byte{},
Outcome: concludeOutcome,
TurnNum: uint64(2),
IsFinal: true,
}

// Prepare test data to trigger EthChainService
challengerSig, err := NitroAdjudicator.SignChallengeMessage(concludeState, Alice.PrivateKey)
if err != nil {
t.Fatal(err)
}
concludeSignedState := state.NewSignedState(concludeState)
aSig, err := concludeState.Sign(Alice.PrivateKey)
if err != nil {
t.Fatal(err)
}
bSig, err := concludeState.Sign(Bob.PrivateKey)
if err != nil {
t.Fatal(err)
}
_ = concludeSignedState.AddSignature(aSig)
_ = concludeSignedState.AddSignature(bSig)

challengeTx := protocols.NewChallengeTransaction(concludeState.ChannelId(), concludeSignedState, make([]state.SignedState, 0), challengerSig)

out := cs.EventFeed()
err = cs.SendTransaction(challengeTx)
if err != nil {
t.Fatal(err)
}

// Check that the received events matches the expected event

receivedEvent := <-out
crEvent := receivedEvent.(ChallengeRegisteredEvent)
expectedChallengeRegisteredEvent := NewChallengeRegisteredEvent(concludeState.ChannelId(), 2, crEvent.candidate, crEvent.candidateSignatures)
if diff := cmp.Diff(expectedChallengeRegisteredEvent, crEvent, cmp.AllowUnexported(ChallengeRegisteredEvent{}, commonEvent{}, big.Int{})); diff != "" {
t.Fatalf("Received event did not match expectation; (-want +got):\n%s", diff)
}

testDeposit := types.Funds{
common.HexToAddress("0x00"): three,
bindings.Token.Address: one,
}
testTx := protocols.NewDepositTransaction(concludeState.ChannelId(), testDeposit)

out := cs.EventFeed()
// Submit transaction
err = cs.SendTransaction(testTx)
if err != nil {
Expand All @@ -90,8 +117,8 @@ func TestSimulatedBackendChainService(t *testing.T) {
for i := 0; i < 2; i++ {
receivedEvent := <-out
dEvent := receivedEvent.(DepositedEvent)
expectedEvent := NewDepositedEvent(concludeState.ChannelId(), 2, dEvent.Asset, testDeposit[dEvent.Asset])
if diff := cmp.Diff(expectedEvent, dEvent, cmp.AllowUnexported(DepositedEvent{}, commonEvent{}, big.Int{})); diff != "" {
expectedDepositEvent := NewDepositedEvent(concludeState.ChannelId(), 5, dEvent.Asset, testDeposit[dEvent.Asset])
if diff := cmp.Diff(expectedDepositEvent, dEvent, cmp.AllowUnexported(DepositedEvent{}, commonEvent{}, big.Int{})); diff != "" {
t.Fatalf("Received event did not match expectation; (-want +got):\n%s", diff)
}
delete(testDeposit, dEvent.Asset)
Expand All @@ -101,10 +128,6 @@ func TestSimulatedBackendChainService(t *testing.T) {
t.Fatalf("Mismatch between the deposit transaction and the received events")
}

// Generate Signatures
aSig, _ := concludeState.Sign(Alice.PrivateKey)
bSig, _ := concludeState.Sign(Bob.PrivateKey)

cId := concludeState.ChannelId()

signedConcludeState := state.NewSignedState(concludeState)
Expand All @@ -123,16 +146,16 @@ func TestSimulatedBackendChainService(t *testing.T) {
}
// Check that the recieved event matches the expected event
concludedEvent := <-out
expectedEvent := ConcludedEvent{commonEvent: commonEvent{channelID: cId, blockNum: 5}}
if diff := cmp.Diff(expectedEvent, concludedEvent, cmp.AllowUnexported(ConcludedEvent{}, commonEvent{})); diff != "" {
expectedConcludeEvent := ConcludedEvent{commonEvent: commonEvent{channelID: cId, blockNum: 8}}
if diff := cmp.Diff(expectedConcludeEvent, concludedEvent, cmp.AllowUnexported(ConcludedEvent{}, commonEvent{})); diff != "" {
t.Fatalf("Received event did not match expectation; (-want +got):\n%s", diff)
}

// Check that the recieved event matches the expected event
allocationUpdatedEvent := <-out
expectedEvent2 := NewAllocationUpdatedEvent(cId, 5, common.Address{}, new(big.Int).SetInt64(1))
expectedAllocationUpdatedEvent := NewAllocationUpdatedEvent(cId, 8, common.Address{}, new(big.Int).SetInt64(1))

if diff := cmp.Diff(expectedEvent2, allocationUpdatedEvent, cmp.AllowUnexported(AllocationUpdatedEvent{}, commonEvent{}, big.Int{})); diff != "" {
if diff := cmp.Diff(expectedAllocationUpdatedEvent, allocationUpdatedEvent, cmp.AllowUnexported(AllocationUpdatedEvent{}, commonEvent{}, big.Int{})); diff != "" {
t.Fatalf("Received event did not match expectation; (-want +got):\n%s", diff)
}

Expand Down
22 changes: 22 additions & 0 deletions protocols/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/statechannels/go-nitro/channel/consensus_channel"
"github.com/statechannels/go-nitro/channel/state"
"github.com/statechannels/go-nitro/crypto"
"github.com/statechannels/go-nitro/types"
)

Expand Down Expand Up @@ -44,6 +45,27 @@ func NewWithdrawAllTransaction(channelId types.Destination, signedState state.Si
return WithdrawAllTransaction{SignedState: signedState, ChainTransaction: ChainTransactionBase{channelId: channelId}}
}

type ChallengeTransaction struct {
ChainTransaction
Candidate state.SignedState
Proof []state.SignedState
ChallengerSig crypto.Signature
}

func NewChallengeTransaction(
channelId types.Destination,
candidate state.SignedState,
proof []state.SignedState,
challengerSig crypto.Signature,
) ChallengeTransaction {
return ChallengeTransaction{
ChainTransaction: ChainTransactionBase{channelId: channelId},
Candidate: candidate,
Proof: proof,
ChallengerSig: challengerSig,
}
}

// SideEffects are effects to be executed by an imperative shell
type SideEffects struct {
MessagesToSend []Message
Expand Down

0 comments on commit 6f6e2c4

Please sign in to comment.