From c927b786cf28cf824c4d612fe3af785538a8dc58 Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Wed, 20 Sep 2023 10:16:02 +0300 Subject: [PATCH] Make fee destination less predictable and avoid using go-specific randomness. --- .../cons/bp/aggregated_batch_proposals.go | 8 ++++---- packages/chain/cons/bp/batch_proposal_set.go | 19 +++++++++++++------ packages/chain/cons/cons.go | 2 +- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/packages/chain/cons/bp/aggregated_batch_proposals.go b/packages/chain/cons/bp/aggregated_batch_proposals.go index 3cc242d54c..3f5a557804 100644 --- a/packages/chain/cons/bp/aggregated_batch_proposals.go +++ b/packages/chain/cons/bp/aggregated_batch_proposals.go @@ -18,11 +18,11 @@ import ( // Here we store just an aggregated info. type AggregatedBatchProposals struct { shouldBeSkipped bool + batchProposalSet batchProposalSet decidedIndexProposals map[gpa.NodeID][]int decidedBaseAliasOutput *isc.AliasOutputWithID decidedRequestRefs []*isc.RequestRef aggregatedTime time.Time - validatorFeeTarget isc.AgentID } func AggregateBatchProposals(inputs map[gpa.NodeID][]byte, nodeIDs []gpa.NodeID, f int, log *logger.Logger) *AggregatedBatchProposals { @@ -51,11 +51,11 @@ func AggregateBatchProposals(inputs map[gpa.NodeID][]byte, nodeIDs []gpa.NodeID, aggregatedTime := bps.aggregatedTime(f) decidedBaseAliasOutput := bps.decidedBaseAliasOutput(f) abp := &AggregatedBatchProposals{ + batchProposalSet: bps, decidedIndexProposals: bps.decidedDSSIndexProposals(), decidedBaseAliasOutput: decidedBaseAliasOutput, decidedRequestRefs: bps.decidedRequestRefs(f, decidedBaseAliasOutput), aggregatedTime: aggregatedTime, - validatorFeeTarget: bps.selectedFeeDestination(aggregatedTime), } if abp.decidedBaseAliasOutput == nil || len(abp.decidedRequestRefs) == 0 || abp.aggregatedTime.IsZero() { log.Debugf( @@ -92,11 +92,11 @@ func (abp *AggregatedBatchProposals) AggregatedTime() time.Time { return abp.aggregatedTime } -func (abp *AggregatedBatchProposals) ValidatorFeeTarget() isc.AgentID { +func (abp *AggregatedBatchProposals) ValidatorFeeTarget(randomness hashing.HashValue) isc.AgentID { if abp.shouldBeSkipped { panic("trying to use aggregated proposal marked to be skipped") } - return abp.validatorFeeTarget + return abp.batchProposalSet.selectedFeeDestination(abp.aggregatedTime, randomness) } func (abp *AggregatedBatchProposals) DecidedRequestRefs() []*isc.RequestRef { diff --git a/packages/chain/cons/bp/batch_proposal_set.go b/packages/chain/cons/bp/batch_proposal_set.go index 7b64c1fb20..3b641dc7c1 100644 --- a/packages/chain/cons/bp/batch_proposal_set.go +++ b/packages/chain/cons/bp/batch_proposal_set.go @@ -5,6 +5,7 @@ package bp import ( "bytes" + "encoding/binary" "sort" "time" @@ -13,7 +14,6 @@ import ( "github.com/iotaledger/wasp/packages/gpa" "github.com/iotaledger/wasp/packages/hashing" "github.com/iotaledger/wasp/packages/isc" - "github.com/iotaledger/wasp/packages/util" ) type batchProposalSet map[gpa.NodeID]*BatchProposal @@ -113,7 +113,7 @@ func (bps batchProposalSet) aggregatedTime(f int) time.Time { return ts[proposalCount-f-1] // Max(|acsProposals|-F Lowest) ~= 66 percentile. } -func (bps batchProposalSet) selectedProposal(aggregatedTime time.Time) gpa.NodeID { +func (bps batchProposalSet) selectedProposal(aggregatedTime time.Time, randomness hashing.HashValue) gpa.NodeID { peers := make([]gpa.NodeID, 0, len(bps)) for nid := range bps { peers = append(peers, nid) @@ -121,11 +121,18 @@ func (bps batchProposalSet) selectedProposal(aggregatedTime time.Time) gpa.NodeI slices.SortFunc(peers, func(a gpa.NodeID, b gpa.NodeID) int { return bytes.Compare(a[:], b[:]) }) - rnd := util.NewPseudoRand(aggregatedTime.UnixNano()) - return peers[rnd.Intn(len(bps))] + uint64Bytes := make([]byte, 8) + binary.BigEndian.PutUint64(uint64Bytes, uint64(aggregatedTime.UnixNano())) + hashed := hashing.HashDataBlake2b( + uint64Bytes, + randomness[:], + ) + randomUint := binary.BigEndian.Uint64(hashed[:]) + randomPos := int(randomUint % uint64(len(bps))) + return peers[randomPos] } -func (bps batchProposalSet) selectedFeeDestination(aggregatedTime time.Time) isc.AgentID { - bp := bps[bps.selectedProposal(aggregatedTime)] +func (bps batchProposalSet) selectedFeeDestination(aggregatedTime time.Time, randomness hashing.HashValue) isc.AgentID { + bp := bps[bps.selectedProposal(aggregatedTime, randomness)] return bp.validatorFeeDestination } diff --git a/packages/chain/cons/cons.go b/packages/chain/cons/cons.go index 564c3a7410..2ce980a900 100644 --- a/packages/chain/cons/cons.go +++ b/packages/chain/cons/cons.go @@ -559,7 +559,7 @@ func (c *consImpl) uponVMInputsReceived(aggregatedProposals *bp.AggregatedBatchP Requests: aggregatedProposals.OrderedRequests(requests, *randomness), TimeAssumption: aggregatedProposals.AggregatedTime(), Entropy: *randomness, - ValidatorFeeTarget: aggregatedProposals.ValidatorFeeTarget(), + ValidatorFeeTarget: aggregatedProposals.ValidatorFeeTarget(*randomness), EstimateGasMode: false, EnableGasBurnLogging: false, Log: c.log.Named("VM"),