amp.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package record
  2. import (
  3. "fmt"
  4. "io"
  5. "github.com/lightningnetwork/lnd/tlv"
  6. )
  7. // AMPOnionType is the type used in the onion to reference the AMP fields:
  8. // root_share, set_id, and child_index.
  9. const AMPOnionType tlv.Type = 14
  10. // AMP is a record that encodes the fields necessary for atomic multi-path
  11. // payments.
  12. type AMP struct {
  13. rootShare [32]byte
  14. setID [32]byte
  15. childIndex uint32
  16. }
  17. // MaxAmpPayLoadSize is an AMP Record which when serialized to a tlv record uses
  18. // the maximum payload size. The `childIndex` is created randomly and is a
  19. // 4 byte `varint` type so we make sure we use an index which will be encoded in
  20. // 4 bytes.
  21. var MaxAmpPayLoadSize = AMP{
  22. rootShare: [32]byte{},
  23. setID: [32]byte{},
  24. childIndex: 0x80000000,
  25. }
  26. // NewAMP generate a new AMP record with the given root_share, set_id, and
  27. // child_index.
  28. func NewAMP(rootShare, setID [32]byte, childIndex uint32) *AMP {
  29. return &AMP{
  30. rootShare: rootShare,
  31. setID: setID,
  32. childIndex: childIndex,
  33. }
  34. }
  35. // RootShare returns the root share contained in the AMP record.
  36. func (a *AMP) RootShare() [32]byte {
  37. return a.rootShare
  38. }
  39. // SetID returns the set id contained in the AMP record.
  40. func (a *AMP) SetID() [32]byte {
  41. return a.setID
  42. }
  43. // ChildIndex returns the child index contained in the AMP record.
  44. func (a *AMP) ChildIndex() uint32 {
  45. return a.childIndex
  46. }
  47. // AMPEncoder writes the AMP record to the provided io.Writer.
  48. func AMPEncoder(w io.Writer, val interface{}, buf *[8]byte) error {
  49. if v, ok := val.(*AMP); ok {
  50. if err := tlv.EBytes32(w, &v.rootShare, buf); err != nil {
  51. return err
  52. }
  53. if err := tlv.EBytes32(w, &v.setID, buf); err != nil {
  54. return err
  55. }
  56. return tlv.ETUint32T(w, v.childIndex, buf)
  57. }
  58. return tlv.NewTypeForEncodingErr(val, "AMP")
  59. }
  60. const (
  61. // minAMPLength is the minimum length of a serialized AMP TLV record,
  62. // which occurs when the truncated encoding of child_index takes 0
  63. // bytes, leaving only the root_share and set_id.
  64. minAMPLength = 64
  65. // maxAMPLength is the maximum length of a serialized AMP TLV record,
  66. // which occurs when the truncated encoding of a child_index takes 2
  67. // bytes.
  68. maxAMPLength = 68
  69. )
  70. // AMPDecoder reads the AMP record from the provided io.Reader.
  71. func AMPDecoder(r io.Reader, val interface{}, buf *[8]byte, l uint64) error {
  72. if v, ok := val.(*AMP); ok && minAMPLength <= l && l <= maxAMPLength {
  73. if err := tlv.DBytes32(r, &v.rootShare, buf, 32); err != nil {
  74. return err
  75. }
  76. if err := tlv.DBytes32(r, &v.setID, buf, 32); err != nil {
  77. return err
  78. }
  79. return tlv.DTUint32(r, &v.childIndex, buf, l-minAMPLength)
  80. }
  81. return tlv.NewTypeForDecodingErr(val, "AMP", l, maxAMPLength)
  82. }
  83. // Record returns a tlv.Record that can be used to encode or decode this record.
  84. func (a *AMP) Record() tlv.Record {
  85. return tlv.MakeDynamicRecord(
  86. AMPOnionType, a, a.PayloadSize, AMPEncoder, AMPDecoder,
  87. )
  88. }
  89. // PayloadSize returns the size this record takes up in encoded form.
  90. func (a *AMP) PayloadSize() uint64 {
  91. return 32 + 32 + tlv.SizeTUint32(a.childIndex)
  92. }
  93. // String returns a human-readable description of the amp payload fields.
  94. func (a *AMP) String() string {
  95. if a == nil {
  96. return "<nil>"
  97. }
  98. return fmt.Sprintf("root_share=%x set_id=%x child_index=%d",
  99. a.rootShare, a.setID, a.childIndex)
  100. }