Skip to content

Commit f661f51

Browse files
author
Manoranjith
authored
Merge pull request #307 from boschresearch/301-proposal-id-generation
💥 Update the mechanism for proposal ID generation Implements perun-proposal #6.
2 parents f3f8a24 + f2270ba commit f661f51

File tree

3 files changed

+23
-132
lines changed

3 files changed

+23
-132
lines changed

client/proposal.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ func (c *Client) handleChannelProposalRej(
280280
req ChannelProposal, reason string,
281281
) error {
282282
msgReject := &ChannelProposalRejMsg{
283-
ProposalID: req.ProposalID(),
283+
ProposalID: req.Base().ProposalID,
284284
Reason: reason,
285285
}
286286
if err := c.conn.pubMsg(ctx, msgReject, p); err != nil {
@@ -305,7 +305,7 @@ func (c *Client) proposeTwoPartyChannel(
305305
pred := enableVer0Cache(c.conn)
306306
defer c.conn.ReleaseCache(pred)
307307

308-
proposalID := proposal.ProposalID()
308+
proposalID := proposal.Base().ProposalID
309309
isResponse := func(e *wire.Envelope) bool {
310310
acc, isAcc := e.Msg.(ChannelProposalAccept)
311311
return (isAcc && acc.Base().ProposalID == proposalID) ||
@@ -467,7 +467,7 @@ func (c *Client) validChannelProposalAcc(
467467
return errors.Errorf("Received invalid accept message %T to proposal %T", response, proposal)
468468
}
469469

470-
propID := proposal.ProposalID()
470+
propID := proposal.Base().ProposalID
471471
accID := response.Base().ProposalID
472472
if !bytes.Equal(propID[:], accID[:]) {
473473
return errors.Errorf("mismatched proposal ID %b and accept ID %b", propID, accID)

client/proposalmsgs.go

Lines changed: 15 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package client
1616

1717
import (
18+
"crypto/rand"
1819
"hash"
1920
"io"
2021

@@ -93,9 +94,6 @@ type (
9394

9495
// Valid checks whether a channel proposal is valid.
9596
Valid() error
96-
97-
// ProposalID calculates the proposal's unique identifier.
98-
ProposalID() ProposalID
9997
}
10098

10199
// BaseChannelProposal contains all data necessary to propose a new
@@ -104,6 +102,7 @@ type (
104102
// BaseChannelProposal implements the channel proposal messages from the
105103
// Multi-Party Channel Proposal Protocol (MPCPP).
106104
BaseChannelProposal struct {
105+
ProposalID ProposalID // Unique ID for the proposal.
107106
ChallengeDuration uint64 // Dispute challenge duration.
108107
NonceShare NonceShare // Proposer's channel nonce share.
109108
App channel.App // App definition, or nil.
@@ -165,8 +164,14 @@ func makeBaseChannelProposal(
165164
}
166165
}
167166

167+
var proposalID ProposalID
168+
if _, err := io.ReadFull(rand.Reader, proposalID[:]); err != nil {
169+
return BaseChannelProposal{}, errors.Wrap(err, "generating proposal ID")
170+
}
171+
168172
return BaseChannelProposal{
169173
ChallengeDuration: challengeDuration,
174+
ProposalID: proposalID,
170175
NonceShare: opt.nonce(),
171176
App: opt.App(),
172177
InitData: opt.AppData(),
@@ -188,7 +193,7 @@ func (p BaseChannelProposal) NumPeers() int {
188193
// Encode encodes the BaseChannelProposal into an io.Writer.
189194
func (p BaseChannelProposal) Encode(w io.Writer) error {
190195
optAppAndDataEnc := channel.OptAppAndDataEnc{App: p.App, Data: p.InitData}
191-
return perunio.Encode(w, p.ChallengeDuration, p.NonceShare,
196+
return perunio.Encode(w, p.ProposalID, p.ChallengeDuration, p.NonceShare,
192197
optAppAndDataEnc, p.InitBals, p.FundingAgreement)
193198
}
194199

@@ -198,7 +203,7 @@ func (p *BaseChannelProposal) Decode(r io.Reader) (err error) {
198203
p.InitBals = new(channel.Allocation)
199204
}
200205
optAppAndDataDec := channel.OptAppAndDataDec{App: &p.App, Data: &p.InitData}
201-
return perunio.Decode(r, &p.ChallengeDuration, &p.NonceShare,
206+
return perunio.Decode(r, &p.ProposalID, &p.ChallengeDuration, &p.NonceShare,
202207
optAppAndDataDec, p.InitBals, &p.FundingAgreement)
203208
}
204209

@@ -229,12 +234,12 @@ func (p LedgerChannelProposalMsg) Accept(
229234
nonceShare ProposalOpts,
230235
) *LedgerChannelProposalAccMsg {
231236
if !nonceShare.isNonce() {
232-
log.WithField("proposal", p.ProposalID()).
237+
log.WithField("proposal", p.ProposalID).
233238
Panic("LedgerChannelProposal.Accept: nonceShare has no configured nonce")
234239
}
235240
return &LedgerChannelProposalAccMsg{
236241
BaseChannelProposalAcc: makeBaseChannelProposalAcc(
237-
p.ProposalID(), nonceShare.nonce()),
242+
p.ProposalID, nonceShare.nonce()),
238243
Participant: participant,
239244
}
240245
}
@@ -275,16 +280,6 @@ func (LedgerChannelProposalMsg) Type() wire.Type {
275280
return wire.LedgerChannelProposal
276281
}
277282

278-
// ProposalID returns the identifier of this channel proposal request.
279-
func (p LedgerChannelProposalMsg) ProposalID() (propID ProposalID) {
280-
hasher := newHasher()
281-
if err := perunio.Encode(hasher, p); err != nil {
282-
log.Panicf("proposal ID nonce encoding: %v", err)
283-
}
284-
copy(propID[:], hasher.Sum(nil))
285-
return
286-
}
287-
288283
// Encode encodes a ledger channel proposal.
289284
func (p LedgerChannelProposalMsg) Encode(w io.Writer) error {
290285
if err := p.assertValidNumParts(); err != nil {
@@ -347,16 +342,6 @@ func NewSubChannelProposal(
347342
return
348343
}
349344

350-
// ProposalID returns the identifier of this channel proposal request.
351-
func (p SubChannelProposalMsg) ProposalID() (propID ProposalID) {
352-
hasher := newHasher()
353-
if err := perunio.Encode(hasher, p); err != nil {
354-
log.Panicf("proposal ID nonce encoding: %v", err)
355-
}
356-
copy(propID[:], hasher.Sum(nil))
357-
return
358-
}
359-
360345
// Encode encodes the SubChannelProposal into an io.Writer.
361346
func (p SubChannelProposalMsg) Encode(w io.Writer) error {
362347
return perunio.Encode(w, p.BaseChannelProposal, p.Parent)
@@ -377,14 +362,13 @@ func (SubChannelProposalMsg) Type() wire.Type {
377362
func (p SubChannelProposalMsg) Accept(
378363
nonceShare ProposalOpts,
379364
) *SubChannelProposalAccMsg {
380-
propID := p.ProposalID()
381365
if !nonceShare.isNonce() {
382-
log.WithField("proposal", propID).
366+
log.WithField("proposal", p.ProposalID).
383367
Panic("SubChannelProposal.Accept: nonceShare has no configured nonce")
384368
}
385369
return &SubChannelProposalAccMsg{
386370
BaseChannelProposalAcc: makeBaseChannelProposalAcc(
387-
propID, nonceShare.nonce()),
371+
p.ProposalID, nonceShare.nonce()),
388372
}
389373
}
390374

@@ -602,25 +586,14 @@ func (VirtualChannelProposalMsg) Type() wire.Type {
602586
return wire.VirtualChannelProposal
603587
}
604588

605-
// ProposalID returns the identifier of this channel proposal.
606-
func (p VirtualChannelProposalMsg) ProposalID() (propID ProposalID) {
607-
hasher := newHasher()
608-
if err := perunio.Encode(hasher, p); err != nil {
609-
log.Panicf("proposal ID base encoding: %v", err)
610-
}
611-
copy(propID[:], hasher.Sum(nil))
612-
return
613-
}
614-
615589
// Accept constructs an accept message that belongs to a proposal message.
616590
func (p VirtualChannelProposalMsg) Accept(
617591
responder wallet.Address,
618592
opts ...ProposalOpts,
619593
) *VirtualChannelProposalAccMsg {
620-
propID := p.ProposalID()
621594
_opts := union(opts...)
622595
return &VirtualChannelProposalAccMsg{
623-
BaseChannelProposalAcc: makeBaseChannelProposalAcc(propID, _opts.nonce()),
596+
BaseChannelProposalAcc: makeBaseChannelProposalAcc(p.ProposalID, _opts.nonce()),
624597
Responder: responder,
625598
}
626599
}

client/proposalmsgs_test.go

Lines changed: 5 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -79,68 +79,21 @@ func TestChannelProposalReqSerialization(t *testing.T) {
7979
func TestLedgerChannelProposalReqProposalID(t *testing.T) {
8080
rng := pkgtest.Prng(t)
8181
original := *client.NewRandomLedgerChannelProposal(rng)
82-
s := original.ProposalID()
83-
fake := *client.NewRandomLedgerChannelProposal(rng)
84-
85-
assert.NotEqual(t, original.ChallengeDuration, fake.ChallengeDuration)
86-
assert.NotEqual(t, original.NonceShare, fake.NonceShare)
87-
assert.NotEqual(t, original.App, fake.App)
88-
89-
c0 := original
90-
c0.ChallengeDuration = fake.ChallengeDuration
91-
assert.NotEqual(t, s, c0.ProposalID())
92-
93-
c1 := original
94-
c1.NonceShare = fake.NonceShare
95-
assert.NotEqual(t, s, c1.ProposalID())
96-
97-
c2 := original
98-
c2.Participant = fake.Participant
99-
assert.NotEqual(t, s, c2.ProposalID())
10082

101-
c3 := original
102-
c3.App = fake.App
103-
assert.NotEqual(t, s, c3.ProposalID())
104-
105-
c4 := original
106-
c4.InitData = fake.InitData
107-
assert.NotEqual(t, s, c4.ProposalID())
108-
109-
c5 := original
110-
c5.InitBals = fake.InitBals
111-
assert.NotEqual(t, s, c5.ProposalID())
83+
fake := *client.NewRandomLedgerChannelProposal(rng)
11284

113-
c6 := original
114-
c6.Peers = fake.Peers
115-
assert.NotEqual(t, s, c6.ProposalID())
85+
assert.NotEqual(t, original.ProposalID, fake.ProposalID)
11686
}
11787

11888
func TestSubChannelProposalReqProposalID(t *testing.T) {
11989
rng := pkgtest.Prng(t)
12090
original, err := clienttest.NewRandomSubChannelProposal(rng)
12191
require.NoError(t, err)
122-
s := original.ProposalID()
92+
12393
fake, err := clienttest.NewRandomSubChannelProposal(rng)
12494
require.NoError(t, err)
12595

126-
assert.NotEqual(t, original.ChallengeDuration, fake.ChallengeDuration)
127-
assert.NotEqual(t, original.NonceShare, fake.NonceShare)
128-
129-
c0 := original
130-
c0.ChallengeDuration = fake.ChallengeDuration
131-
assert.NotEqual(t, s, c0.ProposalID())
132-
133-
c1 := original
134-
c1.NonceShare = fake.NonceShare
135-
assert.NotEqual(t, s, c1.ProposalID())
136-
137-
c2 := original
138-
c2.Parent = fake.Parent
139-
assert.NotEqual(t, s, c2.ProposalID())
140-
141-
c3 := original
142-
c3.InitBals = fake.InitBals
143-
assert.NotEqual(t, s, c3.ProposalID())
96+
assert.NotEqual(t, original.ProposalID, fake.ProposalID)
14497
}
14598

14699
func TestVirtualChannelProposalReqProposalID(t *testing.T) {
@@ -156,42 +109,7 @@ func TestVirtualChannelProposalReqProposalID(t *testing.T) {
156109
assert.Equal(t, channel.NoApp(), fake.App, "virtual channel should always has no app")
157110
assert.Equal(t, channel.NoData(), fake.InitData, "virtual channel should always has no data")
158111

159-
assert.NotEqual(t, original.ChallengeDuration, fake.ChallengeDuration)
160-
assert.NotEqual(t, original.NonceShare, fake.NonceShare)
161-
assert.NotEqual(t, original.InitBals, fake.InitBals)
162-
assert.NotEqual(t, original.FundingAgreement, fake.FundingAgreement)
163-
assert.NotEqual(t, original.Proposer, fake.Proposer)
164-
assert.NotEqual(t, original.Peers, fake.Peers)
165-
assert.NotEqual(t, original.Parents, fake.Parents)
166-
assert.NotEqual(t, original.IndexMaps, fake.IndexMaps)
167-
168-
testProp := *original
169-
testProp.ChallengeDuration = fake.ChallengeDuration
170-
assert.NotEqual(t, original.ProposalID(), testProp.ProposalID())
171-
172-
testProp = *original
173-
testProp.NonceShare = fake.NonceShare
174-
assert.NotEqual(t, original.ProposalID(), testProp.ProposalID())
175-
176-
testProp = *original
177-
testProp.InitBals = fake.InitBals
178-
assert.NotEqual(t, original.ProposalID(), testProp.ProposalID())
179-
180-
testProp = *original
181-
testProp.FundingAgreement = fake.FundingAgreement
182-
assert.NotEqual(t, original.ProposalID(), testProp.ProposalID())
183-
184-
testProp = *original
185-
testProp.Proposer = fake.Proposer
186-
assert.NotEqual(t, original.ProposalID(), testProp.ProposalID())
187-
188-
testProp = *original
189-
testProp.Peers = fake.Peers
190-
assert.NotEqual(t, original.ProposalID(), testProp.ProposalID())
191-
192-
testProp = *original
193-
testProp.IndexMaps = fake.IndexMaps
194-
assert.NotEqual(t, original.ProposalID(), testProp.ProposalID())
112+
assert.NotEqual(t, original.ProposalID, fake.ProposalID)
195113
}
196114

197115
func TestChannelProposalAccSerialization(t *testing.T) {

0 commit comments

Comments
 (0)