added limitbytereader to utils, less buffer usage on block decoding

This commit is contained in:
DataHoarder 2023-06-03 10:04:14 +02:00
parent e4be941d5e
commit 0cd75a0509
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
7 changed files with 70 additions and 31 deletions

View file

@ -10,6 +10,7 @@ import (
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/randomx"
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/transaction"
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
"git.gammaspectra.live/P2Pool/p2pool-observer/utils"
"io"
)
@ -39,11 +40,6 @@ type Header struct {
Id types.Hash `json:"id"`
}
type readerAndByteReader interface {
io.Reader
io.ByteReader
}
func (b *Block) MarshalBinary() (buf []byte, err error) {
return b.MarshalBinaryFlags(false, false)
}
@ -93,11 +89,11 @@ func (b *Block) AppendBinaryFlags(preAllocatedBuf []byte, pruned, compact bool)
return buf, nil
}
func (b *Block) FromReader(reader readerAndByteReader) (err error) {
func (b *Block) FromReader(reader utils.ReaderAndByteReader) (err error) {
return b.FromReaderFlags(reader, false)
}
func (b *Block) FromCompactReader(reader readerAndByteReader) (err error) {
func (b *Block) FromCompactReader(reader utils.ReaderAndByteReader) (err error) {
return b.FromReaderFlags(reader, true)
}
@ -106,7 +102,7 @@ func (b *Block) UnmarshalBinary(data []byte) error {
return b.FromReader(reader)
}
func (b *Block) FromReaderFlags(reader readerAndByteReader, compact bool) (err error) {
func (b *Block) FromReaderFlags(reader utils.ReaderAndByteReader, compact bool) (err error) {
var (
txCount uint64
transactionHash types.Hash

View file

@ -8,7 +8,7 @@ import (
"git.gammaspectra.live/P2Pool/p2pool-observer/monero"
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto"
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
"io"
"git.gammaspectra.live/P2Pool/p2pool-observer/utils"
"sync"
)
@ -32,17 +32,12 @@ type CoinbaseTransaction struct {
ExtraBaseRCT uint8 `json:"extra_base_rct"`
}
type readerAndByteReader interface {
io.Reader
io.ByteReader
}
func (c *CoinbaseTransaction) UnmarshalBinary(data []byte) error {
reader := bytes.NewReader(data)
return c.FromReader(reader)
}
func (c *CoinbaseTransaction) FromReader(reader readerAndByteReader) (err error) {
func (c *CoinbaseTransaction) FromReader(reader utils.ReaderAndByteReader) (err error) {
var (
txExtraSize uint64
)
@ -121,12 +116,12 @@ func (c *CoinbaseTransaction) FromReader(reader readerAndByteReader) (err error)
return errors.New("tx extra too large")
}
txExtra := make([]byte, txExtraSize)
if _, err = io.ReadFull(reader, txExtra); err != nil {
limitReader := utils.LimitByteReader(reader, int64(txExtraSize))
if err = c.Extra.FromReader(limitReader); err != nil {
return err
}
if err = c.Extra.UnmarshalBinary(txExtra); err != nil {
return err
if limitReader.Left() > 0 {
return errors.New("bytes leftover in extra data")
}
if err = binary.Read(reader, binary.LittleEndian, &c.ExtraBaseRCT); err != nil {
return err

View file

@ -7,6 +7,7 @@ import (
"fmt"
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto"
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
"git.gammaspectra.live/P2Pool/p2pool-observer/utils"
"io"
)
@ -78,7 +79,7 @@ func (t *ExtraTags) SideChainHashingBlob(preAllocatedBuf []byte, zeroTemplateId
return buf, nil
}
func (t *ExtraTags) FromReader(reader readerAndByteReader) (err error) {
func (t *ExtraTags) FromReader(reader utils.ReaderAndByteReader) (err error) {
var tag ExtraTag
for {
if err = tag.FromReader(reader); err != nil {
@ -148,7 +149,7 @@ func (t *ExtraTag) SideChainHashingBlob(preAllocatedBuf []byte, zeroTemplateId b
return buf, nil
}
func (t *ExtraTag) FromReader(reader readerAndByteReader) (err error) {
func (t *ExtraTag) FromReader(reader utils.ReaderAndByteReader) (err error) {
if err = binary.Read(reader, binary.LittleEndian, &t.Tag); err != nil {
return err

View file

@ -5,12 +5,13 @@ import (
"errors"
"fmt"
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto"
"git.gammaspectra.live/P2Pool/p2pool-observer/utils"
"io"
)
type Outputs []Output
func (s *Outputs) FromReader(reader readerAndByteReader) (err error) {
func (s *Outputs) FromReader(reader utils.ReaderAndByteReader) (err error) {
var outputCount uint64
if outputCount, err = binary.ReadUvarint(reader); err != nil {

View file

@ -14,6 +14,7 @@ import (
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/transaction"
p2poolcrypto "git.gammaspectra.live/P2Pool/p2pool-observer/p2pool/crypto"
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
"git.gammaspectra.live/P2Pool/p2pool-observer/utils"
"golang.org/x/exp/slices"
"io"
"sync"
@ -463,7 +464,7 @@ func (b *PoolBlock) AppendBinaryFlags(preAllocatedBuf []byte, pruned, compact bo
}
}
func (b *PoolBlock) FromReader(consensus *Consensus, derivationCache DerivationCacheInterface, reader readerAndByteReader) (err error) {
func (b *PoolBlock) FromReader(consensus *Consensus, derivationCache DerivationCacheInterface, reader utils.ReaderAndByteReader) (err error) {
if err = b.Main.FromReader(reader); err != nil {
return err
}
@ -489,7 +490,7 @@ func (b *PoolBlock) FromReader(consensus *Consensus, derivationCache DerivationC
}
// FromCompactReader used in Protocol 1.1 and above
func (b *PoolBlock) FromCompactReader(consensus *Consensus, derivationCache DerivationCacheInterface, reader readerAndByteReader) (err error) {
func (b *PoolBlock) FromCompactReader(consensus *Consensus, derivationCache DerivationCacheInterface, reader utils.ReaderAndByteReader) (err error) {
if err = b.Main.FromCompactReader(reader); err != nil {
return err
}
@ -675,7 +676,7 @@ type poolBlockCache struct {
powHash types.Hash
}
func (c *poolBlockCache) FromReader(reader readerAndByteReader) (err error) {
func (c *poolBlockCache) FromReader(reader utils.ReaderAndByteReader) (err error) {
buf := make([]byte, types.HashSize*3+types.DifficultySize+FullIdSize)
if _, err = reader.Read(buf); err != nil {
return err

View file

@ -7,6 +7,7 @@ import (
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto"
p2pooltypes "git.gammaspectra.live/P2Pool/p2pool-observer/p2pool/types"
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
"git.gammaspectra.live/P2Pool/p2pool-observer/utils"
"io"
)
@ -31,11 +32,6 @@ type SideData struct {
}
}
type readerAndByteReader interface {
io.Reader
io.ByteReader
}
func (b *SideData) BufferLength() int {
return crypto.PublicKeySize + crypto.PublicKeySize + types.HashSize + types.HashSize + binary.MaxVarintLen64 + len(b.Uncles)*types.HashSize + binary.MaxVarintLen64 + binary.MaxVarintLen64 + binary.MaxVarintLen64 + binary.MaxVarintLen64 + binary.MaxVarintLen64 + 4*4
}
@ -73,7 +69,7 @@ func (b *SideData) AppendBinary(preAllocatedBuf []byte, version ShareVersion) (b
return buf, nil
}
func (b *SideData) FromReader(reader readerAndByteReader, version ShareVersion) (err error) {
func (b *SideData) FromReader(reader utils.ReaderAndByteReader, version ShareVersion) (err error) {
var (
uncleCount uint64
uncleHash types.Hash

49
utils/limitreader.go Normal file
View file

@ -0,0 +1,49 @@
package utils
import "io"
type ReaderAndByteReader interface {
io.Reader
io.ByteReader
}
// LimitByteReader returns a Reader that reads from r
// but stops with EOF after n bytes.
// The underlying implementation is a *LimitedReader.
func LimitByteReader(r ReaderAndByteReader, n int64) *LimitedByteReader {
return &LimitedByteReader{r, n}
}
// A LimitedByteReader reads from R but limits the amount of
// data returned to just N bytes. Each call to Read
// updates N to reflect the new amount remaining.
// Read returns EOF when N <= 0 or when the underlying R returns EOF.
type LimitedByteReader struct {
R ReaderAndByteReader // underlying reader
N int64 // max bytes remaining
}
func (l *LimitedByteReader) Read(p []byte) (n int, err error) {
if l.N <= 0 {
return 0, io.EOF
}
if int64(len(p)) > l.N {
p = p[0:l.N]
}
n, err = l.R.Read(p)
l.N -= int64(n)
return
}
func (l *LimitedByteReader) ReadByte() (v uint8, err error) {
if l.N <= 0 {
return 0, io.EOF
}
v, err = l.R.ReadByte()
l.N--
return
}
func (l *LimitedByteReader) Left() int64 {
return l.N
}