github.com/jimmyx0x/go-ethereum@v1.10.28/rlp/raw.go (about) 1 // Copyright 2015 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 rlp 18 19 import ( 20 "io" 21 "reflect" 22 ) 23 24 // RawValue represents an encoded RLP value and can be used to delay 25 // RLP decoding or to precompute an encoding. Note that the decoder does 26 // not verify whether the content of RawValues is valid RLP. 27 type RawValue []byte 28 29 var rawValueType = reflect.TypeOf(RawValue{}) 30 31 // StringSize returns the encoded size of a string. 32 func StringSize(s string) uint64 { 33 switch { 34 case len(s) == 0: 35 return 1 36 case len(s) == 1: 37 if s[0] <= 0x7f { 38 return 1 39 } else { 40 return 2 41 } 42 default: 43 return uint64(headsize(uint64(len(s))) + len(s)) 44 } 45 } 46 47 // BytesSize returns the encoded size of a byte slice. 48 func BytesSize(b []byte) uint64 { 49 switch { 50 case len(b) == 0: 51 return 1 52 case len(b) == 1: 53 if b[0] <= 0x7f { 54 return 1 55 } else { 56 return 2 57 } 58 default: 59 return uint64(headsize(uint64(len(b))) + len(b)) 60 } 61 } 62 63 // ListSize returns the encoded size of an RLP list with the given 64 // content size. 65 func ListSize(contentSize uint64) uint64 { 66 return uint64(headsize(contentSize)) + contentSize 67 } 68 69 // IntSize returns the encoded size of the integer x. Note: The return type of this 70 // function is 'int' for backwards-compatibility reasons. The result is always positive. 71 func IntSize(x uint64) int { 72 if x < 0x80 { 73 return 1 74 } 75 return 1 + intsize(x) 76 } 77 78 // Split returns the content of first RLP value and any 79 // bytes after the value as subslices of b. 80 func Split(b []byte) (k Kind, content, rest []byte, err error) { 81 k, ts, cs, err := readKind(b) 82 if err != nil { 83 return 0, nil, b, err 84 } 85 return k, b[ts : ts+cs], b[ts+cs:], nil 86 } 87 88 // SplitString splits b into the content of an RLP string 89 // and any remaining bytes after the string. 90 func SplitString(b []byte) (content, rest []byte, err error) { 91 k, content, rest, err := Split(b) 92 if err != nil { 93 return nil, b, err 94 } 95 if k == List { 96 return nil, b, ErrExpectedString 97 } 98 return content, rest, nil 99 } 100 101 // SplitUint64 decodes an integer at the beginning of b. 102 // It also returns the remaining data after the integer in 'rest'. 103 func SplitUint64(b []byte) (x uint64, rest []byte, err error) { 104 content, rest, err := SplitString(b) 105 if err != nil { 106 return 0, b, err 107 } 108 switch { 109 case len(content) == 0: 110 return 0, rest, nil 111 case len(content) == 1: 112 if content[0] == 0 { 113 return 0, b, ErrCanonInt 114 } 115 return uint64(content[0]), rest, nil 116 case len(content) > 8: 117 return 0, b, errUintOverflow 118 default: 119 x, err = readSize(content, byte(len(content))) 120 if err != nil { 121 return 0, b, ErrCanonInt 122 } 123 return x, rest, nil 124 } 125 } 126 127 // SplitList splits b into the content of a list and any remaining 128 // bytes after the list. 129 func SplitList(b []byte) (content, rest []byte, err error) { 130 k, content, rest, err := Split(b) 131 if err != nil { 132 return nil, b, err 133 } 134 if k != List { 135 return nil, b, ErrExpectedList 136 } 137 return content, rest, nil 138 } 139 140 // CountValues counts the number of encoded values in b. 141 func CountValues(b []byte) (int, error) { 142 i := 0 143 for ; len(b) > 0; i++ { 144 _, tagsize, size, err := readKind(b) 145 if err != nil { 146 return 0, err 147 } 148 b = b[tagsize+size:] 149 } 150 return i, nil 151 } 152 153 func readKind(buf []byte) (k Kind, tagsize, contentsize uint64, err error) { 154 if len(buf) == 0 { 155 return 0, 0, 0, io.ErrUnexpectedEOF 156 } 157 b := buf[0] 158 switch { 159 case b < 0x80: 160 k = Byte 161 tagsize = 0 162 contentsize = 1 163 case b < 0xB8: 164 k = String 165 tagsize = 1 166 contentsize = uint64(b - 0x80) 167 // Reject strings that should've been single bytes. 168 if contentsize == 1 && len(buf) > 1 && buf[1] < 128 { 169 return 0, 0, 0, ErrCanonSize 170 } 171 case b < 0xC0: 172 k = String 173 tagsize = uint64(b-0xB7) + 1 174 contentsize, err = readSize(buf[1:], b-0xB7) 175 case b < 0xF8: 176 k = List 177 tagsize = 1 178 contentsize = uint64(b - 0xC0) 179 default: 180 k = List 181 tagsize = uint64(b-0xF7) + 1 182 contentsize, err = readSize(buf[1:], b-0xF7) 183 } 184 if err != nil { 185 return 0, 0, 0, err 186 } 187 // Reject values larger than the input slice. 188 if contentsize > uint64(len(buf))-tagsize { 189 return 0, 0, 0, ErrValueTooLarge 190 } 191 return k, tagsize, contentsize, err 192 } 193 194 func readSize(b []byte, slen byte) (uint64, error) { 195 if int(slen) > len(b) { 196 return 0, io.ErrUnexpectedEOF 197 } 198 var s uint64 199 switch slen { 200 case 1: 201 s = uint64(b[0]) 202 case 2: 203 s = uint64(b[0])<<8 | uint64(b[1]) 204 case 3: 205 s = uint64(b[0])<<16 | uint64(b[1])<<8 | uint64(b[2]) 206 case 4: 207 s = uint64(b[0])<<24 | uint64(b[1])<<16 | uint64(b[2])<<8 | uint64(b[3]) 208 case 5: 209 s = uint64(b[0])<<32 | uint64(b[1])<<24 | uint64(b[2])<<16 | uint64(b[3])<<8 | uint64(b[4]) 210 case 6: 211 s = uint64(b[0])<<40 | uint64(b[1])<<32 | uint64(b[2])<<24 | uint64(b[3])<<16 | uint64(b[4])<<8 | uint64(b[5]) 212 case 7: 213 s = uint64(b[0])<<48 | uint64(b[1])<<40 | uint64(b[2])<<32 | uint64(b[3])<<24 | uint64(b[4])<<16 | uint64(b[5])<<8 | uint64(b[6]) 214 case 8: 215 s = uint64(b[0])<<56 | uint64(b[1])<<48 | uint64(b[2])<<40 | uint64(b[3])<<32 | uint64(b[4])<<24 | uint64(b[5])<<16 | uint64(b[6])<<8 | uint64(b[7]) 216 } 217 // Reject sizes < 56 (shouldn't have separate size) and sizes with 218 // leading zero bytes. 219 if s < 56 || b[0] == 0 { 220 return 0, ErrCanonSize 221 } 222 return s, nil 223 } 224 225 // AppendUint64 appends the RLP encoding of i to b, and returns the resulting slice. 226 func AppendUint64(b []byte, i uint64) []byte { 227 if i == 0 { 228 return append(b, 0x80) 229 } else if i < 128 { 230 return append(b, byte(i)) 231 } 232 switch { 233 case i < (1 << 8): 234 return append(b, 0x81, byte(i)) 235 case i < (1 << 16): 236 return append(b, 0x82, 237 byte(i>>8), 238 byte(i), 239 ) 240 case i < (1 << 24): 241 return append(b, 0x83, 242 byte(i>>16), 243 byte(i>>8), 244 byte(i), 245 ) 246 case i < (1 << 32): 247 return append(b, 0x84, 248 byte(i>>24), 249 byte(i>>16), 250 byte(i>>8), 251 byte(i), 252 ) 253 case i < (1 << 40): 254 return append(b, 0x85, 255 byte(i>>32), 256 byte(i>>24), 257 byte(i>>16), 258 byte(i>>8), 259 byte(i), 260 ) 261 262 case i < (1 << 48): 263 return append(b, 0x86, 264 byte(i>>40), 265 byte(i>>32), 266 byte(i>>24), 267 byte(i>>16), 268 byte(i>>8), 269 byte(i), 270 ) 271 case i < (1 << 56): 272 return append(b, 0x87, 273 byte(i>>48), 274 byte(i>>40), 275 byte(i>>32), 276 byte(i>>24), 277 byte(i>>16), 278 byte(i>>8), 279 byte(i), 280 ) 281 282 default: 283 return append(b, 0x88, 284 byte(i>>56), 285 byte(i>>48), 286 byte(i>>40), 287 byte(i>>32), 288 byte(i>>24), 289 byte(i>>16), 290 byte(i>>8), 291 byte(i), 292 ) 293 } 294 }