From 8534e340bdedbde38b8e6c27a9d901a0151cc5e9 Mon Sep 17 00:00:00 2001 From: amir babazadeh Date: Thu, 5 Oct 2023 21:17:49 +0330 Subject: [PATCH 1/4] feat: implementing pip-7 --- sync/bundle/message/hello.go | 39 +++++++++++++++++++++--------------- sync/handler_hello.go | 9 +++++++++ 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/sync/bundle/message/hello.go b/sync/bundle/message/hello.go index 204447f85..40079c7d4 100644 --- a/sync/bundle/message/hello.go +++ b/sync/bundle/message/hello.go @@ -2,6 +2,7 @@ package message import ( "fmt" + "time" "github.com/libp2p/go-libp2p/core/peer" "github.com/pactus-project/pactus/crypto/bls" @@ -12,28 +13,30 @@ import ( ) type HelloMessage struct { - PeerID peer.ID `cbor:"1,keyasint"` - Agent string `cbor:"2,keyasint"` - Moniker string `cbor:"3,keyasint"` - PublicKeys []*bls.PublicKey `cbor:"4,keyasint"` - Signature *bls.Signature `cbor:"5,keyasint"` - Height uint32 `cbor:"6,keyasint"` - Services services.Services `cbor:"7,keyasint"` - GenesisHash hash.Hash `cbor:"8,keyasint"` - BlockHash hash.Hash `cbor:"9,keyasint"` + PeerID peer.ID `cbor:"1,keyasint"` + Agent string `cbor:"2,keyasint"` + Moniker string `cbor:"3,keyasint"` + PublicKeys []*bls.PublicKey `cbor:"4,keyasint"` + Signature *bls.Signature `cbor:"5,keyasint"` + Height uint32 `cbor:"6,keyasint"` + Services services.Services `cbor:"7,keyasint"` + GenesisHash hash.Hash `cbor:"8,keyasint"` + BlockHash hash.Hash `cbor:"9,keyasint"` + MyTimeUnixMilli int64 `cbor:"10,keyasint"` } func NewHelloMessage(pid peer.ID, moniker string, height uint32, services services.Services, blockHash, genesisHash hash.Hash, ) *HelloMessage { return &HelloMessage{ - PeerID: pid, - Agent: version.Agent(), - Moniker: moniker, - GenesisHash: genesisHash, - BlockHash: blockHash, - Height: height, - Services: services, + PeerID: pid, + Agent: version.Agent(), + Moniker: moniker, + GenesisHash: genesisHash, + BlockHash: blockHash, + Height: height, + Services: services, + MyTimeUnixMilli: time.Now().UnixMilli(), } } @@ -48,6 +51,10 @@ func (m *HelloMessage) BasicCheck() error { return aggPublicKey.Verify(m.SignBytes(), m.Signature) } +func (m *HelloMessage) MyTime() time.Time { + return time.UnixMilli(m.MyTimeUnixMilli) +} + func (m *HelloMessage) SignBytes() []byte { return []byte(fmt.Sprintf("%s:%s:%s:%s", m.Type(), m.Agent, m.PeerID, m.GenesisHash.String())) } diff --git a/sync/handler_hello.go b/sync/handler_hello.go index 50ef4f05e..92cb45cfa 100644 --- a/sync/handler_hello.go +++ b/sync/handler_hello.go @@ -2,6 +2,7 @@ package sync import ( "fmt" + "time" "github.com/libp2p/go-libp2p/core/peer" "github.com/pactus-project/pactus/sync/bundle" @@ -38,6 +39,14 @@ func (handler *helloHandler) ParseMessage(m message.Message, initiator peer.ID) return handler.acknowledge(response, initiator) } + if time.Since(msg.MyTime()) > 10*time.Second { + response := message.NewHelloAckMessage(message.ResponseCodeRejected, + fmt.Sprintf("hello message difference time is more than 10 seconds,"+ + " my node time: %v, hello message time: %v", time.Now().UTC(), msg.MyTime().UTC())) + + return handler.acknowledge(response, initiator) + } + handler.logger.Debug("updating peer info", "pid", initiator.ShortString(), "moniker", msg.Moniker, From 4ae7496668e9836c74cb5d8e3d22597edab537ee Mon Sep 17 00:00:00 2001 From: amir babazadeh Date: Thu, 5 Oct 2023 21:18:10 +0330 Subject: [PATCH 2/4] test: implementing tests of pip-7 --- sync/bundle/message/hello_test.go | 12 ++++++++++++ sync/handler_hello_test.go | 29 +++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/sync/bundle/message/hello_test.go b/sync/bundle/message/hello_test.go index d37dec7fc..d3f4d52c0 100644 --- a/sync/bundle/message/hello_test.go +++ b/sync/bundle/message/hello_test.go @@ -2,6 +2,7 @@ package message import ( "testing" + "time" "github.com/pactus-project/pactus/crypto" "github.com/pactus-project/pactus/crypto/bls" @@ -15,6 +16,17 @@ func TestHelloType(t *testing.T) { assert.Equal(t, m.Type(), TypeHello) } +func TestHelloMessageMyTimeUnix(t *testing.T) { + myTime := time.Now() + myTimeUnixMilli := myTime.UnixMilli() + m := &HelloMessage{ + MyTimeUnixMilli: myTimeUnixMilli, + } + + assert.Equal(t, myTimeUnixMilli, m.MyTimeUnixMilli) + assert.Equal(t, myTimeUnixMilli, m.MyTime().UnixMilli()) +} + func TestHelloMessage(t *testing.T) { ts := testsuite.NewTestSuite(t) diff --git a/sync/handler_hello_test.go b/sync/handler_hello_test.go index 76ca91750..9b6dae86e 100644 --- a/sync/handler_hello_test.go +++ b/sync/handler_hello_test.go @@ -2,6 +2,7 @@ package sync import ( "testing" + "time" "github.com/pactus-project/pactus/crypto/bls" "github.com/pactus-project/pactus/sync/bundle" @@ -29,8 +30,8 @@ func TestParsingHelloMessages(t *testing.T) { assert.NoError(t, td.receivingNewMessage(td.sync, msg, initiator)) assert.Equal(t, td.sync.peerSet.GetPeer(initiator).Status, peerset.StatusCodeBanned) - bundle := td.shouldPublishMessageWithThisType(t, td.network, message.TypeHelloAck) - assert.Equal(t, bundle.Message.(*message.HelloAckMessage).ResponseCode, message.ResponseCodeRejected) + bdl := td.shouldPublishMessageWithThisType(t, td.network, message.TypeHelloAck) + assert.Equal(t, bdl.Message.(*message.HelloAckMessage).ResponseCode, message.ResponseCodeRejected) }) t.Run("Receiving Hello message from a peer. Genesis hash is wrong.", @@ -44,8 +45,24 @@ func TestParsingHelloMessages(t *testing.T) { assert.NoError(t, td.receivingNewMessage(td.sync, msg, pid)) td.checkPeerStatus(t, pid, peerset.StatusCodeBanned) - bundle := td.shouldPublishMessageWithThisType(t, td.network, message.TypeHelloAck) - assert.Equal(t, bundle.Message.(*message.HelloAckMessage).ResponseCode, message.ResponseCodeRejected) + bdl := td.shouldPublishMessageWithThisType(t, td.network, message.TypeHelloAck) + assert.Equal(t, bdl.Message.(*message.HelloAckMessage).ResponseCode, message.ResponseCodeRejected) + }) + + t.Run("Receiving Hello message from a peer. Difference of Hello Message Time with node time is a lot.", + func(t *testing.T) { + valKey := td.RandValKey() + height := td.RandUint32NonZero(td.state.LastBlockHeight()) + pid := td.RandPeerID() + msg := message.NewHelloMessage(pid, "kitty", height, services.New(services.Network), + td.state.LastBlockHash(), td.state.Genesis().Hash()) + msg.Sign([]*bls.ValidatorKey{valKey}) + + msg.MyTimeUnixMilli = msg.MyTime().Add(-11 * time.Second).UnixMilli() + assert.NoError(t, td.receivingNewMessage(td.sync, msg, pid)) + td.checkPeerStatus(t, pid, peerset.StatusCodeBanned) + bdl := td.shouldPublishMessageWithThisType(t, td.network, message.TypeHelloAck) + assert.Equal(t, bdl.Message.(*message.HelloAckMessage).ResponseCode, message.ResponseCodeRejected) }) t.Run("Receiving Hello message from a peer. It should be acknowledged and updates the peer info", @@ -59,8 +76,8 @@ func TestParsingHelloMessages(t *testing.T) { assert.NoError(t, td.receivingNewMessage(td.sync, msg, pid)) - bundle := td.shouldPublishMessageWithThisType(t, td.network, message.TypeHelloAck) - assert.Equal(t, bundle.Message.(*message.HelloAckMessage).ResponseCode, message.ResponseCodeOK) + bdl := td.shouldPublishMessageWithThisType(t, td.network, message.TypeHelloAck) + assert.Equal(t, bdl.Message.(*message.HelloAckMessage).ResponseCode, message.ResponseCodeOK) // Check if the peer info is updated p := td.sync.peerSet.GetPeer(pid) From 5cf5231be4b90d965fc4ede8c97f8727d82efea9 Mon Sep 17 00:00:00 2001 From: amir babazadeh Date: Fri, 6 Oct 2023 22:04:21 +0330 Subject: [PATCH 3/4] fix: resolve request changes plus calc abs of time.since --- sync/bundle/message/hello_test.go | 31 ++++++++++++++++++++----------- sync/handler_hello.go | 6 +++--- sync/handler_hello_test.go | 20 ++++++++++++++++++-- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/sync/bundle/message/hello_test.go b/sync/bundle/message/hello_test.go index d3f4d52c0..2f8fb03f3 100644 --- a/sync/bundle/message/hello_test.go +++ b/sync/bundle/message/hello_test.go @@ -16,17 +16,6 @@ func TestHelloType(t *testing.T) { assert.Equal(t, m.Type(), TypeHello) } -func TestHelloMessageMyTimeUnix(t *testing.T) { - myTime := time.Now() - myTimeUnixMilli := myTime.UnixMilli() - m := &HelloMessage{ - MyTimeUnixMilli: myTimeUnixMilli, - } - - assert.Equal(t, myTimeUnixMilli, m.MyTimeUnixMilli) - assert.Equal(t, myTimeUnixMilli, m.MyTime().UnixMilli()) -} - func TestHelloMessage(t *testing.T) { ts := testsuite.NewTestSuite(t) @@ -57,6 +46,26 @@ func TestHelloMessage(t *testing.T) { assert.Equal(t, errors.Code(m.BasicCheck()), errors.ErrInvalidPublicKey) }) + t.Run("MyTimeUnixMilli of time1 is less or equal than hello message time", func(t *testing.T) { + time1 := time.Now() + myTimeUnixMilli := time1.UnixMilli() + + m := NewHelloMessage(ts.RandPeerID(), "Alice", 100, 0, ts.RandHash(), ts.RandHash()) + + assert.LessOrEqual(t, m.MyTimeUnixMilli, time.Now().UnixMilli()) + assert.GreaterOrEqual(t, m.MyTimeUnixMilli, myTimeUnixMilli) + }) + + t.Run("MyTimeUnixMilli of time1 is greater than hello message time", func(t *testing.T) { + m := NewHelloMessage(ts.RandPeerID(), "Alice", 100, 0, ts.RandHash(), ts.RandHash()) + <-time.After(time.Millisecond) + + time1 := time.Now() + myTimeUnixMilli := time1.UnixMilli() + + assert.GreaterOrEqual(t, myTimeUnixMilli, m.MyTimeUnixMilli) + }) + t.Run("Ok", func(t *testing.T) { valKey := ts.RandValKey() m := NewHelloMessage(ts.RandPeerID(), "Alice", 100, 0, ts.RandHash(), ts.RandHash()) diff --git a/sync/handler_hello.go b/sync/handler_hello.go index 92cb45cfa..e9858cf0f 100644 --- a/sync/handler_hello.go +++ b/sync/handler_hello.go @@ -2,6 +2,7 @@ package sync import ( "fmt" + "math" "time" "github.com/libp2p/go-libp2p/core/peer" @@ -39,10 +40,9 @@ func (handler *helloHandler) ParseMessage(m message.Message, initiator peer.ID) return handler.acknowledge(response, initiator) } - if time.Since(msg.MyTime()) > 10*time.Second { + if math.Abs(time.Since(msg.MyTime()).Seconds()) > 10 { response := message.NewHelloAckMessage(message.ResponseCodeRejected, - fmt.Sprintf("hello message difference time is more than 10 seconds,"+ - " my node time: %v, hello message time: %v", time.Now().UTC(), msg.MyTime().UTC())) + "time discrepancy exceeds 10 seconds") return handler.acknowledge(response, initiator) } diff --git a/sync/handler_hello_test.go b/sync/handler_hello_test.go index 9b6dae86e..5fcc8cba2 100644 --- a/sync/handler_hello_test.go +++ b/sync/handler_hello_test.go @@ -49,7 +49,7 @@ func TestParsingHelloMessages(t *testing.T) { assert.Equal(t, bdl.Message.(*message.HelloAckMessage).ResponseCode, message.ResponseCodeRejected) }) - t.Run("Receiving Hello message from a peer. Difference of Hello Message Time with node time is a lot.", + t.Run("Receiving Hello message from a peer. Difference is greater or equal than -10 seconds.", func(t *testing.T) { valKey := td.RandValKey() height := td.RandUint32NonZero(td.state.LastBlockHeight()) @@ -58,7 +58,23 @@ func TestParsingHelloMessages(t *testing.T) { td.state.LastBlockHash(), td.state.Genesis().Hash()) msg.Sign([]*bls.ValidatorKey{valKey}) - msg.MyTimeUnixMilli = msg.MyTime().Add(-11 * time.Second).UnixMilli() + msg.MyTimeUnixMilli = msg.MyTime().Add(-10 * time.Second).UnixMilli() + assert.NoError(t, td.receivingNewMessage(td.sync, msg, pid)) + td.checkPeerStatus(t, pid, peerset.StatusCodeBanned) + bdl := td.shouldPublishMessageWithThisType(t, td.network, message.TypeHelloAck) + assert.Equal(t, bdl.Message.(*message.HelloAckMessage).ResponseCode, message.ResponseCodeRejected) + }) + + t.Run("Receiving Hello message from a peer. Difference is less or equal than 20 seconds.", + func(t *testing.T) { + valKey := td.RandValKey() + height := td.RandUint32NonZero(td.state.LastBlockHeight()) + pid := td.RandPeerID() + msg := message.NewHelloMessage(pid, "kitty", height, services.New(services.Network), + td.state.LastBlockHash(), td.state.Genesis().Hash()) + msg.Sign([]*bls.ValidatorKey{valKey}) + + msg.MyTimeUnixMilli = msg.MyTime().Add(20 * time.Second).UnixMilli() assert.NoError(t, td.receivingNewMessage(td.sync, msg, pid)) td.checkPeerStatus(t, pid, peerset.StatusCodeBanned) bdl := td.shouldPublishMessageWithThisType(t, td.network, message.TypeHelloAck) From 830022cf0f3d70e450891bdcc4259cbeaa89b4f6 Mon Sep 17 00:00:00 2001 From: amir babazadeh Date: Fri, 6 Oct 2023 22:09:39 +0330 Subject: [PATCH 4/4] test: remove duplicate tests --- sync/bundle/message/hello_test.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/sync/bundle/message/hello_test.go b/sync/bundle/message/hello_test.go index 2f8fb03f3..f0e149430 100644 --- a/sync/bundle/message/hello_test.go +++ b/sync/bundle/message/hello_test.go @@ -56,16 +56,6 @@ func TestHelloMessage(t *testing.T) { assert.GreaterOrEqual(t, m.MyTimeUnixMilli, myTimeUnixMilli) }) - t.Run("MyTimeUnixMilli of time1 is greater than hello message time", func(t *testing.T) { - m := NewHelloMessage(ts.RandPeerID(), "Alice", 100, 0, ts.RandHash(), ts.RandHash()) - <-time.After(time.Millisecond) - - time1 := time.Now() - myTimeUnixMilli := time1.UnixMilli() - - assert.GreaterOrEqual(t, myTimeUnixMilli, m.MyTimeUnixMilli) - }) - t.Run("Ok", func(t *testing.T) { valKey := ts.RandValKey() m := NewHelloMessage(ts.RandPeerID(), "Alice", 100, 0, ts.RandHash(), ts.RandHash())