github.com/ava-labs/avalanchego@v1.11.11/message/outbound_msg_builder.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package message 5 6 import ( 7 "net/netip" 8 "time" 9 10 "github.com/ava-labs/avalanchego/ids" 11 "github.com/ava-labs/avalanchego/proto/pb/p2p" 12 "github.com/ava-labs/avalanchego/utils/compression" 13 "github.com/ava-labs/avalanchego/utils/ips" 14 ) 15 16 var _ OutboundMsgBuilder = (*outMsgBuilder)(nil) 17 18 // OutboundMsgBuilder builds outbound messages. Outbound messages are returned 19 // with a reference count of 1. Once the reference count hits 0, the message 20 // bytes should no longer be accessed. 21 type OutboundMsgBuilder interface { 22 Handshake( 23 networkID uint32, 24 myTime uint64, 25 ip netip.AddrPort, 26 client string, 27 major uint32, 28 minor uint32, 29 patch uint32, 30 ipSigningTime uint64, 31 ipNodeIDSig []byte, 32 ipBLSSig []byte, 33 trackedSubnets []ids.ID, 34 supportedACPs []uint32, 35 objectedACPs []uint32, 36 knownPeersFilter []byte, 37 knownPeersSalt []byte, 38 requestAllSubnetIPs bool, 39 ) (OutboundMessage, error) 40 41 GetPeerList( 42 knownPeersFilter []byte, 43 knownPeersSalt []byte, 44 requestAllSubnetIPs bool, 45 ) (OutboundMessage, error) 46 47 PeerList( 48 peers []*ips.ClaimedIPPort, 49 bypassThrottling bool, 50 ) (OutboundMessage, error) 51 52 Ping( 53 primaryUptime uint32, 54 subnetUptimes []*p2p.SubnetUptime, 55 ) (OutboundMessage, error) 56 57 Pong() (OutboundMessage, error) 58 59 GetStateSummaryFrontier( 60 chainID ids.ID, 61 requestID uint32, 62 deadline time.Duration, 63 ) (OutboundMessage, error) 64 65 StateSummaryFrontier( 66 chainID ids.ID, 67 requestID uint32, 68 summary []byte, 69 ) (OutboundMessage, error) 70 71 GetAcceptedStateSummary( 72 chainID ids.ID, 73 requestID uint32, 74 deadline time.Duration, 75 heights []uint64, 76 ) (OutboundMessage, error) 77 78 AcceptedStateSummary( 79 chainID ids.ID, 80 requestID uint32, 81 summaryIDs []ids.ID, 82 ) (OutboundMessage, error) 83 84 GetAcceptedFrontier( 85 chainID ids.ID, 86 requestID uint32, 87 deadline time.Duration, 88 ) (OutboundMessage, error) 89 90 AcceptedFrontier( 91 chainID ids.ID, 92 requestID uint32, 93 containerID ids.ID, 94 ) (OutboundMessage, error) 95 96 GetAccepted( 97 chainID ids.ID, 98 requestID uint32, 99 deadline time.Duration, 100 containerIDs []ids.ID, 101 ) (OutboundMessage, error) 102 103 Accepted( 104 chainID ids.ID, 105 requestID uint32, 106 containerIDs []ids.ID, 107 ) (OutboundMessage, error) 108 109 GetAncestors( 110 chainID ids.ID, 111 requestID uint32, 112 deadline time.Duration, 113 containerID ids.ID, 114 engineType p2p.EngineType, 115 ) (OutboundMessage, error) 116 117 Ancestors( 118 chainID ids.ID, 119 requestID uint32, 120 containers [][]byte, 121 ) (OutboundMessage, error) 122 123 Get( 124 chainID ids.ID, 125 requestID uint32, 126 deadline time.Duration, 127 containerID ids.ID, 128 ) (OutboundMessage, error) 129 130 Put( 131 chainID ids.ID, 132 requestID uint32, 133 container []byte, 134 ) (OutboundMessage, error) 135 136 PushQuery( 137 chainID ids.ID, 138 requestID uint32, 139 deadline time.Duration, 140 container []byte, 141 requestedHeight uint64, 142 ) (OutboundMessage, error) 143 144 PullQuery( 145 chainID ids.ID, 146 requestID uint32, 147 deadline time.Duration, 148 containerID ids.ID, 149 requestedHeight uint64, 150 ) (OutboundMessage, error) 151 152 Chits( 153 chainID ids.ID, 154 requestID uint32, 155 preferredID ids.ID, 156 preferredIDAtHeight ids.ID, 157 acceptedID ids.ID, 158 ) (OutboundMessage, error) 159 160 AppRequest( 161 chainID ids.ID, 162 requestID uint32, 163 deadline time.Duration, 164 msg []byte, 165 ) (OutboundMessage, error) 166 167 AppResponse( 168 chainID ids.ID, 169 requestID uint32, 170 msg []byte, 171 ) (OutboundMessage, error) 172 173 AppError( 174 chainID ids.ID, 175 requestID uint32, 176 errorCode int32, 177 errorMessage string, 178 ) (OutboundMessage, error) 179 180 AppGossip( 181 chainID ids.ID, 182 msg []byte, 183 ) (OutboundMessage, error) 184 } 185 186 type outMsgBuilder struct { 187 compressionType compression.Type 188 189 builder *msgBuilder 190 } 191 192 // Use "message.NewCreator" to import this function 193 // since we do not expose "msgBuilder" yet 194 func newOutboundBuilder(compressionType compression.Type, builder *msgBuilder) OutboundMsgBuilder { 195 return &outMsgBuilder{ 196 compressionType: compressionType, 197 builder: builder, 198 } 199 } 200 201 func (b *outMsgBuilder) Ping( 202 primaryUptime uint32, 203 subnetUptimes []*p2p.SubnetUptime, 204 ) (OutboundMessage, error) { 205 return b.builder.createOutbound( 206 &p2p.Message{ 207 Message: &p2p.Message_Ping{ 208 Ping: &p2p.Ping{ 209 Uptime: primaryUptime, 210 SubnetUptimes: subnetUptimes, 211 }, 212 }, 213 }, 214 compression.TypeNone, 215 false, 216 ) 217 } 218 219 func (b *outMsgBuilder) Pong() (OutboundMessage, error) { 220 return b.builder.createOutbound( 221 &p2p.Message{ 222 Message: &p2p.Message_Pong{ 223 Pong: &p2p.Pong{}, 224 }, 225 }, 226 compression.TypeNone, 227 false, 228 ) 229 } 230 231 func (b *outMsgBuilder) Handshake( 232 networkID uint32, 233 myTime uint64, 234 ip netip.AddrPort, 235 client string, 236 major uint32, 237 minor uint32, 238 patch uint32, 239 ipSigningTime uint64, 240 ipNodeIDSig []byte, 241 ipBLSSig []byte, 242 trackedSubnets []ids.ID, 243 supportedACPs []uint32, 244 objectedACPs []uint32, 245 knownPeersFilter []byte, 246 knownPeersSalt []byte, 247 requestAllSubnetIPs bool, 248 ) (OutboundMessage, error) { 249 subnetIDBytes := make([][]byte, len(trackedSubnets)) 250 encodeIDs(trackedSubnets, subnetIDBytes) 251 // TODO: Use .AsSlice() after v1.12.x activates. 252 addr := ip.Addr().As16() 253 return b.builder.createOutbound( 254 &p2p.Message{ 255 Message: &p2p.Message_Handshake{ 256 Handshake: &p2p.Handshake{ 257 NetworkId: networkID, 258 MyTime: myTime, 259 IpAddr: addr[:], 260 IpPort: uint32(ip.Port()), 261 IpSigningTime: ipSigningTime, 262 IpNodeIdSig: ipNodeIDSig, 263 TrackedSubnets: subnetIDBytes, 264 Client: &p2p.Client{ 265 Name: client, 266 Major: major, 267 Minor: minor, 268 Patch: patch, 269 }, 270 SupportedAcps: supportedACPs, 271 ObjectedAcps: objectedACPs, 272 KnownPeers: &p2p.BloomFilter{ 273 Filter: knownPeersFilter, 274 Salt: knownPeersSalt, 275 }, 276 IpBlsSig: ipBLSSig, 277 AllSubnets: requestAllSubnetIPs, 278 }, 279 }, 280 }, 281 compression.TypeNone, 282 true, 283 ) 284 } 285 286 func (b *outMsgBuilder) GetPeerList( 287 knownPeersFilter []byte, 288 knownPeersSalt []byte, 289 requestAllSubnetIPs bool, 290 ) (OutboundMessage, error) { 291 return b.builder.createOutbound( 292 &p2p.Message{ 293 Message: &p2p.Message_GetPeerList{ 294 GetPeerList: &p2p.GetPeerList{ 295 KnownPeers: &p2p.BloomFilter{ 296 Filter: knownPeersFilter, 297 Salt: knownPeersSalt, 298 }, 299 AllSubnets: requestAllSubnetIPs, 300 }, 301 }, 302 }, 303 b.compressionType, 304 false, 305 ) 306 } 307 308 func (b *outMsgBuilder) PeerList(peers []*ips.ClaimedIPPort, bypassThrottling bool) (OutboundMessage, error) { 309 claimIPPorts := make([]*p2p.ClaimedIpPort, len(peers)) 310 for i, p := range peers { 311 // TODO: Use .AsSlice() after v1.12.x activates. 312 ip := p.AddrPort.Addr().As16() 313 claimIPPorts[i] = &p2p.ClaimedIpPort{ 314 X509Certificate: p.Cert.Raw, 315 IpAddr: ip[:], 316 IpPort: uint32(p.AddrPort.Port()), 317 Timestamp: p.Timestamp, 318 Signature: p.Signature, 319 TxId: ids.Empty[:], 320 } 321 } 322 return b.builder.createOutbound( 323 &p2p.Message{ 324 Message: &p2p.Message_PeerList_{ 325 PeerList_: &p2p.PeerList{ 326 ClaimedIpPorts: claimIPPorts, 327 }, 328 }, 329 }, 330 b.compressionType, 331 bypassThrottling, 332 ) 333 } 334 335 func (b *outMsgBuilder) GetStateSummaryFrontier( 336 chainID ids.ID, 337 requestID uint32, 338 deadline time.Duration, 339 ) (OutboundMessage, error) { 340 return b.builder.createOutbound( 341 &p2p.Message{ 342 Message: &p2p.Message_GetStateSummaryFrontier{ 343 GetStateSummaryFrontier: &p2p.GetStateSummaryFrontier{ 344 ChainId: chainID[:], 345 RequestId: requestID, 346 Deadline: uint64(deadline), 347 }, 348 }, 349 }, 350 compression.TypeNone, 351 false, 352 ) 353 } 354 355 func (b *outMsgBuilder) StateSummaryFrontier( 356 chainID ids.ID, 357 requestID uint32, 358 summary []byte, 359 ) (OutboundMessage, error) { 360 return b.builder.createOutbound( 361 &p2p.Message{ 362 Message: &p2p.Message_StateSummaryFrontier_{ 363 StateSummaryFrontier_: &p2p.StateSummaryFrontier{ 364 ChainId: chainID[:], 365 RequestId: requestID, 366 Summary: summary, 367 }, 368 }, 369 }, 370 b.compressionType, 371 false, 372 ) 373 } 374 375 func (b *outMsgBuilder) GetAcceptedStateSummary( 376 chainID ids.ID, 377 requestID uint32, 378 deadline time.Duration, 379 heights []uint64, 380 ) (OutboundMessage, error) { 381 return b.builder.createOutbound( 382 &p2p.Message{ 383 Message: &p2p.Message_GetAcceptedStateSummary{ 384 GetAcceptedStateSummary: &p2p.GetAcceptedStateSummary{ 385 ChainId: chainID[:], 386 RequestId: requestID, 387 Deadline: uint64(deadline), 388 Heights: heights, 389 }, 390 }, 391 }, 392 b.compressionType, 393 false, 394 ) 395 } 396 397 func (b *outMsgBuilder) AcceptedStateSummary( 398 chainID ids.ID, 399 requestID uint32, 400 summaryIDs []ids.ID, 401 ) (OutboundMessage, error) { 402 summaryIDBytes := make([][]byte, len(summaryIDs)) 403 encodeIDs(summaryIDs, summaryIDBytes) 404 return b.builder.createOutbound( 405 &p2p.Message{ 406 Message: &p2p.Message_AcceptedStateSummary_{ 407 AcceptedStateSummary_: &p2p.AcceptedStateSummary{ 408 ChainId: chainID[:], 409 RequestId: requestID, 410 SummaryIds: summaryIDBytes, 411 }, 412 }, 413 }, 414 b.compressionType, 415 false, 416 ) 417 } 418 419 func (b *outMsgBuilder) GetAcceptedFrontier( 420 chainID ids.ID, 421 requestID uint32, 422 deadline time.Duration, 423 ) (OutboundMessage, error) { 424 return b.builder.createOutbound( 425 &p2p.Message{ 426 Message: &p2p.Message_GetAcceptedFrontier{ 427 GetAcceptedFrontier: &p2p.GetAcceptedFrontier{ 428 ChainId: chainID[:], 429 RequestId: requestID, 430 Deadline: uint64(deadline), 431 }, 432 }, 433 }, 434 compression.TypeNone, 435 false, 436 ) 437 } 438 439 func (b *outMsgBuilder) AcceptedFrontier( 440 chainID ids.ID, 441 requestID uint32, 442 containerID ids.ID, 443 ) (OutboundMessage, error) { 444 return b.builder.createOutbound( 445 &p2p.Message{ 446 Message: &p2p.Message_AcceptedFrontier_{ 447 AcceptedFrontier_: &p2p.AcceptedFrontier{ 448 ChainId: chainID[:], 449 RequestId: requestID, 450 ContainerId: containerID[:], 451 }, 452 }, 453 }, 454 compression.TypeNone, 455 false, 456 ) 457 } 458 459 func (b *outMsgBuilder) GetAccepted( 460 chainID ids.ID, 461 requestID uint32, 462 deadline time.Duration, 463 containerIDs []ids.ID, 464 ) (OutboundMessage, error) { 465 containerIDBytes := make([][]byte, len(containerIDs)) 466 encodeIDs(containerIDs, containerIDBytes) 467 return b.builder.createOutbound( 468 &p2p.Message{ 469 Message: &p2p.Message_GetAccepted{ 470 GetAccepted: &p2p.GetAccepted{ 471 ChainId: chainID[:], 472 RequestId: requestID, 473 Deadline: uint64(deadline), 474 ContainerIds: containerIDBytes, 475 }, 476 }, 477 }, 478 compression.TypeNone, 479 false, 480 ) 481 } 482 483 func (b *outMsgBuilder) Accepted( 484 chainID ids.ID, 485 requestID uint32, 486 containerIDs []ids.ID, 487 ) (OutboundMessage, error) { 488 containerIDBytes := make([][]byte, len(containerIDs)) 489 encodeIDs(containerIDs, containerIDBytes) 490 return b.builder.createOutbound( 491 &p2p.Message{ 492 Message: &p2p.Message_Accepted_{ 493 Accepted_: &p2p.Accepted{ 494 ChainId: chainID[:], 495 RequestId: requestID, 496 ContainerIds: containerIDBytes, 497 }, 498 }, 499 }, 500 compression.TypeNone, 501 false, 502 ) 503 } 504 505 func (b *outMsgBuilder) GetAncestors( 506 chainID ids.ID, 507 requestID uint32, 508 deadline time.Duration, 509 containerID ids.ID, 510 engineType p2p.EngineType, 511 ) (OutboundMessage, error) { 512 return b.builder.createOutbound( 513 &p2p.Message{ 514 Message: &p2p.Message_GetAncestors{ 515 GetAncestors: &p2p.GetAncestors{ 516 ChainId: chainID[:], 517 RequestId: requestID, 518 Deadline: uint64(deadline), 519 ContainerId: containerID[:], 520 EngineType: engineType, 521 }, 522 }, 523 }, 524 compression.TypeNone, 525 false, 526 ) 527 } 528 529 func (b *outMsgBuilder) Ancestors( 530 chainID ids.ID, 531 requestID uint32, 532 containers [][]byte, 533 ) (OutboundMessage, error) { 534 return b.builder.createOutbound( 535 &p2p.Message{ 536 Message: &p2p.Message_Ancestors_{ 537 Ancestors_: &p2p.Ancestors{ 538 ChainId: chainID[:], 539 RequestId: requestID, 540 Containers: containers, 541 }, 542 }, 543 }, 544 b.compressionType, 545 false, 546 ) 547 } 548 549 func (b *outMsgBuilder) Get( 550 chainID ids.ID, 551 requestID uint32, 552 deadline time.Duration, 553 containerID ids.ID, 554 ) (OutboundMessage, error) { 555 return b.builder.createOutbound( 556 &p2p.Message{ 557 Message: &p2p.Message_Get{ 558 Get: &p2p.Get{ 559 ChainId: chainID[:], 560 RequestId: requestID, 561 Deadline: uint64(deadline), 562 ContainerId: containerID[:], 563 }, 564 }, 565 }, 566 compression.TypeNone, 567 false, 568 ) 569 } 570 571 func (b *outMsgBuilder) Put( 572 chainID ids.ID, 573 requestID uint32, 574 container []byte, 575 ) (OutboundMessage, error) { 576 return b.builder.createOutbound( 577 &p2p.Message{ 578 Message: &p2p.Message_Put{ 579 Put: &p2p.Put{ 580 ChainId: chainID[:], 581 RequestId: requestID, 582 Container: container, 583 }, 584 }, 585 }, 586 b.compressionType, 587 false, 588 ) 589 } 590 591 func (b *outMsgBuilder) PushQuery( 592 chainID ids.ID, 593 requestID uint32, 594 deadline time.Duration, 595 container []byte, 596 requestedHeight uint64, 597 ) (OutboundMessage, error) { 598 return b.builder.createOutbound( 599 &p2p.Message{ 600 Message: &p2p.Message_PushQuery{ 601 PushQuery: &p2p.PushQuery{ 602 ChainId: chainID[:], 603 RequestId: requestID, 604 Deadline: uint64(deadline), 605 Container: container, 606 RequestedHeight: requestedHeight, 607 }, 608 }, 609 }, 610 b.compressionType, 611 false, 612 ) 613 } 614 615 func (b *outMsgBuilder) PullQuery( 616 chainID ids.ID, 617 requestID uint32, 618 deadline time.Duration, 619 containerID ids.ID, 620 requestedHeight uint64, 621 ) (OutboundMessage, error) { 622 return b.builder.createOutbound( 623 &p2p.Message{ 624 Message: &p2p.Message_PullQuery{ 625 PullQuery: &p2p.PullQuery{ 626 ChainId: chainID[:], 627 RequestId: requestID, 628 Deadline: uint64(deadline), 629 ContainerId: containerID[:], 630 RequestedHeight: requestedHeight, 631 }, 632 }, 633 }, 634 compression.TypeNone, 635 false, 636 ) 637 } 638 639 func (b *outMsgBuilder) Chits( 640 chainID ids.ID, 641 requestID uint32, 642 preferredID ids.ID, 643 preferredIDAtHeight ids.ID, 644 acceptedID ids.ID, 645 ) (OutboundMessage, error) { 646 return b.builder.createOutbound( 647 &p2p.Message{ 648 Message: &p2p.Message_Chits{ 649 Chits: &p2p.Chits{ 650 ChainId: chainID[:], 651 RequestId: requestID, 652 PreferredId: preferredID[:], 653 PreferredIdAtHeight: preferredIDAtHeight[:], 654 AcceptedId: acceptedID[:], 655 }, 656 }, 657 }, 658 compression.TypeNone, 659 false, 660 ) 661 } 662 663 func (b *outMsgBuilder) AppRequest( 664 chainID ids.ID, 665 requestID uint32, 666 deadline time.Duration, 667 msg []byte, 668 ) (OutboundMessage, error) { 669 return b.builder.createOutbound( 670 &p2p.Message{ 671 Message: &p2p.Message_AppRequest{ 672 AppRequest: &p2p.AppRequest{ 673 ChainId: chainID[:], 674 RequestId: requestID, 675 Deadline: uint64(deadline), 676 AppBytes: msg, 677 }, 678 }, 679 }, 680 b.compressionType, 681 false, 682 ) 683 } 684 685 func (b *outMsgBuilder) AppResponse(chainID ids.ID, requestID uint32, msg []byte) (OutboundMessage, error) { 686 return b.builder.createOutbound( 687 &p2p.Message{ 688 Message: &p2p.Message_AppResponse{ 689 AppResponse: &p2p.AppResponse{ 690 ChainId: chainID[:], 691 RequestId: requestID, 692 AppBytes: msg, 693 }, 694 }, 695 }, 696 b.compressionType, 697 false, 698 ) 699 } 700 701 func (b *outMsgBuilder) AppError(chainID ids.ID, requestID uint32, errorCode int32, errorMessage string) (OutboundMessage, error) { 702 return b.builder.createOutbound( 703 &p2p.Message{ 704 Message: &p2p.Message_AppError{ 705 AppError: &p2p.AppError{ 706 ChainId: chainID[:], 707 RequestId: requestID, 708 ErrorCode: errorCode, 709 ErrorMessage: errorMessage, 710 }, 711 }, 712 }, 713 b.compressionType, 714 false, 715 ) 716 } 717 718 func (b *outMsgBuilder) AppGossip(chainID ids.ID, msg []byte) (OutboundMessage, error) { 719 return b.builder.createOutbound( 720 &p2p.Message{ 721 Message: &p2p.Message_AppGossip{ 722 AppGossip: &p2p.AppGossip{ 723 ChainId: chainID[:], 724 AppBytes: msg, 725 }, 726 }, 727 }, 728 b.compressionType, 729 false, 730 ) 731 }