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

feature/oonodz-integration. Integrate ooNodz workflow and create and push docker images #176

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
52 changes: 52 additions & 0 deletions .github/workflows/ci-push-image-aylin.yml
@@ -0,0 +1,52 @@
name: Build + Push aylin image

on:
push:
branches:
- aylin

defaults:
run:
shell: bash

jobs:
build_fuji_image_aylin:
name: Build Docker Image
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Get Current Tag
id: get_tag
run: echo ::set-output name=tag::$(git describe --abbrev=0 --tags)

- name: Login to Docker hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASS }}

- name: Build Dockerfile and Push it
run: |
TAG_END=$GITHUB_SHA

if [ -n "$GITHUB_TAG" ]; then
TAG_END=$GITHUB_TAG
fi

export BUILD_IMAGE_ID="${{ vars.AVALANCHE_VERSION_DEV }}-aylin-${TAG_END}"

# Copy binary to the correct Fuji VM ID respository
echo "COPY --from=builder /build/jvrKsTB9MfYGnAXtxbzFYpXKceXr9J8J8ej6uWGrYM5tXswhJ /root/.avalanchego/plugins/jvrKsTB9MfYGnAXtxbzFYpXKceXr9J8J8ej6uWGrYM5tXswhJ" >> Dockerfile

# Copy binary to the correct Mainnet VM ID respository
echo "COPY --from=builder /build/jvrKsTB9MfYGnAXtxbzFYpXKceXr9J8J8ej6uWGrYM5tXswhJ /root/.avalanchego/plugins/o1Fg94YujMqL75Ebrdkos95MTVjZpPpdeAp5ocEsp2X9c2FSz" >> Dockerfile

./scripts/build_image.sh
env:
CURRENT_BRANCH: ${{ github.head_ref || github.ref_name }}
PUSH_DOCKER_IMAGE: true
DOCKERHUB_REPO: hubbleexchange/hubblenet
GITHUB_TAG: ${{ steps.get_tag.outputs.tag }}
GITHUB_SHA: ${{ github.sha }}
85 changes: 85 additions & 0 deletions .github/workflows/push-image-release.yml
@@ -0,0 +1,85 @@
name: Build + Push release image

on:
workflow_dispatch:
inputs:
release_tag:
description: 'Release tag'
required: true
type: string

defaults:
run:
shell: bash

jobs:
build_release_image:
name: Build Docker Image
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Login to Docker hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASS }}

- name: Create the Dockerfile
env:
HUBBLENET_RELEASE_TAG: ${{ inputs.release_tag }}
AVALANCHE_VERSION: ${{ vars.AVALANCHE_VERSION }}
run: |
if [ "${HUBBLENET_RELEASE_TAG:0:1}" = "v" ]; then
HUBBLENET_VERSION="${HUBBLENET_RELEASE_TAG:1}";
HUBBLENET_RELEASE_TAG="${HUBBLENET_RELEASE_TAG}";
else
HUBBLENET_VERSION="${HUBBLENET_RELEASE_TAG}";
fi

multiline_text=$(cat <<EOF
FROM avaplatform/avalanchego:${AVALANCHE_VERSION} as builder

RUN apt update \
&& DEBIAN_FRONTEND="noninteractive" apt install -y wget \
&& cd /tmp \
&& wget https://github.com/hubble-exchange/hubblenet/releases/download/${HUBBLENET_RELEASE_TAG}/hubblenet_${HUBBLENET_VERSION}_linux_amd64.tar.gz \
&& tar -xf hubblenet_${HUBBLENET_VERSION}_linux_amd64.tar.gz

FROM avaplatform/avalanchego:${AVALANCHE_VERSION}
LABEL Description="Hubblenet image"
ARG VM_ID

RUN mkdir -p /root/.avalanchego/plugins \
&& DEBIAN_FRONTEND="noninteractive" apt update \
&& DEBIAN_FRONTEND="noninteractive" apt install -y wget

COPY --from=builder /tmp/hubblenet-${HUBBLENET_VERSION} /root/.avalanchego/plugins/\${VM_ID}

EOF
)

echo "$multiline_text" > Dockerfile-release
cat Dockerfile-release

- name: Build and push release image for the mainnet
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile-release
push: true
tags: "hubbleexchange/hubblenet:${{ vars.AVALANCHE_VERSION }}-${{ inputs.release_tag }}"
build-args: |
VM_ID=o1Fg94YujMqL75Ebrdkos95MTVjZpPpdeAp5ocEsp2X9c2FSz


- name: Build and push release image for the fuji
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile-release
push: true
tags: "hubbleexchange/hubblenet:${{ vars.AVALANCHE_VERSION }}-fuji-${{ inputs.release_tag }}"
build-args: |
VM_ID=jvrKsTB9MfYGnAXtxbzFYpXKceXr9J8J8ej6uWGrYM5tXswhJ
3 changes: 1 addition & 2 deletions chain.json
Expand Up @@ -7,8 +7,7 @@
"priority-regossip-txs-per-address": 200,
"priority-regossip-addresses": ["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", "0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC"],
"validator-private-key-file": "/tmp/validator.pk",
"is-validator": true,
"trading-api-enabled": true,
"node-type": "kitkat_berghain",
"testing-api-enabled": true,
"load-from-snapshot-enabled": true,
"snapshot-file-path": "/tmp/snapshot",
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -16,6 +16,7 @@ require (
github.com/fsnotify/fsnotify v1.6.0
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08
github.com/go-cmd/cmd v1.4.1
github.com/golang/mock v1.6.0
github.com/google/uuid v1.3.0
github.com/gorilla/rpc v1.2.0
github.com/gorilla/websocket v1.4.2
Expand Down Expand Up @@ -77,7 +78,6 @@ require (
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.3.0 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/google/btree v1.1.2 // indirect
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Expand Up @@ -1049,8 +1049,6 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
Expand Down
5 changes: 5 additions & 0 deletions network-configs/aylin/chain_tresor.json
@@ -0,0 +1,5 @@
{
"state-sync-enabled": true,
"feeRecipient": "0xB3D25D47291D7F8b97FE3884A924541cDDcbB8Be",
"node-type": "tresor"
}
12 changes: 4 additions & 8 deletions plugin/evm/config.go
Expand Up @@ -60,8 +60,7 @@ const (
defaultStateSyncMinBlocks = 300_000
defaultStateSyncRequestSize = 1024 // the number of key/values to ask peers for per request

defaultIsValidator = false
defaultTradingAPIEnabled = false
defaultNodeType = "tresor"
defaultLoadFromSnapshotEnabled = true
defaultSnapshotFilePath = "/tmp/snapshot"
defaultMakerbookDatabasePath = "/tmp/makerbook"
Expand Down Expand Up @@ -236,11 +235,9 @@ type Config struct {

// Testing apis enabled
TestingApiEnabled bool `json:"testing-api-enabled"`
// IsValidator is true if this node is a validator
IsValidator bool `json:"is-validator"`

// TradingAPI is for the sdk
TradingAPIEnabled bool `json:"trading-api-enabled"`
// NodeType is the type of node among the following: "tresor", "kitkat", "berghain", meaning validator only, matching engine, rpc node respectively
NodeType string `json:"node-type"`

// LoadFromSnapshotEnabled = true if the node should load the memory db from a snapshot
LoadFromSnapshotEnabled bool `json:"load-from-snapshot-enabled"`
Expand Down Expand Up @@ -311,8 +308,7 @@ func (c *Config) SetDefaults() {
c.AcceptedCacheSize = defaultAcceptedCacheSize
c.ValidatorPrivateKeyFile = defaultValidatorPrivateKeyFile
c.TestingApiEnabled = defaultTestingApiEnabled
c.IsValidator = defaultIsValidator
c.TradingAPIEnabled = defaultTradingAPIEnabled
c.NodeType = defaultNodeType
c.LoadFromSnapshotEnabled = defaultLoadFromSnapshotEnabled
c.SnapshotFilePath = defaultSnapshotFilePath
c.MakerbookDatabasePath = defaultMakerbookDatabasePath
Expand Down
5 changes: 5 additions & 0 deletions plugin/evm/gossiper_orders.go
Expand Up @@ -125,6 +125,11 @@ func (n *pushGossiper) sendSignedOrders(orders []*hu.SignedOrder) error {
// #### HANDLER ####

func (h *GossipHandler) HandleSignedOrders(nodeID ids.NodeID, msg message.SignedOrdersGossip) error {
// for vanilla validators we do not care about gossiping orders
if h.vm.limitOrderProcesser.GetNodeType() == Tresor {
return nil
}

h.mu.Lock()
defer h.mu.Unlock()

Expand Down
73 changes: 68 additions & 5 deletions plugin/evm/limit_order.go
Expand Up @@ -9,6 +9,7 @@ import (
"os"
"runtime"
"runtime/debug"
"strings"
"sync"
"time"

Expand All @@ -32,12 +33,23 @@ const (
snapshotInterval uint64 = 10 // save snapshot every 1000 blocks
)

type NodeType string

const (
Tresor NodeType = "tresor" // vanilla validator
Kitkat NodeType = "kitkat" // validator + matching engine
Berghain NodeType = "berghain" // rpc node
Kitkat_Berghain NodeType = "kitkat_berghain" // validator + matching engine + rpc node
)

type LimitOrderProcesser interface {
ListenAndProcessTransactions(blockBuilder *blockBuilder)
GetOrderBookAPI() *orderbook.OrderBookAPI
GetTestingAPI() *orderbook.TestingAPI
GetTradingAPI() *orderbook.TradingAPI
RunMatchingPipeline()
GetNodeType() NodeType
isMatcherNode() bool
}

type limitOrderProcesser struct {
Expand All @@ -56,19 +68,36 @@ type limitOrderProcesser struct {
hubbleDB database.Database
configService orderbook.IConfigService
blockBuilder *blockBuilder
isValidator bool
tradingAPIEnabled bool
nodeType NodeType
loadFromSnapshotEnabled bool
snapshotSavedBlockNumber uint64
snapshotFilePath string
tradingAPI *orderbook.TradingAPI
}

func NewLimitOrderProcesser(ctx *snow.Context, txPool *txpool.TxPool, shutdownChan <-chan struct{}, shutdownWg *sync.WaitGroup, backend *eth.EthAPIBackend, blockChain *core.BlockChain, hubbleDB database.Database, validatorPrivateKey string, config Config) LimitOrderProcesser {
func NewLimitOrderProcesser(ctx *snow.Context, txPool *txpool.TxPool, shutdownChan <-chan struct{}, shutdownWg *sync.WaitGroup, backend *eth.EthAPIBackend, blockChain *core.BlockChain, hubbleDB database.Database, config Config) (LimitOrderProcesser, error) {
log.Info("**** NewLimitOrderProcesser")

configService := orderbook.NewConfigService(blockChain)
memoryDb := orderbook.NewInMemoryDatabase(configService)

nodeType, err := stringToNodeType(config.NodeType)
if err != nil {
return nil, err
}
var validatorPrivateKey string
if nodeType == Kitkat || nodeType == Kitkat_Berghain {
validatorPrivateKey, err = loadPrivateKeyFromFile(config.ValidatorPrivateKeyFile)
if err != nil {
panic(fmt.Sprint("please specify correct path for validator-private-key-file in chain.json ", err))
}
if validatorPrivateKey == "" {
panic("validator private key is empty")
}
}
lotp := orderbook.NewLimitOrderTxProcessor(txPool, memoryDb, backend, validatorPrivateKey)

signedObAddy := configService.GetSignedOrderbookContract()
contractEventProcessor := orderbook.NewContractEventsProcessor(memoryDb, signedObAddy)

Expand Down Expand Up @@ -110,14 +139,40 @@ func NewLimitOrderProcesser(ctx *snow.Context, txPool *txpool.TxPool, shutdownCh
matchingPipeline: matchingPipeline,
filterAPI: filterAPI,
configService: configService,
isValidator: config.IsValidator,
tradingAPIEnabled: config.TradingAPIEnabled,
nodeType: nodeType,
loadFromSnapshotEnabled: config.LoadFromSnapshotEnabled,
snapshotFilePath: config.SnapshotFilePath,
}, nil
}

func loadPrivateKeyFromFile(keyFile string) (string, error) {
key, err := os.ReadFile(keyFile)
if err != nil {
return "", err
}
return strings.TrimSuffix(string(key), "\n"), nil
}

func stringToNodeType(nodeTypeString string) (NodeType, error) {
switch nodeTypeString {
case string(Tresor):
return Tresor, nil
case string(Kitkat):
return Kitkat, nil
case string(Berghain):
return Berghain, nil
case string(Kitkat_Berghain):
return Kitkat_Berghain, nil
default:
return "", fmt.Errorf("unknown NodeType: %s", nodeTypeString)
}
}

func (lop *limitOrderProcesser) ListenAndProcessTransactions(blockBuilder *blockBuilder) {
if lop.nodeType == Tresor {
return
}

lop.mu.Lock()

lastAccepted := lop.blockChain.LastAcceptedBlock()
Expand Down Expand Up @@ -174,7 +229,7 @@ func (lop *limitOrderProcesser) ListenAndProcessTransactions(blockBuilder *block
}

func (lop *limitOrderProcesser) RunMatchingPipeline() {
if !lop.isValidator {
if !lop.isMatcherNode() {
return
}
executeFuncAndRecoverPanic(func() {
Expand Down Expand Up @@ -206,6 +261,14 @@ func (lop *limitOrderProcesser) GetTestingAPI() *orderbook.TestingAPI {
return orderbook.NewTestingAPI(lop.memoryDb, lop.backend, lop.configService, lop.hubbleDB)
}

func (lop *limitOrderProcesser) GetNodeType() NodeType {
return lop.nodeType
}

func (lop *limitOrderProcesser) isMatcherNode() bool {
return lop.nodeType == Kitkat || lop.nodeType == Kitkat_Berghain
}

func (lop *limitOrderProcesser) listenAndStoreLimitOrderTransactions() {
logsCh := make(chan []*types.Log)
logsSubscription := lop.backend.SubscribeHubbleLogsEvent(logsCh)
Expand Down
1 change: 1 addition & 0 deletions plugin/evm/order_api.go
Expand Up @@ -60,6 +60,7 @@ func (api *OrderAPI) PlaceSignedOrders(ctx context.Context, input string) (Place
continue
}

// we ignore the 2nd argument shouldTriggerMatching. since PlaceSignedOrders is only called in API nodes, we do not trigger matching in them
orderId, _, err := api.tradingAPI.PlaceOrder(order)
orderResponse.OrderId = orderId.String()
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions plugin/evm/orderbook_test.go
Expand Up @@ -961,8 +961,8 @@ func TestHubbleLogs(t *testing.T) {
// Create two VMs which will agree on block A and then
// build the two distinct preferred chains above
ctx := context.Background()
issuer1, vm1, _, _ := GenesisVM(t, true, genesisJSON, "{\"pruning-enabled\":true}", "")
issuer2, vm2, _, _ := GenesisVM(t, true, genesisJSON, "{\"pruning-enabled\":true}", "")
issuer1, vm1, _, _ := GenesisVM(t, true, genesisJSON, "{\"pruning-enabled\":true,\"node-type\":\"kitkat\"}", "")
issuer2, vm2, _, _ := GenesisVM(t, true, genesisJSON, "{\"pruning-enabled\":true,\"node-type\":\"kitkat\"}", "")

defer func() {
if err := vm1.Shutdown(ctx); err != nil {
Expand Down