mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-02-21 10:27:26 +08:00
* v2.1.0 [omit consensus and adjacent] - this commit will be amended with the full release after the file copy is complete * 2.1.0 main node rollup
158 lines
3.3 KiB
Go
158 lines
3.3 KiB
Go
package multiaddr
|
||
|
||
import (
|
||
"bytes"
|
||
"fmt"
|
||
"strings"
|
||
|
||
"github.com/multiformats/go-varint"
|
||
)
|
||
|
||
func stringToBytes(s string) ([]byte, error) {
|
||
// consume trailing slashes
|
||
s = strings.TrimRight(s, "/")
|
||
|
||
var b bytes.Buffer
|
||
sp := strings.Split(s, "/")
|
||
|
||
if sp[0] != "" {
|
||
return nil, fmt.Errorf("failed to parse multiaddr %q: must begin with /", s)
|
||
}
|
||
|
||
// consume first empty elem
|
||
sp = sp[1:]
|
||
|
||
if len(sp) == 0 {
|
||
return nil, fmt.Errorf("failed to parse multiaddr %q: empty multiaddr", s)
|
||
}
|
||
|
||
for len(sp) > 0 {
|
||
name := sp[0]
|
||
p := ProtocolWithName(name)
|
||
if p.Code == 0 {
|
||
return nil, fmt.Errorf("failed to parse multiaddr %q: unknown protocol %s", s, sp[0])
|
||
}
|
||
_, _ = b.Write(p.VCode)
|
||
sp = sp[1:]
|
||
|
||
if p.Size == 0 { // no length.
|
||
continue
|
||
}
|
||
|
||
if len(sp) < 1 {
|
||
return nil, fmt.Errorf("failed to parse multiaddr %q: unexpected end of multiaddr", s)
|
||
}
|
||
|
||
if p.Path {
|
||
// it's a path protocol (terminal).
|
||
// consume the rest of the address as the next component.
|
||
sp = []string{"/" + strings.Join(sp, "/")}
|
||
}
|
||
|
||
a, err := p.Transcoder.StringToBytes(sp[0])
|
||
if err != nil {
|
||
return nil, fmt.Errorf("failed to parse multiaddr %q: invalid value %q for protocol %s: %s", s, sp[0], p.Name, err)
|
||
}
|
||
err = p.Transcoder.ValidateBytes(a)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("failed to validate multiaddr %q: invalid value %q for protocol %s: %w", s, sp[0], p.Name, err)
|
||
}
|
||
if p.Size < 0 { // varint size.
|
||
_, _ = b.Write(varint.ToUvarint(uint64(len(a))))
|
||
}
|
||
b.Write(a)
|
||
sp = sp[1:]
|
||
}
|
||
|
||
return b.Bytes(), nil
|
||
}
|
||
|
||
func readComponent(b []byte) (int, *Component, error) {
|
||
var offset int
|
||
code, n, err := ReadVarintCode(b)
|
||
if err != nil {
|
||
return 0, nil, err
|
||
}
|
||
offset += n
|
||
|
||
p := ProtocolWithCode(code)
|
||
if p.Code == 0 {
|
||
return 0, nil, fmt.Errorf("no protocol with code %d", code)
|
||
}
|
||
pPtr := protocolPtrByCode[code]
|
||
if pPtr == nil {
|
||
return 0, nil, fmt.Errorf("no protocol with code %d", code)
|
||
}
|
||
|
||
if p.Size == 0 {
|
||
c := &Component{
|
||
bytes: string(b[:offset]),
|
||
valueStartIdx: offset,
|
||
protocol: pPtr,
|
||
}
|
||
|
||
err := validateComponent(c)
|
||
if err != nil {
|
||
return 0, nil, err
|
||
}
|
||
|
||
return offset, c, nil
|
||
}
|
||
|
||
var size int
|
||
if p.Size < 0 {
|
||
// varint
|
||
var n int
|
||
size, n, err = ReadVarintCode(b[offset:])
|
||
if err != nil {
|
||
return 0, nil, err
|
||
}
|
||
offset += n
|
||
} else {
|
||
// Size is in bits, but we operate on bytes
|
||
size = p.Size / 8
|
||
}
|
||
|
||
if len(b[offset:]) < size || size <= 0 {
|
||
return 0, nil, fmt.Errorf("invalid value for size %d", len(b[offset:]))
|
||
}
|
||
|
||
c := &Component{
|
||
bytes: string(b[:offset+size]),
|
||
protocol: pPtr,
|
||
valueStartIdx: offset,
|
||
}
|
||
err = validateComponent(c)
|
||
if err != nil {
|
||
return 0, nil, err
|
||
}
|
||
|
||
return offset + size, c, err
|
||
}
|
||
|
||
func readMultiaddr(b []byte) (int, Multiaddr, error) {
|
||
if len(b) == 0 {
|
||
return 0, nil, fmt.Errorf("empty multiaddr")
|
||
}
|
||
|
||
var res Multiaddr
|
||
bytesRead := 0
|
||
sawPathComponent := false
|
||
for len(b) > 0 {
|
||
n, c, err := readComponent(b)
|
||
if err != nil {
|
||
return 0, nil, err
|
||
}
|
||
b = b[n:]
|
||
bytesRead += n
|
||
|
||
if sawPathComponent {
|
||
// It is an error to have another component after a path component.
|
||
return bytesRead, nil, fmt.Errorf("unexpected component after path component")
|
||
}
|
||
sawPathComponent = c.protocol.Path
|
||
res = append(res, *c)
|
||
}
|
||
return bytesRead, res, nil
|
||
}
|