git.gammaspectra.live/P2Pool/consensus@v0.0.0-20240403173234-a039820b20c9/monero/transaction/output.go (about) 1 package transaction 2 3 import ( 4 "encoding/binary" 5 "errors" 6 "fmt" 7 "git.gammaspectra.live/P2Pool/consensus/monero/crypto" 8 "git.gammaspectra.live/P2Pool/consensus/utils" 9 "io" 10 ) 11 12 type Outputs []Output 13 14 func (s *Outputs) FromReader(reader utils.ReaderAndByteReader) (err error) { 15 var outputCount uint64 16 17 if outputCount, err = binary.ReadUvarint(reader); err != nil { 18 return err 19 } 20 21 if outputCount > 0 { 22 if outputCount < 8192 { 23 *s = make(Outputs, 0, outputCount) 24 } 25 26 var o Output 27 for index := 0; index < int(outputCount); index++ { 28 o.Index = uint64(index) 29 30 if o.Reward, err = binary.ReadUvarint(reader); err != nil { 31 return err 32 } 33 34 if o.Type, err = reader.ReadByte(); err != nil { 35 return err 36 } 37 38 switch o.Type { 39 case TxOutToTaggedKey, TxOutToKey: 40 if _, err = io.ReadFull(reader, o.EphemeralPublicKey[:]); err != nil { 41 return err 42 } 43 44 if o.Type == TxOutToTaggedKey { 45 if o.ViewTag, err = reader.ReadByte(); err != nil { 46 return err 47 } 48 } else { 49 o.ViewTag = 0 50 } 51 default: 52 return fmt.Errorf("unknown %d TXOUT key", o.Type) 53 } 54 55 *s = append(*s, o) 56 } 57 } 58 return nil 59 } 60 61 func (s *Outputs) BufferLength() (n int) { 62 n = utils.UVarInt64Size(len(*s)) 63 for _, o := range *s { 64 n += utils.UVarInt64Size(o.Reward) + 65 1 + 66 crypto.PublicKeySize 67 if o.Type == TxOutToTaggedKey { 68 n++ 69 } 70 } 71 return n 72 } 73 74 func (s *Outputs) MarshalBinary() (data []byte, err error) { 75 return s.AppendBinary(make([]byte, 0, s.BufferLength())) 76 } 77 78 func (s *Outputs) AppendBinary(preAllocatedBuf []byte) (data []byte, err error) { 79 data = preAllocatedBuf 80 81 data = binary.AppendUvarint(data, uint64(len(*s))) 82 83 for _, o := range *s { 84 data = binary.AppendUvarint(data, o.Reward) 85 data = append(data, o.Type) 86 87 switch o.Type { 88 case TxOutToTaggedKey, TxOutToKey: 89 data = append(data, o.EphemeralPublicKey[:]...) 90 91 if o.Type == TxOutToTaggedKey { 92 data = append(data, o.ViewTag) 93 } 94 default: 95 return nil, errors.New("unknown output type") 96 } 97 } 98 return data, nil 99 } 100 101 type Output struct { 102 Index uint64 `json:"index"` 103 Reward uint64 `json:"reward"` 104 // Type would be here 105 EphemeralPublicKey crypto.PublicKeyBytes `json:"ephemeral_public_key"` 106 // Type re-arranged here to improve memory layout space 107 Type uint8 `json:"type"` 108 ViewTag uint8 `json:"view_tag"` 109 }