Skip to content

Commit

Permalink
RIDE v4 and Waves Protocol 1.2 (#366)
Browse files Browse the repository at this point in the history
Fully reimplemented RIDE evaluator.
Three versions of script estimators were implemented.
Code generation for RIDE function families.
RIDE Support of Groth16 verify functions.

* Import fixed, BlockV5 activation fixed
* PoS fixed. StringEntry function fixed.
* Stagenet fixed
* Fixed calcuation of state hash for DeleteDataEntry
* DataEntries fixes
* Fixed ExchangeTransaction fees validation
* New TestNet nodes
* Correct testnet peers
* Package rename
* Groth16 wrappers generators added
  • Loading branch information
alexeykiselev authored Oct 12, 2020
1 parent 4337fdc commit 73038c0
Show file tree
Hide file tree
Showing 122 changed files with 20,661 additions and 14,097 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ vendor:
go mod vendor

vetcheck:
go list ./... | grep -v bn254 | xargs go vet -v
go list ./... | grep -v bn254 | xargs go vet
golangci-lint run --skip-dirs pkg/crypto/internal/groth16/bn256/utils/bn254

build-chaincmp-linux:
Expand Down
32 changes: 16 additions & 16 deletions cmd/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ var (

var defaultPeers = map[string]string{
"mainnet": "35.156.19.4:6868,52.50.69.247:6868,52.52.46.76:6868,52.57.147.71:6868,52.214.55.18:6868,54.176.190.226:6868",
"testnet": "52.51.92.182:6863,52.231.205.53:6863,52.30.47.67:6863,52.28.66.217:6863",
"testnet": "159.69.126.149:6863,94.130.105.239:6863,159.69.126.153:6863,94.130.172.201:6863",
"stagenet": "217.100.219.251:6861",
}

Expand Down Expand Up @@ -243,7 +243,7 @@ func main() {
params.ProvideExtendedApi = *serveExtendedApi
params.BuildStateHashes = *buildStateHashes
params.Time = ntptm
state, err := state.NewState(path, params, cfg)
st, err := state.NewState(path, params, cfg)
if err != nil {
zap.S().Error(err)
cancel()
Expand All @@ -257,15 +257,15 @@ func main() {
return
}

features, err = miner.ValidateFeatures(state, features)
features, err = miner.ValidateFeatures(st, features)
if err != nil {
cancel()
zap.S().Error(err)
return
}

// Check if we need to start serving extended API right now.
if err := node.MaybeEnableExtendedApi(state, ntptm); err != nil {
if err := node.MaybeEnableExtendedApi(st, ntptm); err != nil {
zap.S().Error(err)
cancel()
return
Expand All @@ -280,7 +280,7 @@ func main() {
mb := 1024 * 1014
pool := bytespool.NewBytesPool(64, mb+(mb/2))

utx := utxpool.New(uint64(1024*mb), utxpool.NewValidator(state, ntptm, outdatePeriodSeconds*1000), cfg)
utx := utxpool.New(uint64(1024*mb), utxpool.NewValidator(st, ntptm, outdatePeriodSeconds*1000), cfg)

parent := peer.NewParent()

Expand All @@ -301,7 +301,7 @@ func main() {
go peerManager.Run(ctx)

var sched Scheduler = scheduler.NewScheduler(
state,
st,
wal,
cfg,
ntptm,
Expand All @@ -313,8 +313,8 @@ func main() {
}
blockApplier := blocks_applier.NewBlocksApplier()

services := services.Services{
State: state,
svs := services.Services{
State: st,
Peers: peerManager,
Scheduler: sched,
BlocksApplier: blockApplier,
Expand All @@ -328,12 +328,12 @@ func main() {
MinPeersMining: *minPeersMining,
}

mine := miner.NewMicroblockMiner(services, features, reward, maxTransactionTimeForwardOffset)
mine := miner.NewMicroblockMiner(svs, features, reward, maxTransactionTimeForwardOffset)
peerManager.SetConnectPeers(!*disableOutgoingConnections)
go miner.Run(ctx, mine, sched, services.InternalChannel)
go miner.Run(ctx, mine, sched, svs.InternalChannel)

n := node.NewNode(services, declAddr, bindAddr, proto.NewTimestampFromUSeconds(outdatePeriodSeconds))
go n.Run(ctx, parent, services.InternalChannel)
n := node.NewNode(svs, declAddr, bindAddr, proto.NewTimestampFromUSeconds(outdatePeriodSeconds))
go n.Run(ctx, parent, svs.InternalChannel)

go sched.Reschedule()

Expand All @@ -344,14 +344,14 @@ func main() {
}
}

app, err := api.NewApp(*apiKey, sched, services)
app, err := api.NewApp(*apiKey, sched, svs)
if err != nil {
zap.S().Error(err)
cancel()
return
}

webApi := api.NewNodeApi(app, state, n)
webApi := api.NewNodeApi(app, st, n)
go func() {
err := api.Run(ctx, conf.HttpAddr, webApi)
if err != nil {
Expand All @@ -360,7 +360,7 @@ func main() {
}()

if *enableGrpcApi {
grpcServer, err := server.NewServer(services)
grpcServer, err := server.NewServer(svs)
if err != nil {
zap.S().Errorf("Failed to create gRPC server: %v", err)
}
Expand Down Expand Up @@ -406,7 +406,7 @@ func applyIntegrationSettings(blockchainSettings *settings.BlockchainSettings) *
for _, t := range blockchainSettings.Genesis.Transactions {
t.(*proto.Genesis).Timestamp = uint64(*integrationGenesisTimestamp)
}
blockchainSettings.AddressSchemeCharacter = proto.Scheme((*integrationAddressSchemeCharacter)[0])
blockchainSettings.AddressSchemeCharacter = (*integrationAddressSchemeCharacter)[0]
blockchainSettings.AverageBlockDelaySeconds = blockchainSettings.AverageBlockDelaySeconds / 2
blockchainSettings.MinUpdateAssetInfoInterval = uint64(*integrationMinAssetInfoUpdateInterval)

Expand Down
271 changes: 271 additions & 0 deletions cmd/statehash/statehash.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
package main

import (
"context"
"errors"
"flag"
"fmt"
"net/http"
"net/url"
"os"
"runtime"
"strings"

"github.com/wavesplatform/gowaves/pkg/client"
"github.com/wavesplatform/gowaves/pkg/proto"
"github.com/wavesplatform/gowaves/pkg/settings"
"github.com/wavesplatform/gowaves/pkg/state"
"github.com/wavesplatform/gowaves/pkg/util/common"
"go.uber.org/zap"
)

const (
MB = 1024 * 1024
)

var (
version = "v0.0.0"
)

func main() {
err := run()
if err != nil {
os.Exit(1)
}
}

func run() error {
var (
node string
statePath string
blockchainType string
height uint64
extendedAPI bool
compare bool
search bool
showHelp bool
showVersion bool
)

common.SetupLogger("INFO")

flag.StringVar(&node, "node", "", "Path to node's state folder")
flag.StringVar(&statePath, "state-path", "", "Path to node's state folder")
flag.StringVar(&blockchainType, "blockchain-type", "mainnet", "Blockchain type mainnet/testnet/stagenet, default value is mainnet")
flag.Uint64Var(&height, "at-height", 0, "Height to get state hash at, defaults to the top most value")
flag.BoolVar(&extendedAPI, "extended-api", false, "Open state with extended API")
flag.BoolVar(&compare, "compare", false, "Compare the state hash with the node's state hash at the same height")
flag.BoolVar(&search, "search", false, "Search for the topmost equal state hashes")
flag.BoolVar(&showHelp, "help", false, "Show usage information and exit")
flag.BoolVar(&showVersion, "version", false, "Print version information and quit")
flag.Parse()

if showHelp {
showUsage()
return nil
}
if showVersion {
fmt.Printf("Waves RIDE Appraiser %s\n", version)
return nil
}

if search {
compare = true
}

if statePath == "" || len(strings.Fields(statePath)) > 1 {
zap.S().Errorf("Invalid path to state '%s'", statePath)
return errors.New("invalid state path")
}

ss, err := settings.BlockchainSettingsByTypeName(blockchainType)
if err != nil {
zap.S().Errorf("Failed to load blockchain settings: %v", err)
return err
}

params := state.DefaultStateParams()
params.VerificationGoroutinesNum = 2 * runtime.NumCPU()
params.DbParams.WriteBuffer = 16 * MB
params.StoreExtendedApiData = extendedAPI
params.BuildStateHashes = true
params.ProvideExtendedApi = false
st, err := state.NewState(statePath, params, ss)
if err != nil {
zap.S().Errorf("Failed to open state at '%s': %v", statePath, err)
return err
}
defer func() {
if err := st.Close(); err != nil {
zap.S().Fatalf("Failed to close State: %v", err)
}
}()

var c *client.Client
if compare {
if node == "" || len(strings.Fields(node)) > 1 {
zap.S().Errorf("Invalid node's URL '%s'", node)
return errors.New("invalid node")
}
node, err := checkAndUpdateURL(node)
if err != nil {
zap.S().Errorf("Incorrect node's URL: %s", err.Error())
return err
}
c, err = client.NewClient(client.Options{BaseUrl: node, Client: &http.Client{}})
if err != nil {
zap.S().Errorf("Failed to create client for URL '%s': %s", node, err)
return err
}
rsh, err := getRemoteStateHash(c, 1)
if err != nil {
zap.S().Errorf("Failed to get remote state hash at height 1: %v", err)
return err
}
lsh, err := st.StateHashAtHeight(1)
if err != nil {
zap.S().Errorf("Failed to get local state hash at 1: %v", err)
return err

}
_, err = compareStateHashes(lsh, rsh)
if err != nil {
zap.S().Errorf("State hashes at height 1 are different: %v", err)
return err
}
}

if height == 0 {
h, err := st.Height()
if err != nil {
zap.S().Errorf("Failed to get current blockchain height: %v", err)
return err
}
height = h
}
lsh, err := st.StateHashAtHeight(height)
if err != nil {
zap.S().Errorf("Failed to get state hash at %d: %v", height, err)
return err
}
zap.S().Infof("State hash at height %d:\n%s", height, stateHashToString(lsh))
if compare {
ok, rsh, err := compareWithRemote(lsh, c, height)
if err != nil {
zap.S().Errorf("Failed to compare: %v", err)
return err
}
if !ok {
zap.S().Warnf("[NOT OK] State hashes are different")
zap.S().Infof("Remote state hash at height %d:\n%s", height, stateHashToString(rsh))
if search {
h, err := findLastEqualStateHashes(c, st, height)
if err != nil {
zap.S().Errorf("Failed to find equal hashes: %v", err)
return err
}
zap.S().Infof("State hashes are equal at height %d", h)
lsh, err = st.StateHashAtHeight(h + 1)
if err != nil {
zap.S().Errorf("Failed to get state hash at %d: %v", h+1, err)
return err
}
zap.S().Infof("Local state hash at height %d:\n%s", h+1, stateHashToString(lsh))
rsh, err = getRemoteStateHash(c, h+1)
if err != nil {
zap.S().Errorf("Failed to get remote state hash at height 1: %v", err)
return err
}
zap.S().Infof("Remote state hash at height %d:\n%s", h+1, stateHashToString(rsh))
}
return nil
}
zap.S().Info("[OK] State hash is equal to remote state hash at the same height")
}
return nil
}

func findLastEqualStateHashes(c *client.Client, st state.State, stop uint64) (uint64, error) {
var err error
var r uint64
var lsh, rsh *proto.StateHash
var start uint64 = 1
for start <= stop {
middle := (start + stop) / 2
lsh, err = st.StateHashAtHeight(middle)
if err != nil {
return middle, err
}
rsh, err = getRemoteStateHash(c, middle)
if err != nil {
return middle, err
}
ok, err := compareStateHashes(lsh, rsh)
if err != nil {
return middle, err
}
if !ok {
stop = middle - 1
r = stop
} else {
start = middle + 1
r = middle
}
}
return r, nil
}

func stateHashToString(sh *proto.StateHash) string {
js, err := sh.MarshalJSON()
if err != nil {
zap.S().Fatalf("Failed to render state hash to text: %v", err)
}
return string(js)
}

func compareStateHashes(sh1, sh2 *proto.StateHash) (bool, error) {
if sh1.BlockID != sh2.BlockID {
return false, fmt.Errorf("different block IDs: '%s' != '%s'", sh1.BlockID.String(), sh2.BlockID.String())
}
return sh1.SumHash == sh2.SumHash, nil
}

func compareWithRemote(sh *proto.StateHash, c *client.Client, h uint64) (bool, *proto.StateHash, error) {
rsh, err := getRemoteStateHash(c, h)
if err != nil {
return false, nil, err
}
ok, err := compareStateHashes(sh, rsh)
return ok, rsh, err
}

func getRemoteStateHash(c *client.Client, h uint64) (*proto.StateHash, error) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
sh, _, err := c.Debug.StateHash(ctx, h)
return sh, err
}
func showUsage() {
_, _ = fmt.Fprintf(os.Stderr, "\nUsage of statehash %s\n", version)
flag.PrintDefaults()
}

func checkAndUpdateURL(s string) (string, error) {
var u *url.URL
var err error
if strings.Contains(s, "//") {
u, err = url.Parse(s)
} else {
u, err = url.Parse("//" + s)
}
if err != nil {
return "", fmt.Errorf("failed to parse URL '%s': %v", s, err)
}
if u.Scheme == "" {
u.Scheme = "http"
}
if u.Scheme != "http" && u.Scheme != "https" {
return "", fmt.Errorf("unsupported URL scheme '%s'", u.Scheme)
}
return u.String(), nil
}
Loading

0 comments on commit 73038c0

Please sign in to comment.