github.com/ethw3/go-ethereuma@v0.0.0-20221013053120-c14602a4c23c/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/ethw3/go-ethereuma/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 // CapacityQueryReq 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 }