33
44import { TypedEventEmitter } from '@libp2p/interface/events'
55import { start , stop } from '@libp2p/interface/startable'
6- import { mockConnectionGater , mockRegistrar , mockUpgrader , connectionPair } from '@libp2p/interface-compliance-tests/mocks'
6+ import { mockConnectionGater , mockRegistrar , mockUpgrader , connectionPair , mockStream } from '@libp2p/interface-compliance-tests/mocks'
77import { createEd25519PeerId } from '@libp2p/peer-id-factory'
88import { PeerRecord , RecordEnvelope } from '@libp2p/peer-record'
99import { PersistentPeerStore } from '@libp2p/peer-store'
@@ -15,6 +15,7 @@ import drain from 'it-drain'
1515import * as lp from 'it-length-prefixed'
1616import { pipe } from 'it-pipe'
1717import { pbStream } from 'it-protobuf-stream'
18+ import { pushable } from 'it-pushable'
1819import pDefer from 'p-defer'
1920import sinon from 'sinon'
2021import { stubInterface } from 'sinon-ts'
@@ -31,8 +32,11 @@ import { DefaultIdentifyService } from '../../src/identify/identify.js'
3132import { identifyService , type IdentifyServiceInit , Message } from '../../src/identify/index.js'
3233import { Identify } from '../../src/identify/pb/message.js'
3334import { DefaultTransportManager } from '../../src/transport-manager.js'
35+ import type { Connection } from '@libp2p/interface/connection'
36+ import type { Peer } from '@libp2p/interface/peer-store'
3437import type { IncomingStreamData } from '@libp2p/interface-internal/registrar'
3538import type { TransportManager } from '@libp2p/interface-internal/transport-manager'
39+ import type { Duplex , Source } from 'it-stream-types'
3640
3741const listenMaddrs = [ multiaddr ( '/ip4/127.0.0.1/tcp/15002/ws' ) ]
3842
@@ -504,4 +508,77 @@ describe('identify', () => {
504508 } ] )
505509 expect ( peer . id . publicKey ) . to . equalBytes ( remoteComponents . peerId . publicKey )
506510 } )
511+
512+ it ( 'should not overwrite peer data when fields are omitted' , async ( ) => {
513+ const localIdentify = new DefaultIdentifyService ( localComponents , defaultInit )
514+ await start ( localIdentify )
515+
516+ const peer : Peer = {
517+ id : remoteComponents . peerId ,
518+ addresses : [ {
519+ multiaddr : multiaddr ( '/ip4/127.0.0.1/tcp/4001' ) ,
520+ isCertified : true
521+ } ] ,
522+ protocols : [
523+ '/proto/1'
524+ ] ,
525+ metadata : new Map ( [ [ 'key' , uint8ArrayFromString ( 'value' ) ] ] ) ,
526+ tags : new Map ( [ [ 'key' , { value : 1 } ] ] )
527+ }
528+
529+ await localComponents . peerStore . save ( remoteComponents . peerId , peer )
530+
531+ const duplex : Duplex < any , Source < any > , any > = {
532+ source : pushable ( ) ,
533+ sink : async ( source ) => {
534+ await drain ( source )
535+ }
536+ }
537+
538+ duplex . source . push ( lp . encode . single ( Identify . encode ( {
539+ protocols : [
540+ '/proto/2'
541+ ]
542+ } ) ) )
543+
544+ await localIdentify . _handlePush ( {
545+ stream : mockStream ( duplex ) ,
546+ connection : stubInterface < Connection > ( {
547+ remotePeer : remoteComponents . peerId
548+ } )
549+ } )
550+
551+ const updatedPeerData = await localComponents . peerStore . get ( remoteComponents . peerId )
552+ expect ( updatedPeerData . addresses [ 0 ] . multiaddr . toString ( ) ) . to . equal ( '/ip4/127.0.0.1/tcp/4001' )
553+ expect ( updatedPeerData . protocols ) . to . deep . equal ( [ '/proto/2' ] )
554+ expect ( updatedPeerData . metadata . get ( 'key' ) ) . to . equalBytes ( uint8ArrayFromString ( 'value' ) )
555+ expect ( updatedPeerData . tags . get ( 'key' ) ) . to . deep . equal ( { value : 1 } )
556+ } )
557+
558+ it ( 'should reject incorrect public key' , async ( ) => {
559+ const localIdentify = new DefaultIdentifyService ( localComponents , defaultInit )
560+ await start ( localIdentify )
561+
562+ const duplex : Duplex < any , Source < any > , any > = {
563+ source : pushable ( ) ,
564+ sink : async ( source ) => {
565+ await drain ( source )
566+ }
567+ }
568+
569+ duplex . source . push ( lp . encode . single ( Identify . encode ( {
570+ publicKey : Uint8Array . from ( [ 0 , 1 , 2 , 3 , 4 ] )
571+ } ) ) )
572+
573+ const localPeerStorePatchSpy = sinon . spy ( localComponents . peerStore , 'patch' )
574+
575+ await localIdentify . _handlePush ( {
576+ stream : mockStream ( duplex ) ,
577+ connection : stubInterface < Connection > ( {
578+ remotePeer : remoteComponents . peerId
579+ } )
580+ } )
581+
582+ expect ( localPeerStorePatchSpy . called ) . to . be . false ( 'patch was called when public key was invalid' )
583+ } )
507584} )
0 commit comments