fix serialization + boost codes

Signed-off-by: Ciro S. Costa <utxobr@protonmail.com>
This commit is contained in:
Ciro S. Costa 2021-04-19 09:05:07 -04:00
parent 79029ea95b
commit 598a420bed
5 changed files with 104 additions and 80 deletions

View file

@ -18,9 +18,9 @@ const (
BoostSerializeTypeDouble byte = 0x9
BoostSerializeTypeString byte = 0x10
BoostSerializeTypeBool byte = 0x11
BoostSerializeTypeObject byte = 0x12
BoostSerializeTypeString byte = 0x0a
BoostSerializeTypeBool byte = 0x0b
BoostSerializeTypeObject byte = 0x0c
BoostSerializeTypeArray byte = 0x13
BoostSerializeFlagArray byte = 0x80

View file

@ -5,6 +5,7 @@ import (
"fmt"
"io"
"net"
"os"
"time"
)
@ -47,52 +48,21 @@ func (c *Client) Handshake(ctx context.Context) error {
Name: "node_data",
Serializable: &Section{
Entries: []Entry{
{
Name: "local_time",
Serializable: BoostUint64(time.Now().Unix()),
},
{
Name: "my_port",
Serializable: BoostUint32(0),
},
{
Name: "network_id",
Serializable: BoostString(string(MainnetNetworkId)),
},
{
Name: "peer_id",
Serializable: BoostUint64(12343332),
},
},
},
},
{
Name: "payload_data",
Serializable: &Section{
Entries: []Entry{
{
Name: "cumulative_difficulty",
Serializable: BoostUint64(1),
},
{
Name: "current_height",
Serializable: BoostUint64(1),
},
{
Name: "top_id",
Serializable: BoostString(MainnetGenesisTx),
},
{
Name: "top_version",
Serializable: BoostByte(1),
},
},
},
},
},
}).Bytes()
for _, b := range payload {
fmt.Printf("%x ", b)
}
fmt.Println()
reqHeaderB := NewRequestHeader(CommandHandshake, uint64(len(payload))).Bytes()
if _, err := c.conn.Write(reqHeaderB); err != nil {
@ -103,18 +73,42 @@ func (c *Client) Handshake(ctx context.Context) error {
return fmt.Errorf("write payload: %w", err)
}
again:
responseHeaderB := make([]byte, LevinHeaderSizeBytes)
if _, err := io.ReadFull(c.conn, responseHeaderB); err != nil {
return fmt.Errorf("read full header: %w", err)
}
respHeader, err := NewHeaderFromResponseBytes(responseHeaderB)
respHeader, err := NewHeaderFromBytesBytes(responseHeaderB)
if err != nil {
return fmt.Errorf("new header from resp bytes: %w", err)
}
fmt.Printf("%+v\n", respHeader)
if respHeader.Length != 0 {
var dest io.Writer = os.Stderr
if respHeader.Command == CommandHandshake {
f, err := os.Create("resp.bin")
if err != nil {
panic(err)
}
defer f.Close()
dest = f
}
if _, err := io.CopyN(dest, c.conn, int64(respHeader.Length)); err != nil {
return fmt.Errorf("copy payload to stdout: %w", err)
}
}
if respHeader.Command != CommandHandshake {
goto again
}
return nil
}
@ -130,7 +124,7 @@ func (c *Client) Ping(ctx context.Context) error {
return fmt.Errorf("read full header: %w", err)
}
respHeader, err := NewHeaderFromResponseBytes(responseHeaderB)
respHeader, err := NewHeaderFromBytesBytes(responseHeaderB)
if err != nil {
return fmt.Errorf("new header from resp bytes: %w", err)
}

View file

@ -35,7 +35,8 @@ const (
)
func IsValidReturnCode(c int32) bool {
return (c >= LevinErrorFormat && c <= LevinOk)
// anything >= 0 is good (there are some `1`s in the code :shrug:)
return c >= LevinErrorFormat
}
const (
@ -57,7 +58,7 @@ var (
0x16, 0xa1, 0xa1, 0x10,
}
MainnetGenesisTx = "013c01ff0001ffffffffffff03029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121017767aafcde9be00dcfd098715ebcf7f410daebc582fda69d24a28e9d0bc890d1"
MainnetGenesisTx = "418015bb9ae982a1975da7d79277c2705727a56894ba0fb246adaabb1f4632e3"
)
func IsValidCommand(c uint32) bool {
@ -154,7 +155,7 @@ func NewRequestHeader(command uint32, length uint64) *Header {
}
}
func NewHeaderFromResponseBytes(bytes []byte) (*Header, error) {
func NewHeaderFromBytesBytes(bytes []byte) (*Header, error) {
if len(bytes) != LevinHeaderSizeBytes {
return nil, fmt.Errorf("invalid header size: expected %d, has %d",
LevinHeaderSizeBytes, len(bytes),
@ -216,11 +217,6 @@ func NewHeaderFromResponseBytes(bytes []byte) (*Header, error) {
size = 4
header.Flags = binary.LittleEndian.Uint32(bytes[idx : idx+size])
idx += size
if header.Flags != LevinPacketReponse {
return nil, fmt.Errorf("response flag not properly set %x",
header.Flags)
}
}
{ // version

View file

@ -12,14 +12,14 @@ import (
func TestLevin(t *testing.T) {
spec.Run(t, "NewHeaderFromResponse", func(t *testing.T, when spec.G, it spec.S) {
spec.Run(t, "NewHeaderFromBytes", func(t *testing.T, when spec.G, it spec.S) {
it("fails w/ wrong size", func() {
bytes := []byte{
0xff,
}
_, err := levin.NewHeaderFromResponseBytes(bytes)
_, err := levin.NewHeaderFromBytesBytes(bytes)
assert.Error(t, err)
})
@ -36,7 +36,7 @@ func TestLevin(t *testing.T) {
0x00, 0x00, 0x00, 0x00, // version
}
_, err := levin.NewHeaderFromResponseBytes(bytes)
_, err := levin.NewHeaderFromBytesBytes(bytes)
assert.Error(t, err)
assert.Contains(t, err.Error(), "signature mismatch")
})
@ -54,7 +54,7 @@ func TestLevin(t *testing.T) {
0x00, 0x00, 0x00, 0x00, // version
}
_, err := levin.NewHeaderFromResponseBytes(bytes)
_, err := levin.NewHeaderFromBytesBytes(bytes)
assert.Error(t, err)
assert.Contains(t, err.Error(), "invalid command")
})
@ -66,35 +66,17 @@ func TestLevin(t *testing.T) {
0x01, 0x00, 0x00, 0x00, // length
0x00, 0x00, 0x00, 0x00, //
0x01, // expects response
0x03, 0x10, 0x00, 0x00, // command
0xe9, 0x03, 0x00, 0x00, // command
0xaa, 0xaa, 0xaa, 0xaa, // return code
0x00, 0x00, 0x00, 0x00, // flags
0x00, 0x00, 0x00, 0x00, // version
}
_, err := levin.NewHeaderFromResponseBytes(bytes)
_, err := levin.NewHeaderFromBytesBytes(bytes)
assert.Error(t, err)
assert.Contains(t, err.Error(), "invalid return code")
})
it("fails w/ response flag not set", func() {
bytes := []byte{
0x01, 0x21, 0x01, 0x01, // signature
0x01, 0x01, 0x01, 0x01,
0x01, 0x00, 0x00, 0x00, // length
0x00, 0x00, 0x00, 0x00, //
0x01, // expects response
0x03, 0x10, 0x00, 0x00, // command
0x00, 0x00, 0x00, 0x00, // return code
0x00, 0x00, 0x00, 0x00, // flags
0x00, 0x00, 0x00, 0x00, // version
}
_, err := levin.NewHeaderFromResponseBytes(bytes)
assert.Error(t, err)
assert.Contains(t, err.Error(), "response flag not properly set")
})
it("fails w/ invalid version", func() {
bytes := []byte{
0x01, 0x21, 0x01, 0x01, // signature
@ -102,13 +84,13 @@ func TestLevin(t *testing.T) {
0x01, 0x00, 0x00, 0x00, // length
0x00, 0x00, 0x00, 0x00, //
0x01, // expects response
0x03, 0x10, 0x00, 0x00, // command
0xe9, 0x03, 0x00, 0x00, // command
0x00, 0x00, 0x00, 0x00, // return code
0x02, 0x00, 0x00, 0x00, // flags
0x00, 0x00, 0x00, 0x00, // version
}
_, err := levin.NewHeaderFromResponseBytes(bytes)
_, err := levin.NewHeaderFromBytesBytes(bytes)
assert.Error(t, err)
assert.Contains(t, err.Error(), "invalid version")
})
@ -120,13 +102,13 @@ func TestLevin(t *testing.T) {
0x01, 0x00, 0x00, 0x00, // length
0x00, 0x00, 0x00, 0x00, //
0x01, // expects response
0x03, 0x10, 0x00, 0x00, // command
0xeb, 0x03, 0x00, 0x00, // command
0x00, 0x00, 0x00, 0x00, // return code
0x02, 0x00, 0x00, 0x00, // flags
0x01, 0x00, 0x00, 0x00, // version
}
header, err := levin.NewHeaderFromResponseBytes(bytes)
header, err := levin.NewHeaderFromBytesBytes(bytes)
assert.NoError(t, err)
assert.Equal(t, header.Command, levin.CommandPing)
assert.Equal(t, header.ReturnCode, levin.LevinOk)
@ -147,7 +129,7 @@ func TestLevin(t *testing.T) {
0x01, 0x00, 0x00, 0x00, // length -- 0 for a ping msg
0x00, 0x00, 0x00, 0x00,
0x01, // expects response -- `true` bool
0x03, 0x10, 0x00, 0x00, // command -- 1003 for ping
0xeb, 0x03, 0x00, 0x00, // command -- 1003 for ping
0x00, 0x00, 0x00, 0x00, // return code -- 0 for requests
0x01, 0x00, 0x00, 0x00, // flags -- Q(1st lsb) set for req
0x01, 0x00, 0x00, 0x00, // version
@ -162,8 +144,8 @@ func TestLevin(t *testing.T) {
0x01, 0x01, 0x01, 0x01,
0x04, 0x00, 0x00, 0x00, // length -- 0 for a ping msg
0x00, 0x00, 0x00, 0x00,
0x01, // expects response -- `true` bool
0x01, 0x10, 0x00, 0x00, // command -- 1003 for ping
0x01, // expects response -- `true` bool
0xe9, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, // return code -- 0 for requests
0x01, 0x00, 0x00, 0x00, // flags -- Q(1st lsb) set for req
0x01, 0x00, 0x00, 0x00, // version

View file

@ -32,6 +32,58 @@ type PortableStorage struct {
Entries []Entry
}
func NewPortableStorageFromBytes(bytes []byte) error {
var (
size = 0
idx = 0
)
{ // sig-a
size = 4
sig := binary.LittleEndian.Uint32(bytes[idx : idx+size])
idx += size
if sig != uint32(PortableStorageSignatureA) {
return fmt.Errorf("sig-a doesn't match")
}
}
{ // sig-b
size = 4
sig := binary.LittleEndian.Uint32(bytes[idx : idx+size])
idx += size
if sig != uint32(PortableStorageSignatureB) {
return fmt.Errorf("sig-b doesn't match")
}
}
{ // format ver
size = 1
version := bytes[idx]
idx += size
if version != PortableStorageFormatVersion {
return fmt.Errorf("version doesn't match")
}
}
// read section
// count = read var int (gives you number of entries)
// while count >0:
//
return nil
}
func ReadVarInt(b []byte) int {
// read mask
// depending on the mask:
// read N next bytes
return 0
}
func (s *PortableStorage) Bytes() []byte {
var (
body = make([]byte, 9) // fit _at least_ signatures + format ver