From 75716be4fab0cf3dcb8378b2ccbc45a5b99d24ab Mon Sep 17 00:00:00 2001 From: Cassandra Heart Date: Tue, 26 Nov 2024 18:50:25 -0600 Subject: [PATCH] =?UTF-8?q?=E3=81=95=E3=82=88=E3=81=AA=E3=82=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/data_clock_consensus_engine.go | 5 ++-- node/consensus/data/message_handler.go | 4 +++ node/consensus/data/message_validators.go | 26 ++++++++++++++++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/node/consensus/data/data_clock_consensus_engine.go b/node/consensus/data/data_clock_consensus_engine.go index 3ef95b9..4d83e0c 100644 --- a/node/consensus/data/data_clock_consensus_engine.go +++ b/node/consensus/data/data_clock_consensus_engine.go @@ -121,7 +121,7 @@ type DataClockConsensusEngine struct { dependencyMapMx sync.Mutex stagedTransactions *protobufs.TokenRequests stagedTransactionsSet map[string]struct{} - stagedTransactionsMx sync.Mutex + stagedTransactionsMx sync.RWMutex peerMapMx sync.RWMutex peerAnnounceMapMx sync.Mutex lastKeyBundleAnnouncementFrame uint64 @@ -270,7 +270,8 @@ func NewDataClockConsensusEngine( rateLimit, time.Minute, ), - requestSyncCh: make(chan struct{}, 1), + requestSyncCh: make(chan struct{}, 1), + stagedTransactionsSet: map[string]struct{}{}, } logger.Info("constructing consensus engine") diff --git a/node/consensus/data/message_handler.go b/node/consensus/data/message_handler.go index a49cc23..44efa1d 100644 --- a/node/consensus/data/message_handler.go +++ b/node/consensus/data/message_handler.go @@ -2,6 +2,7 @@ package data import ( "bytes" + "encoding/binary" "fmt" "sync" "time" @@ -381,6 +382,9 @@ func TokenRequestIdentifiers(transition *protobufs.TokenRequest) []string { case *protobufs.TokenRequest_Mint: if len(t.Mint.Proofs) == 1 { return []string{fmt.Sprintf("mint-proof-%x", sha3.Sum512(t.Mint.Proofs[0]))} + } else if len(t.Mint.Proofs) >= 3 { + frameNumber := binary.BigEndian.Uint64(t.Mint.Proofs[2]) + return []string{fmt.Sprintf("mint-sign-%d-%x", frameNumber, t.Mint.Signature.PublicKey.KeyValue)} } return []string{fmt.Sprintf("mint-sign-%x", t.Mint.Signature.PublicKey.KeyValue)} case *protobufs.TokenRequest_Announce: diff --git a/node/consensus/data/message_validators.go b/node/consensus/data/message_validators.go index 47567ee..8e881b5 100644 --- a/node/consensus/data/message_validators.go +++ b/node/consensus/data/message_validators.go @@ -2,6 +2,7 @@ package data import ( "encoding/binary" + "fmt" "time" "github.com/libp2p/go-libp2p/core/peer" @@ -61,11 +62,34 @@ func (e *DataClockConsensusEngine) validateTxMessage(peerID peer.ID, message *pb if len(mint.Proofs[2]) != 8 { return p2p.ValidationResultReject } + if mint.Signature == nil || + mint.Signature.PublicKey == nil || + mint.Signature.PublicKey.KeyValue == nil { + return p2p.ValidationResultReject + } head, err := e.dataTimeReel.Head() if err != nil { panic(err) } - if frameNumber := binary.BigEndian.Uint64(mint.Proofs[2]); frameNumber+2 < head.FrameNumber { + + // cheap hack for handling protobuf trickery: because protobufs can be + // serialized in infinite ways, message ids can be regenerated simply by + // modifying the data without affecting the underlying signed message. + // if this is encountered, go scorched earth on the sender – a thank you + // message for destabilizing the network. + frameNumber := binary.BigEndian.Uint64(mint.Proofs[2]) + id := fmt.Sprintf( + "mint-sign-%d-%x", + frameNumber, + mint.Signature.PublicKey.KeyValue, + ) + e.stagedTransactionsMx.RLock() + _, ok := e.stagedTransactionsSet[id] + e.stagedTransactionsMx.RUnlock() + if ok { + return p2p.ValidationResultReject + } + if frameNumber+2 < head.FrameNumber { return p2p.ValidationResultIgnore } }