Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

exp/lighthorizon: Prototyping support for XDR serialization #4369

Merged
merged 5 commits into from
May 5, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions exp/lighthorizon/index/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
source 'https://rubygems.org'

gem 'xdrgen', git:'https://github.com/stellar/xdrgen.git', ref: 'master'
gem 'pry'
gem 'octokit'
gem 'netrc'
gem 'rake'
Shaptic marked this conversation as resolved.
Show resolved Hide resolved
53 changes: 53 additions & 0 deletions exp/lighthorizon/index/Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
require 'bundler'
Bundler.setup()
require 'pry'

namespace :xdr do

HORIZON_XDR = [
"xdr/LightHorizon-types.x"
]
LOCAL_XDR_PATHS = HORIZON_XDR.map{ |src| "xdr/" + File.basename(src) }

task :update => [:download, :generate]

task :download do
require 'octokit'
require 'base64'
FileUtils.mkdir_p "xdr"
FileUtils.rm_rf "xdr/*.x"

client = Octokit::Client.new(:netrc => true)

HORIZON_XDR.each do |src|
local_path = "xdr/" + File.basename(src)
encoded = client.contents("stellar/go/exp/lighthorizon", path: src).content
decoded = Base64.decode64 encoded

IO.write(local_path, decoded)
end
end

task :generate do
require "pathname"
require "xdrgen"
require 'fileutils'

compilation = Xdrgen::Compilation.new(
LOCAL_XDR_PATHS,
output_dir: "xdr",
namespace: "xdr",
language: :go
)
compilation.compile

xdr_generated = IO.read("xdr/xdr_generated.go")
IO.write("xdr/xdr_generated.go", <<~EOS)
//lint:file-ignore S1005 The issue should be fixed in xdrgen. Unfortunately, there's no way to ignore a single file in staticcheck.
//lint:file-ignore U1000 fmtTest is not needed anywhere, should be removed in xdrgen.
Shaptic marked this conversation as resolved.
Show resolved Hide resolved
#{xdr_generated}
EOS

system("gofmt -w xdr/xdr_generated.go")
end
end
60 changes: 18 additions & 42 deletions exp/lighthorizon/index/main.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package index

import (
"bufio"
"bytes"
"io"
"strconv"
"sync"

"github.com/stellar/go/exp/lighthorizon/index/xdr"
)

const CheckpointIndexVersion = 1
Expand All @@ -18,44 +18,16 @@ type CheckpointIndex struct {
}

func NewCheckpointIndexFromBytes(b []byte) (*CheckpointIndex, error) {
buf := bytes.NewBuffer(b)
r := bufio.NewReader(buf)

firstCheckpointString, err := r.ReadString(0x00)
if err != nil {
return nil, err
}

// Remove trailing 0x00 byte
firstCheckpointString = firstCheckpointString[:len(firstCheckpointString)-1]

firstCheckpoint, err := strconv.ParseUint(firstCheckpointString, 10, 32)
if err != nil {
return nil, err
}

lastCheckpointString, err := r.ReadString(0x00)
if err != nil {
return nil, err
}

// Remove trailing 0x00 byte
lastCheckpointString = lastCheckpointString[:len(lastCheckpointString)-1]

lastCheckpoint, err := strconv.ParseUint(lastCheckpointString, 10, 32)
if err != nil {
return nil, err
}

bitmap, err := io.ReadAll(r)
xdrCheckpoint := xdr.CheckpointIndex{}
err := xdrCheckpoint.UnmarshalBinary(b)
if err != nil {
return nil, err
}

return &CheckpointIndex{
bitmap: bitmap,
firstCheckpoint: uint32(firstCheckpoint),
lastCheckpoint: uint32(lastCheckpoint),
bitmap: xdrCheckpoint.Bitmap,
firstCheckpoint: uint32(xdrCheckpoint.FirstCheckpoint),
lastCheckpoint: uint32(xdrCheckpoint.LastCheckpoint),
}, nil
Comment on lines 27 to 31
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better would of course to make xdr.CheckpointIndex part of CheckpointIndex, but since I'm just prototyping this is less changes until we land on the "right" pattern for this.

}

Expand Down Expand Up @@ -243,13 +215,17 @@ func (i *CheckpointIndex) Buffer() *bytes.Buffer {
i.mutex.RLock()
defer i.mutex.RUnlock()

var b bytes.Buffer
b.WriteString(strconv.FormatUint(uint64(i.firstCheckpoint), 10))
b.WriteByte(0)
b.WriteString(strconv.FormatUint(uint64(i.lastCheckpoint), 10))
b.WriteByte(0)
b.Write(i.bitmap)
return &b
xdrCheckpoint := xdr.CheckpointIndex{
FirstCheckpoint: xdr.Uint32(i.firstCheckpoint),
LastCheckpoint: xdr.Uint32(i.lastCheckpoint),
Bitmap: i.bitmap,
}

b, err := xdrCheckpoint.MarshalBinary()
if err != nil {
panic(err)
}
return bytes.NewBuffer(b)
}

// Flush flushes the index data to byte slice in index format.
Expand Down
17 changes: 17 additions & 0 deletions exp/lighthorizon/index/xdr/LightHorizon-types.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2022 Stellar Development Foundation and contributors. Licensed
// under the Apache License, Version 2.0. See the COPYING file at the root
// of this distribution or at http://www.apache.org/licenses/LICENSE-2.0

namespace stellar
{

typedef unsigned int uint32;
typedef opaque Value<>;

struct CheckpointIndex {
uint32 firstCheckpoint;
uint32 lastCheckpoint;
opaque bitmap<>;
};

}
Loading