github.com/mavryk-network/mvgo@v1.19.9/codec/utils.go (about)

     1  // Copyright (c) 2020-2022 Blockwatch Data Inc.
     2  // Author: alex@blockwatch.cc
     3  
     4  package codec
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/binary"
     9  	"fmt"
    10  	"io"
    11  	"math"
    12  
    13  	"github.com/mavryk-network/mvgo/mavryk"
    14  	"github.com/mavryk-network/mvgo/micheline"
    15  )
    16  
    17  // TODO: fetch dynamic from /chains/main/mempool/filter
    18  const (
    19  	minFeeFixedNanoMav int64 = 100_000
    20  	minFeeByteNanoMav  int64 = 1_000
    21  	minFeeGasNanoMav   int64 = 100
    22  )
    23  
    24  // CalculateMinFee returns the minimum fee at/above which bakers will accept
    25  // this operation under default config settings. Lower fee operations may not
    26  // pass the fee filter and may time out in the mempool.
    27  func CalculateMinFee(o Operation, gas int64, withHeader bool, p *mavryk.Params) int64 {
    28  	buf := bytes.NewBuffer(nil)
    29  	_ = o.EncodeBuffer(buf, p)
    30  	sz := int64(buf.Len())
    31  	if withHeader {
    32  		sz += 32 + 64 // branch + signature
    33  	}
    34  	fee := minFeeFixedNanoMav + sz*minFeeByteNanoMav + gas*minFeeGasNanoMav
    35  	return int64(math.Ceil(float64(fee) / 1000)) // nano -> micro, round up
    36  }
    37  
    38  // ensureTagAndSize reads the binary operation's tag and matches it against the expected
    39  // type tag and minimum size for the operation under the current protocol. It returns
    40  // an error when tag does not match or when the buffer is too short for reading the
    41  // mandatory operation contents.
    42  func ensureTagAndSize(buf *bytes.Buffer, typ mavryk.OpType, ver int) error {
    43  	if buf == nil {
    44  		return io.ErrShortBuffer
    45  	}
    46  
    47  	tag, err := buf.ReadByte()
    48  	if err != nil {
    49  		// unread so the caller is able to repair
    50  		buf.UnreadByte()
    51  		return err
    52  	}
    53  
    54  	if tag != typ.TagVersion(ver) {
    55  		// unread so the caller is able to repair
    56  		buf.UnreadByte()
    57  		return fmt.Errorf("invalid tag %d for op type %s", tag, typ)
    58  	}
    59  
    60  	// don't fail size checks for undefined ops
    61  	sz := typ.MinSizeVersion(ver)
    62  	if buf.Len() < sz-1 {
    63  		fmt.Printf("short buffer for tag %d for op type %s: exp=%d got=%d\n", tag, typ,
    64  			sz-1, buf.Len())
    65  		buf.UnreadByte()
    66  		return io.ErrShortBuffer
    67  	}
    68  
    69  	return nil
    70  }
    71  
    72  func readInt64(buf []byte) (int64, error) {
    73  	if len(buf) != 8 {
    74  		return 0, io.ErrShortBuffer
    75  	}
    76  	return int64(enc.Uint64(buf)), nil
    77  }
    78  
    79  func readInt32(buf []byte) (int32, error) {
    80  	if len(buf) != 4 {
    81  		return 0, io.ErrShortBuffer
    82  	}
    83  	return int32(enc.Uint32(buf)), nil
    84  }
    85  
    86  func readInt16(buf []byte) (int16, error) {
    87  	if len(buf) != 2 {
    88  		return 0, io.ErrShortBuffer
    89  	}
    90  	return int16(enc.Uint16(buf)), nil
    91  }
    92  
    93  func readUint32(buf []byte) (uint32, error) {
    94  	if len(buf) != 4 {
    95  		return 0, io.ErrShortBuffer
    96  	}
    97  	return enc.Uint32(buf), nil
    98  }
    99  
   100  func readBool(buf []byte) (bool, error) {
   101  	if len(buf) != 1 {
   102  		return false, io.ErrShortBuffer
   103  	}
   104  	return buf[0] == 255, nil
   105  }
   106  
   107  func readByte(buf []byte) (byte, error) {
   108  	if len(buf) != 1 {
   109  		return 0, io.ErrShortBuffer
   110  	}
   111  	return buf[0], nil
   112  }
   113  
   114  func max64(x, y int64) int64 {
   115  	if x > y {
   116  		return x
   117  	}
   118  	return y
   119  }
   120  
   121  func writeBytesWithLen(buf *bytes.Buffer, b mavryk.HexBytes) (err error) {
   122  	err = binary.Write(buf, enc, uint32(len(b)))
   123  	if err != nil {
   124  		return
   125  	}
   126  	_, err = buf.Write(b)
   127  	return err
   128  }
   129  
   130  func readBytesWithLen(buf *bytes.Buffer) (b mavryk.HexBytes, err error) {
   131  	var l uint32
   132  	l, err = readUint32(buf.Next(4))
   133  	if err != nil {
   134  		return
   135  	}
   136  	err = b.ReadBytes(buf, int(l))
   137  	return
   138  }
   139  
   140  func readPrimWithLen(buf *bytes.Buffer) (p micheline.Prim, err error) {
   141  	var l uint32
   142  	l, err = readUint32(buf.Next(4))
   143  	if err != nil {
   144  		return
   145  	}
   146  	err = p.UnmarshalBinary(buf.Next(int(l)))
   147  	return
   148  }
   149  
   150  func writePrimWithLen(buf *bytes.Buffer, p micheline.Prim) error {
   151  	v, err := p.MarshalBinary()
   152  	if err != nil {
   153  		return err
   154  	}
   155  	if err := binary.Write(buf, enc, uint32(len(v))); err != nil {
   156  		return err
   157  	}
   158  	_, err = buf.Write(v)
   159  	return err
   160  }
   161  
   162  func readStringWithLen(buf *bytes.Buffer) (s string, err error) {
   163  	var l uint32
   164  	l, err = readUint32(buf.Next(4))
   165  	if err != nil {
   166  		return
   167  	}
   168  	if b := buf.Next(int(l)); len(b) != int(l) {
   169  		err = io.ErrShortBuffer
   170  		return
   171  	} else {
   172  		s = string(b)
   173  	}
   174  	return
   175  }
   176  
   177  func writeStringWithLen(buf *bytes.Buffer, s string) error {
   178  	if err := binary.Write(buf, enc, uint32(len(s))); err != nil {
   179  		return err
   180  	}
   181  	_, err := buf.WriteString(s)
   182  	return err
   183  }