github.com/jimmyx0x/go-ethereum@v1.10.28/les/vflux/requests.go (about)

     1  // Copyright 2021 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package vflux
    18  
    19  import (
    20  	"errors"
    21  	"math"
    22  	"math/big"
    23  
    24  	"github.com/ethereum/go-ethereum/rlp"
    25  )
    26  
    27  var ErrNoReply = errors.New("no reply for given request")
    28  
    29  const (
    30  	MaxRequestLength    = 16 // max number of individual requests in a batch
    31  	CapacityQueryName   = "cq"
    32  	CapacityQueryMaxLen = 16
    33  )
    34  
    35  type (
    36  	// Request describes a single vflux request inside a batch. Service and request
    37  	// type are identified by strings, parameters are RLP encoded.
    38  	Request struct {
    39  		Service, Name string
    40  		Params        []byte
    41  	}
    42  	// Requests are a batch of vflux requests
    43  	Requests []Request
    44  
    45  	// Replies are the replies to a batch of requests
    46  	Replies [][]byte
    47  
    48  	// CapacityQueryReq is the encoding format of the capacity query
    49  	CapacityQueryReq struct {
    50  		Bias      uint64 // seconds
    51  		AddTokens []IntOrInf
    52  	}
    53  	// CapacityQueryReply is the encoding format of the response to the capacity query
    54  	CapacityQueryReply []uint64
    55  )
    56  
    57  // Add encodes and adds a new request to the batch
    58  func (r *Requests) Add(service, name string, val interface{}) (int, error) {
    59  	enc, err := rlp.EncodeToBytes(val)
    60  	if err != nil {
    61  		return -1, err
    62  	}
    63  	*r = append(*r, Request{
    64  		Service: service,
    65  		Name:    name,
    66  		Params:  enc,
    67  	})
    68  	return len(*r) - 1, nil
    69  }
    70  
    71  // Get decodes the reply to the i-th request in the batch
    72  func (r Replies) Get(i int, val interface{}) error {
    73  	if i < 0 || i >= len(r) {
    74  		return ErrNoReply
    75  	}
    76  	return rlp.DecodeBytes(r[i], val)
    77  }
    78  
    79  const (
    80  	IntNonNegative = iota
    81  	IntNegative
    82  	IntPlusInf
    83  	IntMinusInf
    84  )
    85  
    86  // IntOrInf is the encoding format for arbitrary length signed integers that can also
    87  // hold the values of +Inf or -Inf
    88  type IntOrInf struct {
    89  	Type  uint8
    90  	Value big.Int
    91  }
    92  
    93  // BigInt returns the value as a big.Int or panics if the value is infinity
    94  func (i *IntOrInf) BigInt() *big.Int {
    95  	switch i.Type {
    96  	case IntNonNegative:
    97  		return new(big.Int).Set(&i.Value)
    98  	case IntNegative:
    99  		return new(big.Int).Neg(&i.Value)
   100  	case IntPlusInf:
   101  		panic(nil) // caller should check Inf() before trying to convert to big.Int
   102  	case IntMinusInf:
   103  		panic(nil)
   104  	}
   105  	return &big.Int{} // invalid type decodes to 0 value
   106  }
   107  
   108  // Inf returns 1 if the value is +Inf, -1 if it is -Inf, 0 otherwise
   109  func (i *IntOrInf) Inf() int {
   110  	switch i.Type {
   111  	case IntPlusInf:
   112  		return 1
   113  	case IntMinusInf:
   114  		return -1
   115  	}
   116  	return 0 // invalid type decodes to 0 value
   117  }
   118  
   119  // Int64 limits the value between MinInt64 and MaxInt64 (even if it is +-Inf) and returns an int64 type
   120  func (i *IntOrInf) Int64() int64 {
   121  	switch i.Type {
   122  	case IntNonNegative:
   123  		if i.Value.IsInt64() {
   124  			return i.Value.Int64()
   125  		} else {
   126  			return math.MaxInt64
   127  		}
   128  	case IntNegative:
   129  		if i.Value.IsInt64() {
   130  			return -i.Value.Int64()
   131  		} else {
   132  			return math.MinInt64
   133  		}
   134  	case IntPlusInf:
   135  		return math.MaxInt64
   136  	case IntMinusInf:
   137  		return math.MinInt64
   138  	}
   139  	return 0 // invalid type decodes to 0 value
   140  }
   141  
   142  // SetBigInt sets the value to the given big.Int
   143  func (i *IntOrInf) SetBigInt(v *big.Int) {
   144  	if v.Sign() >= 0 {
   145  		i.Type = IntNonNegative
   146  		i.Value.Set(v)
   147  	} else {
   148  		i.Type = IntNegative
   149  		i.Value.Neg(v)
   150  	}
   151  }
   152  
   153  // SetInt64 sets the value to the given int64. Note that MaxInt64 translates to +Inf
   154  // while MinInt64 translates to -Inf.
   155  func (i *IntOrInf) SetInt64(v int64) {
   156  	if v >= 0 {
   157  		if v == math.MaxInt64 {
   158  			i.Type = IntPlusInf
   159  		} else {
   160  			i.Type = IntNonNegative
   161  			i.Value.SetInt64(v)
   162  		}
   163  	} else {
   164  		if v == math.MinInt64 {
   165  			i.Type = IntMinusInf
   166  		} else {
   167  			i.Type = IntNegative
   168  			i.Value.SetInt64(-v)
   169  		}
   170  	}
   171  }
   172  
   173  // SetInf sets the value to +Inf or -Inf
   174  func (i *IntOrInf) SetInf(sign int) {
   175  	if sign == 1 {
   176  		i.Type = IntPlusInf
   177  	} else {
   178  		i.Type = IntMinusInf
   179  	}
   180  }