Skip to content

Commit

Permalink
Merge pull request #63 from pegnet/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
sambarnes committed Oct 11, 2019
2 parents eb9d640 + 0d80c2b commit c39b409
Show file tree
Hide file tree
Showing 13 changed files with 198 additions and 19 deletions.
8 changes: 8 additions & 0 deletions .gofmt.sh
@@ -0,0 +1,8 @@
#!/bin/bash

if [ -n "$(gofmt -l .)" ]; then
echo "Go code is not properly formatted:"
gofmt -d .
echo "Run 'gofmt -s -w .' to fix"
exit 1
fi
62 changes: 62 additions & 0 deletions .travis.yml
@@ -0,0 +1,62 @@
language: go

# Use latest go version
go:
- 1.x

services:
- docker

os:
- osx
- windows

# Run gofmt only on linux
matrix:
fast_finish: true
include:
- os: linux
script:
- ./.gofmt.sh
- go test -v -timeout 45m ./...
allow_failures:
- os: windows

script:
- go test -v -timeout 45m ./...

# GO111MODULE will force Go modules
# This will be unnecessary when Go 1.13 lands.
# Also set the bit size to 10 so we can build the hashtable quick
env:
- GO111MODULE=on LXRBITSIZE=10


# Modifies go get flags
# Can be removed when factom@v1-rollup is merged into master
install: true

# No spam
notifications:
email: false

# Build with gox
before_deploy:
- go get github.com/karalabe/xgo
- docker build --tag xgo-builder xgo
- xgo -image xgo-builder --targets=windows/amd64,darwin/amd64,linux/amd64 .
- ls


deploy:
provider: releases
api_key:
secure: olgjR93AxZChmTriGo4DkofTJIhCqymhRPl1qGcO3uD3xBMsmX760kQhGjkMUcgzenhOhtqxiRB9acYPoqPb2LGYNU2Ff8sMXfx5Oa3JMb9yEnosLbPDwM5D0nTdWhgn+VzQlA6QwqzZUejft7qUtDBDwYnLL6AwRaM0BjjvpXHeoyXq2KZGX9VZRijkq0rPFaGhsLHv/2ebfs+adJi/UUzNBO6/AQQrXBI5Bbr6t3ELbkGpEHzjr91ZgCsQiGDxv/JuZKeMEgUuTLM/9b8a9vqqEpzjthfbzuWtrxNCEaVwS/jUPFik+7agXCg9bJzthVHFxcQyFfP/evkm9+OWLpJrKAQc9LieYxgySesZRxzlqLj9zU9WBdoAE46YlOQUvTYuN6pUAD4bhNoR+enLVvYZVn6jSuRF/ggvUqE7kw537GpnaA9qGepGBuvYdFcuIo/EUddc3i24e9FYhgOWxjaBf7SR/G/G/b7jCqCows6SSOtalZP06fcgk/yXG4x654crjxAphgOd9aKHHs8xKRc6YiuJmqw5XVWLePXkXgrum7vzmuEMaLD8ubrPv9OZ9DI8qyXnWhONSPdaYzF8bRKGQLA1/6OvaK7CPH8/a/gL/IzgJwHLngiHJ/sBwrweX+gp7dKW9SeYzS9ojphYwMDlNMju5i2fGZQO862tBx0=
file:
- pegnetd-darwin-10.6-amd64
- pegnetd-linux-amd64
- pegnetd-windows-4.0-amd64.exe
on:
# repo: pegnet/pegnetd
tags: true
condition: $TRAVIS_OS_NAME = linux
46 changes: 43 additions & 3 deletions cmd/root.go
Expand Up @@ -84,6 +84,7 @@ func always(cmd *cobra.Command, args []string) {
node.PegnetActivation = uint32(act)
node.GradingV2Activation = uint32(act)
node.TransactionConversionActivation = uint32(act)
node.PEGPricingActivation = uint32(act)
common.ActivationHeights[common.MainNetwork] = int64(act)
common.ActivationHeights[common.TestNetwork] = int64(act)
common.GradingHeights[common.MainNetwork] = func(height int64) uint8 { return 2 }
Expand Down Expand Up @@ -134,11 +135,50 @@ func always(cmd *cobra.Command, args []string) {
// ReadConfig can be put as a PreRun for a command that uses the config file
func ReadConfig(cmd *cobra.Command, args []string) {
err := viper.ReadInConfig()
if err != nil {
log.WithError(err).Error("failed to load config")
os.Exit(1)

// If no config is found, we will attempt to make one
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
// No config found? We will write the default config for the user
// If the custom config path is set, then we should not write a new config.
if custom, _ := cmd.Flags().GetString("config"); custom == "" {
home, err := os.UserHomeDir()
if err != nil {
log.WithError(err).Fatal("failed to create config path")
}

// Create the pegnetd directory if it is not already
err = os.MkdirAll(filepath.Join(home, ".pegnetd"), 0777)
if err != nil {
log.WithError(err).Fatal("failed to create config path")
}

configpath := filepath.Join(home, ".pegnetd", "pegnetd-conf.toml")
_, err = os.Stat(configpath)
if os.IsExist(err) { // Double check a file does not already exist. Don't overwrite a config
log.WithField("path", configpath).Fatal("config exists, but unable to read")
}

// Attempt to write a new config file
err = viper.WriteConfigAs(configpath)
if err != nil {
log.WithField("path", configpath).WithError(err).Fatal("failed to create config")
}
// Inform the user we made a config
log.WithField("path", configpath).Infof("no config file, one was created")

// Try to read it again
err = viper.ReadInConfig()
if err != nil {
log.WithError(err).Fatal("failed to load config")
}
}
} else if err != nil {
log.WithError(err).Fatal("failed to load config")
}

// Indicate which config was used
log.Infof("Using config from %s", viper.ConfigFileUsed())

initLogger()
}

Expand Down
2 changes: 1 addition & 1 deletion fat/fat2/transactionbatch.go
Expand Up @@ -137,7 +137,7 @@ func (t TransactionBatch) ValidExtIDs() error {
includedRCDHashes[t.FAAddress(i)] = struct{}{}
}
// Ensure that for all unique inputs there is a corresponding RCD in the ExtIDs
for address, _ := range uniqueInputs {
for address := range uniqueInputs {
if _, ok := includedRCDHashes[address]; !ok {
return fmt.Errorf("invalid RCDs")
}
Expand Down
2 changes: 1 addition & 1 deletion main.go
Expand Up @@ -5,4 +5,4 @@ import "github.com/pegnet/pegnetd/cmd"
// Launch the daemon from the cobra cli
func main() {
cmd.Execute()
}
}
3 changes: 3 additions & 0 deletions node/node.go
Expand Up @@ -22,6 +22,9 @@ var GradingV2Activation uint32 = 210330
// Target Activation Height is Oct 7, 2019 15 UTC
var TransactionConversionActivation uint32 = 213237

// Estimated to be Oct 14 2019, 15:00:00 UTC
var PEGPricingActivation uint32 = 214287

type Pegnetd struct {
FactomClient *factom.Client
Config *viper.Viper
Expand Down
5 changes: 2 additions & 3 deletions node/pegnet/addresses.go
Expand Up @@ -266,11 +266,10 @@ func (p *Pegnet) SelectIssuances() (map[fat2.PTicker]uint64, error) {
var sb strings.Builder
for i := fat2.PTickerInvalid + 1; i < fat2.PTickerMax-1; i++ {
tickerLower := strings.ToLower(i.String())
sb.WriteString(fmt.Sprintf("SUM(%s_balance), ", tickerLower))
sb.WriteString(fmt.Sprintf("IFNULL(SUM(%s_balance), 0), ", tickerLower))
}
tickerLower := strings.ToLower((fat2.PTickerMax - 1).String())
sb.WriteString(fmt.Sprintf("SUM(%s_balance) ", tickerLower))

sb.WriteString(fmt.Sprintf("IFNULL(SUM(%s_balance), 0) ", tickerLower))
err := p.DB.QueryRow(fmt.Sprintf(queryFmt, sb.String())).Scan(
&issuances[fat2.PTickerPEG],
&issuances[fat2.PTickerUSD],
Expand Down
54 changes: 46 additions & 8 deletions node/pegnet/grading.go
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/binary"
"encoding/json"
"fmt"
"math/big"

"github.com/Factom-Asset-Tokens/factom"
"github.com/pegnet/pegnet/modules/grader"
Expand Down Expand Up @@ -50,22 +51,57 @@ const createTableRate = `CREATE TABLE IF NOT EXISTS "pn_rate" (
);
`

func (p *Pegnet) InsertRate(tx *sql.Tx, height uint32, rates []opr.AssetUint) error {
for _, r := range rates {
// TODO: Make this more robust? Check if this is the best place to do this
if r.Name != "PEG" {
r.Name = "p" + r.Name
func (p *Pegnet) insertRate(tx *sql.Tx, height uint32, tickerString string, rate uint64) error {
_, err := tx.Exec("INSERT INTO pn_rate (height, token, value) VALUES ($1, $2, $3)", height, tickerString, rate)
if err != nil {
return err
}
return nil
}

// InsertRates adds all asset rates as rows, computing the rate for PEG if necessary
func (p *Pegnet) InsertRates(tx *sql.Tx, height uint32, rates []opr.AssetUint, pricePEG bool) error {
for i := range rates {
if rates[i].Name == "PEG" {
continue
}
_, err := tx.Exec("INSERT INTO pn_rate (height, token, value) VALUES ($1, $2, $3)", height, r.Name, r.Value)
// Correct rates to use `pAsset`
rates[i].Name = "p" + rates[i].Name
err := p.insertRate(tx, height, rates[i].Name, rates[i].Value)
if err != nil {
return err
}
}
ratePEG := new(big.Int)
if pricePEG {
// PEG price = (total capitalization of all other assets) / (total supply of all other assets at height - 1)
issuance, err := p.SelectIssuances()
if err != nil {
return err
}
totalCapitalization := new(big.Int)
for _, r := range rates {
if r.Name == "PEG" {
continue
}

assetCapitalization := new(big.Int).Mul(new(big.Int).SetUint64(issuance[fat2.StringToTicker(r.Name)]), new(big.Int).SetUint64(r.Value))
totalCapitalization.Add(totalCapitalization, assetCapitalization)
}
if issuance[fat2.PTickerPEG] == 0 {
ratePEG.Set(totalCapitalization)
} else {
ratePEG.Div(totalCapitalization, new(big.Int).SetUint64(issuance[fat2.PTickerPEG]))
}
}
err := p.insertRate(tx, height, fat2.PTickerPEG.String(), ratePEG.Uint64())
if err != nil {
return err
}
return nil
}

func (p *Pegnet) InsertGradeBlock(tx *sql.Tx, eblock *factom.EBlock, graded grader.GradedBlock) error {

data, err := json.Marshal(graded.WinnersShortHashes())
if err != nil {
return err
Expand Down Expand Up @@ -168,7 +204,9 @@ func _extractAssets(rows *sql.Rows) (map[fat2.PTicker]uint64, error) {
if err := rows.Scan(&tickerName, &rateValue); err != nil {
return nil, err
}
assets[fat2.StringToTicker(tickerName)] = rateValue
if ticker := fat2.StringToTicker(tickerName); ticker != fat2.PTickerInvalid {
assets[ticker] = rateValue
}
}
return assets, nil
}
2 changes: 1 addition & 1 deletion node/pegnet/pegnet.go
Expand Up @@ -35,7 +35,7 @@ func (p *Pegnet) Init() error {
// TODO: Come up with actual migrations.
// until then, we can just bump this version number
// and make the database reset when we need to.
path += ".v2"
path += ".v3"

// Ensure the path exists
dir := filepath.Dir(path)
Expand Down
3 changes: 2 additions & 1 deletion node/sync.go
Expand Up @@ -168,7 +168,8 @@ func (d *Pegnetd) SyncBlock(ctx context.Context, tx *sql.Tx, height uint32) erro
}
winners := gradedBlock.Winners()
if 0 < len(winners) {
err = d.Pegnet.InsertRate(tx, height, winners[0].OPR.GetOrderedAssetsUint())
shouldPricePEG := PEGPricingActivation <= height
err = d.Pegnet.InsertRates(tx, height, winners[0].OPR.GetOrderedAssetsUint(), shouldPricePEG)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion srv/methods.go
Expand Up @@ -154,7 +154,7 @@ func (s *APIServer) getPegnetBalances(data json.RawMessage) interface{} {
}

type ResultGetIssuance struct {
SyncStatus ResultGetSyncStatus `json:"sync-status"`
SyncStatus ResultGetSyncStatus `json:"syncstatus"`
Issuance ResultPegnetTickerMap `json:"issuance"`
}

Expand Down
17 changes: 17 additions & 0 deletions xgo/Dockerfile
@@ -0,0 +1,17 @@
# Go cross compiler (xgo): Go 1.11
# Copyright (c) 2018 Péter Szilágyi. All rights reserved.
#
# Released under the MIT license.

FROM karalabe/xgo-base

MAINTAINER Péter Szilágyi <peterke@gmail.com>

# Configure the root Go distribution and bootstrap based on it
ENV GO_VERSION 1131

RUN \
export ROOT_DIST=https://storage.googleapis.com/golang/go1.13.1.linux-amd64.tar.gz && \
export ROOT_DIST_SHA=94f874037b82ea5353f4061e543681a0e79657f787437974214629af8407d124 && \
\
$BOOTSTRAP_PURE
11 changes: 11 additions & 0 deletions xgo/README.md
@@ -0,0 +1,11 @@
# Using xgo

xgo is a cross compile tool that works with cgo. Since we use a sqlite library that includes cgo, the normal cross compile method does not work. The xgo Dockerfile in this directory will accomplish the cross compile.

If you use the Dockerfile in this directory:

```
docker build --tag xgo-builder .
xgo -image xgo-builder --targets=windows/amd64,darwin/amd64,linux/amd64 .
```

0 comments on commit c39b409

Please sign in to comment.