From 63b159c27742514a6dec803055c088f90a50ce24 Mon Sep 17 00:00:00 2001 From: esuwu Date: Thu, 13 Jun 2024 22:54:17 -0500 Subject: [PATCH 01/50] Initial draft --- cmd/node/node.go | 101 +++++++++++++++++-------------- cmd/updates/nuts_publisher.go | 43 +++++++++++++ cmd/updates/nuts_subscriber.go | 26 ++++++++ cmd/updates/topics.go | 10 +++ go.mod | 7 ++- go.sum | 15 ++--- pkg/state/transaction_handler.go | 3 + 7 files changed, 150 insertions(+), 55 deletions(-) create mode 100644 cmd/updates/nuts_publisher.go create mode 100644 cmd/updates/nuts_subscriber.go create mode 100644 cmd/updates/topics.go diff --git a/cmd/node/node.go b/cmd/node/node.go index 844a70962..60ea82471 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -63,51 +63,52 @@ var defaultPeers = map[string]string{ } type config struct { - logLevel zapcore.Level - logDevelopment bool - logNetwork bool - logNetworkData bool - logFSM bool - statePath string - blockchainType string - peerAddresses string - declAddr string - nodeName string - cfgPath string - apiAddr string - apiKey string - apiMaxConnections int - rateLimiterOptions string - grpcAddr string - grpcAPIMaxConnections int - enableMetaMaskAPI bool - enableMetaMaskAPILog bool - enableGrpcAPI bool - blackListResidenceTime time.Duration - buildExtendedAPI bool - serveExtendedAPI bool - buildStateHashes bool - bindAddress string - disableOutgoingConnections bool - minerVoteFeatures string - disableBloomFilter bool - reward string - obsolescencePeriod time.Duration - walletPath string - walletPassword string - limitAllConnections uint - minPeersMining int - disableMiner bool - profiler bool - prometheus string - metricsID int - metricsURL string - dropPeers bool - dbFileDescriptors int - newConnectionsLimit int - disableNTP bool - microblockInterval time.Duration - enableLightMode bool + logLevel zapcore.Level + logDevelopment bool + logNetwork bool + logNetworkData bool + logFSM bool + statePath string + blockchainType string + peerAddresses string + declAddr string + nodeName string + cfgPath string + apiAddr string + apiKey string + apiMaxConnections int + rateLimiterOptions string + grpcAddr string + grpcAPIMaxConnections int + enableMetaMaskAPI bool + enableMetaMaskAPILog bool + enableGrpcAPI bool + blackListResidenceTime time.Duration + buildExtendedAPI bool + serveExtendedAPI bool + buildStateHashes bool + bindAddress string + disableOutgoingConnections bool + minerVoteFeatures string + disableBloomFilter bool + reward string + obsolescencePeriod time.Duration + walletPath string + walletPassword string + limitAllConnections uint + minPeersMining int + disableMiner bool + profiler bool + prometheus string + metricsID int + metricsURL string + dropPeers bool + dbFileDescriptors int + newConnectionsLimit int + disableNTP bool + microblockInterval time.Duration + enableLightMode bool + enableBlockchainUpdatesPlugin bool } func (c *config) logParameters() { @@ -144,6 +145,7 @@ func (c *config) logParameters() { zap.S().Debugf("disable-ntp: %t", c.disableNTP) zap.S().Debugf("microblock-interval: %s", c.microblockInterval) zap.S().Debugf("enable-light-mode: %t", c.enableLightMode) + zap.S().Debugf("enable-blockchain-updates-plugin: %t", c.enableBlockchainUpdatesPlugin) } func (c *config) parse() { @@ -237,6 +239,9 @@ func (c *config) parse() { "Interval between microblocks.") flag.BoolVar(&c.enableLightMode, "enable-light-mode", false, "Start node in light mode") + + flag.BoolVar(&c.enableBlockchainUpdatesPlugin, "enable-blockchain-updates", false, + "Turn on blockchain updates plugin") flag.Parse() c.logLevel = *l } @@ -385,6 +390,12 @@ func main() { params.Time = ntpTime params.DbParams.BloomFilterParams.Disable = nc.disableBloomFilter + if nc.enableBlockchainUpdatesPlugin { + // updatesChannel := make(chan interface{}) + // runBlockchainUpdatesPublisher(updatesChannel) + } + + // Send updatesChannel into BlockchainSettings. Write updates into this channel st, err := state.NewState(path, true, params, cfg, nc.enableLightMode) if err != nil { zap.S().Errorf("Failed to initialize node's state: %v", err) diff --git a/cmd/updates/nuts_publisher.go b/cmd/updates/nuts_publisher.go new file mode 100644 index 000000000..75ed3e08d --- /dev/null +++ b/cmd/updates/nuts_publisher.go @@ -0,0 +1,43 @@ +package updates + +import ( + "context" + "fmt" + "github.com/nats-io/nats.go" + "log" + "os" + "os/signal" + "syscall" +) + +func runBlockchainUpdatesPublisher(updatesChannel chan interface{}) { + nc, err := nats.Connect(nats.DefaultURL) + if err != nil { + log.Fatal(err) + } + defer nc.Close() + + ctx, done := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) + defer done() + + func(ctx context.Context, updatesChannel chan interface{}) { + for { + select { + case <-updatesChannel: + var msg string + // Publish blockchain updates + topic := block_updates + err := nc.Publish(topic, []byte(msg)) + if err != nil { + log.Printf("failed to publish message %s on topic %s", msg, topic) + } + fmt.Printf("Published: %s\n", msg) + + case <-ctx.Done(): + return + } + } + }(ctx, updatesChannel) + <-ctx.Done() + +} diff --git a/cmd/updates/nuts_subscriber.go b/cmd/updates/nuts_subscriber.go new file mode 100644 index 000000000..feca5d837 --- /dev/null +++ b/cmd/updates/nuts_subscriber.go @@ -0,0 +1,26 @@ +package updates + +import ( + "github.com/nats-io/nats.go" + "log" + "runtime" +) + +func main() { + // Connect to a NATS server + nc, err := nats.Connect(nats.DefaultURL) + if err != nil { + log.Fatal(err) + } + defer nc.Close() + + for _, topic := range topics { + _, err = nc.Subscribe(topic, func(msg *nats.Msg) { + log.Printf("Received on %s: %s\n", msg.Subject, string(msg.Data)) + }) + if err != nil { + log.Fatal(err) + } + } + runtime.Goexit() +} diff --git a/cmd/updates/topics.go b/cmd/updates/topics.go new file mode 100644 index 000000000..b2326899f --- /dev/null +++ b/cmd/updates/topics.go @@ -0,0 +1,10 @@ +package updates + +/* topics */ +const ( + block_updates = "block_topic" + microblock_updates = "microblock_topic" + contract_uptdates = "contract_topi" +) + +var topics = []string{block_updates, microblock_updates, contract_uptdates} diff --git a/go.mod b/go.mod index ecdb35332..e6b6ff198 100644 --- a/go.mod +++ b/go.mod @@ -22,12 +22,12 @@ require ( github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab github.com/jinzhu/copier v0.4.0 github.com/mr-tron/base58 v1.2.0 + github.com/nats-io/nats.go v1.35.0 github.com/ory/dockertest/v3 v3.10.0 github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.19.1 github.com/qmuntal/stateless v1.7.0 - github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c github.com/semrush/zenrpc/v2 v2.1.1 github.com/spf13/afero v1.11.0 github.com/spf13/pflag v1.0.5 @@ -50,7 +50,6 @@ require ( golang.org/x/sys v0.21.0 google.golang.org/grpc v1.64.0 google.golang.org/protobuf v1.34.2 - gopkg.in/natefinch/lumberjack.v2 v2.2.1 moul.io/zapfilter v1.7.0 ) @@ -66,7 +65,6 @@ require ( github.com/containerd/continuity v0.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect - github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 // indirect github.com/docker/cli v20.10.17+incompatible // indirect github.com/docker/docker v24.0.9+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect @@ -82,11 +80,14 @@ require ( github.com/imdario/mergo v0.3.12 // indirect github.com/ingonyama-zk/icicle v0.0.0-20230928131117-97f0079e5c71 // indirect github.com/ingonyama-zk/iciclegnark v0.1.0 // indirect + github.com/klauspost/compress v1.17.2 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect + github.com/nats-io/nkeys v0.4.7 // indirect + github.com/nats-io/nuid v1.0.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.2 // indirect github.com/opencontainers/runc v1.1.12 // indirect diff --git a/go.sum b/go.sum index 2fbff26a5..9e5a7256f 100644 --- a/go.sum +++ b/go.sum @@ -56,8 +56,6 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= -github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 h1:BS21ZUJ/B5X2UVUbczfmdWH7GapPWAhxcMsDnjJTU1E= -github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32PaqRpvoEkKBy5M= github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= @@ -150,6 +148,8 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= +github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -185,6 +185,12 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nats-io/nats.go v1.35.0 h1:XFNqNM7v5B+MQMKqVGAyHwYhyKb48jrenXNxIU20ULk= +github.com/nats-io/nats.go v1.35.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= +github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= +github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= +github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -240,8 +246,6 @@ github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUz github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= -github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c h1:pqy40B3MQWYrza7YZXOXgl0Nf0QGFqrOC0BKae1UNAA= -github.com/seiflotfy/cuckoofilter v0.0.0-20201222105146-bc6005554a0c/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg= github.com/semrush/zenrpc/v2 v2.1.1 h1:LhtvR6tkqwPUXbIfM2Qc0ouKig8h8WFcohEZ//LgG0I= github.com/semrush/zenrpc/v2 v2.1.1/go.mod h1:+o94fyVC+TvYuT5ULLyBmql+ezicEFKtsieIXSeWBqg= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= @@ -454,8 +458,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= -gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -467,7 +469,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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= diff --git a/pkg/state/transaction_handler.go b/pkg/state/transaction_handler.go index a3964ba47..3c2cf4b62 100644 --- a/pkg/state/transaction_handler.go +++ b/pkg/state/transaction_handler.go @@ -264,6 +264,9 @@ func (h *transactionHandler) performTx( if err := snapshot.Apply(h.sa, tx, validatingUTX); err != nil { return txSnapshot{}, errors.Wrap(err, "failed to apply transaction snapshot") } + + // here + return snapshot, nil } From 69e9dbd2eadd59ae4ed6c03820bd1f2347a9013d Mon Sep 17 00:00:00 2001 From: esuwu Date: Thu, 13 Jun 2024 22:55:36 -0500 Subject: [PATCH 02/50] Changed a comment --- pkg/state/transaction_handler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/state/transaction_handler.go b/pkg/state/transaction_handler.go index 3c2cf4b62..0fc973769 100644 --- a/pkg/state/transaction_handler.go +++ b/pkg/state/transaction_handler.go @@ -265,7 +265,7 @@ func (h *transactionHandler) performTx( return txSnapshot{}, errors.Wrap(err, "failed to apply transaction snapshot") } - // here + // write updates into the updatesChannel here return snapshot, nil } From b35bea166f0757aaefd3b8e5894186c3ff70ee72 Mon Sep 17 00:00:00 2001 From: esuwu Date: Thu, 13 Jun 2024 22:57:57 -0500 Subject: [PATCH 03/50] moved a file --- cmd/updates/nuts_subscriber.go | 3 ++- {cmd/updates => pkg/blockchainupdates}/nuts_publisher.go | 2 +- {cmd/updates => pkg/blockchainupdates}/topics.go | 6 +++--- 3 files changed, 6 insertions(+), 5 deletions(-) rename {cmd/updates => pkg/blockchainupdates}/nuts_publisher.go (96%) rename {cmd/updates => pkg/blockchainupdates}/topics.go (57%) diff --git a/cmd/updates/nuts_subscriber.go b/cmd/updates/nuts_subscriber.go index feca5d837..302aaeb92 100644 --- a/cmd/updates/nuts_subscriber.go +++ b/cmd/updates/nuts_subscriber.go @@ -2,6 +2,7 @@ package updates import ( "github.com/nats-io/nats.go" + "github.com/wavesplatform/gowaves/pkg/blockchainupdates" "log" "runtime" ) @@ -14,7 +15,7 @@ func main() { } defer nc.Close() - for _, topic := range topics { + for _, topic := range blockchainupdates.Topics { _, err = nc.Subscribe(topic, func(msg *nats.Msg) { log.Printf("Received on %s: %s\n", msg.Subject, string(msg.Data)) }) diff --git a/cmd/updates/nuts_publisher.go b/pkg/blockchainupdates/nuts_publisher.go similarity index 96% rename from cmd/updates/nuts_publisher.go rename to pkg/blockchainupdates/nuts_publisher.go index 75ed3e08d..cd7cca924 100644 --- a/cmd/updates/nuts_publisher.go +++ b/pkg/blockchainupdates/nuts_publisher.go @@ -1,4 +1,4 @@ -package updates +package blockchainupdates import ( "context" diff --git a/cmd/updates/topics.go b/pkg/blockchainupdates/topics.go similarity index 57% rename from cmd/updates/topics.go rename to pkg/blockchainupdates/topics.go index b2326899f..7755bf3c7 100644 --- a/cmd/updates/topics.go +++ b/pkg/blockchainupdates/topics.go @@ -1,10 +1,10 @@ -package updates +package blockchainupdates -/* topics */ +/* Topics */ const ( block_updates = "block_topic" microblock_updates = "microblock_topic" contract_uptdates = "contract_topi" ) -var topics = []string{block_updates, microblock_updates, contract_uptdates} +var Topics = []string{block_updates, microblock_updates, contract_uptdates} From 27494adc9fdc7f4119f4c7571add442c93e682df Mon Sep 17 00:00:00 2001 From: esuwu Date: Thu, 13 Jun 2024 22:59:51 -0500 Subject: [PATCH 04/50] rename a folder --- cmd/{updates => blockchainupdates}/nuts_subscriber.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename cmd/{updates => blockchainupdates}/nuts_subscriber.go (95%) diff --git a/cmd/updates/nuts_subscriber.go b/cmd/blockchainupdates/nuts_subscriber.go similarity index 95% rename from cmd/updates/nuts_subscriber.go rename to cmd/blockchainupdates/nuts_subscriber.go index 302aaeb92..c6bba0a28 100644 --- a/cmd/updates/nuts_subscriber.go +++ b/cmd/blockchainupdates/nuts_subscriber.go @@ -1,4 +1,4 @@ -package updates +package blockchainupdates import ( "github.com/nats-io/nats.go" From 983babc2848d64ab96d7f7339443dad66d5d00a5 Mon Sep 17 00:00:00 2001 From: esuwu Date: Thu, 20 Jun 2024 15:40:44 -0500 Subject: [PATCH 05/50] Sent the updates channel into block appplier --- cmd/importer/importer.go | 2 +- cmd/node/node.go | 15 ++++++++++--- cmd/rollback/main.go | 2 +- cmd/statehash/statehash.go | 2 +- pkg/blockchainupdates/nuts_publisher.go | 25 +++++++++++++++++++-- pkg/grpc/server/common_test.go | 4 ++-- pkg/state/address_transactions_test.go | 2 +- pkg/state/api.go | 3 ++- pkg/state/appender.go | 30 +++++++++++++++++++++++++ pkg/state/state.go | 3 ++- pkg/state/state_test.go | 16 ++++++------- 11 files changed, 83 insertions(+), 21 deletions(-) diff --git a/cmd/importer/importer.go b/cmd/importer/importer.go index 9255bc53e..76e036c65 100644 --- a/cmd/importer/importer.go +++ b/cmd/importer/importer.go @@ -174,7 +174,7 @@ func run() error { return err } - st, err := state.NewState(c.dataDirPath, false, c.params(fds), ss, false) + st, err := state.NewState(c.dataDirPath, false, c.params(fds), ss, false, nil) if err != nil { return fmt.Errorf("failed to create state: %w", err) } diff --git a/cmd/node/node.go b/cmd/node/node.go index 60ea82471..9d3f3f524 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -6,6 +6,7 @@ import ( "errors" "flag" "fmt" + "github.com/wavesplatform/gowaves/pkg/blockchainupdates" "math" "math/big" "net/http" @@ -390,13 +391,21 @@ func main() { params.Time = ntpTime params.DbParams.BloomFilterParams.Disable = nc.disableBloomFilter + var bUpdatesExtension *state.BlockchainUpdatesExtension if nc.enableBlockchainUpdatesPlugin { - // updatesChannel := make(chan interface{}) - // runBlockchainUpdatesPublisher(updatesChannel) + updatesChannel := make(chan blockchainupdates.BUpdatesInfo) + bUpdatesExtensionState := blockchainupdates.NewBUpdatesExtensionState() + + bUpdatesExtension = &state.BlockchainUpdatesExtension{ + EnableBlockchainUpdatesPlugin: true, + BUpdatesChannel: updatesChannel, + } + + bUpdatesExtensionState.RunBlockchainUpdatesPublisher(updatesChannel) } // Send updatesChannel into BlockchainSettings. Write updates into this channel - st, err := state.NewState(path, true, params, cfg, nc.enableLightMode) + st, err := state.NewState(path, true, params, cfg, nc.enableLightMode, bUpdatesExtension) if err != nil { zap.S().Errorf("Failed to initialize node's state: %v", err) return diff --git a/cmd/rollback/main.go b/cmd/rollback/main.go index 4116e6335..25a9b39c7 100644 --- a/cmd/rollback/main.go +++ b/cmd/rollback/main.go @@ -75,7 +75,7 @@ func main() { params.BuildStateHashes = *buildStateHashes params.StoreExtendedApiData = *buildExtendedAPI - s, err := state.NewState(*statePath, true, params, cfg, false) + s, err := state.NewState(*statePath, true, params, cfg, false, nil) if err != nil { zap.S().Error(err) return diff --git a/cmd/statehash/statehash.go b/cmd/statehash/statehash.go index 3c98d1188..0cffe4195 100644 --- a/cmd/statehash/statehash.go +++ b/cmd/statehash/statehash.go @@ -106,7 +106,7 @@ func run() error { params.BuildStateHashes = true params.ProvideExtendedApi = false - st, err := state.NewState(statePath, false, params, ss, false) + st, err := state.NewState(statePath, false, params, ss, false, nil) if err != nil { zap.S().Errorf("Failed to open state at '%s': %v", statePath, err) return err diff --git a/pkg/blockchainupdates/nuts_publisher.go b/pkg/blockchainupdates/nuts_publisher.go index cd7cca924..43e7b9aab 100644 --- a/pkg/blockchainupdates/nuts_publisher.go +++ b/pkg/blockchainupdates/nuts_publisher.go @@ -4,13 +4,34 @@ import ( "context" "fmt" "github.com/nats-io/nats.go" + "github.com/wavesplatform/gowaves/pkg/proto" "log" "os" "os/signal" "syscall" ) -func runBlockchainUpdatesPublisher(updatesChannel chan interface{}) { +type BUpdatesInfo struct { + Height uint64 + VRF proto.B58Bytes + BlockID proto.BlockID + BlockHeader *proto.BlockHeader +} + +type BUpdatesExtensionState struct { + currentState *BUpdatesInfo + previousState *BUpdatesInfo // this information is what was just published +} + +func NewBUpdatesExtensionState() *BUpdatesExtensionState { + return &BUpdatesExtensionState{} +} + +func (bu *BUpdatesExtensionState) hasStateChanged() { + +} + +func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(updatesChannel <-chan BUpdatesInfo) { nc, err := nats.Connect(nats.DefaultURL) if err != nil { log.Fatal(err) @@ -20,7 +41,7 @@ func runBlockchainUpdatesPublisher(updatesChannel chan interface{}) { ctx, done := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer done() - func(ctx context.Context, updatesChannel chan interface{}) { + func(ctx context.Context, updatesChannel <-chan BUpdatesInfo) { for { select { case <-updatesChannel: diff --git a/pkg/grpc/server/common_test.go b/pkg/grpc/server/common_test.go index effc572ed..e102a7b42 100644 --- a/pkg/grpc/server/common_test.go +++ b/pkg/grpc/server/common_test.go @@ -86,7 +86,7 @@ func stateWithCustomGenesis(t *testing.T, genesisPath string) state.State { // Activate data transactions. sets.PreactivatedFeatures = []int16{5} params := defaultStateParams() - st, err := state.NewState(dataDir, true, params, sets, false) + st, err := state.NewState(dataDir, true, params, sets, false, nil) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, st.Close()) @@ -120,7 +120,7 @@ func withAutoCancel(t *testing.T, ctx context.Context) context.Context { func newTestState(t *testing.T, amend bool, params state.StateParams, settings *settings.BlockchainSettings) state.State { dataDir := t.TempDir() - st, err := state.NewState(dataDir, amend, params, settings, false) + st, err := state.NewState(dataDir, amend, params, settings, false, nil) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, st.Close()) diff --git a/pkg/state/address_transactions_test.go b/pkg/state/address_transactions_test.go index cae6677ad..cd0771285 100644 --- a/pkg/state/address_transactions_test.go +++ b/pkg/state/address_transactions_test.go @@ -13,7 +13,7 @@ import ( func testIterImpl(t *testing.T, params StateParams) { dataDir := t.TempDir() - st, err := NewState(dataDir, true, params, settings.MainNetSettings, false) + st, err := NewState(dataDir, true, params, settings.MainNetSettings, false, nil) require.NoError(t, err) t.Cleanup(func() { diff --git a/pkg/state/api.go b/pkg/state/api.go index d7a02d49a..a521911af 100644 --- a/pkg/state/api.go +++ b/pkg/state/api.go @@ -221,8 +221,9 @@ func NewState( params StateParams, settings *settings.BlockchainSettings, enableLightNode bool, + bUpdatesExtension *BlockchainUpdatesExtension, ) (State, error) { - s, err := newStateManager(dataDir, amend, params, settings, enableLightNode) + s, err := newStateManager(dataDir, amend, params, settings, enableLightNode, bUpdatesExtension) if err != nil { return nil, errors.Wrap(err, "failed to create new state instance") } diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 71dfca60a..f97f53821 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -2,6 +2,7 @@ package state import ( "fmt" + "github.com/wavesplatform/gowaves/pkg/blockchainupdates" "github.com/mr-tron/base58/base58" "github.com/pkg/errors" @@ -54,6 +55,13 @@ type txAppender struct { // buildApiData flag indicates that additional data for API is built when // appending transactions. buildApiData bool + + bUpdatesExtension *BlockchainUpdatesExtension +} + +type BlockchainUpdatesExtension struct { + EnableBlockchainUpdatesPlugin bool + BUpdatesChannel chan<- blockchainupdates.BUpdatesInfo } func newTxAppender( @@ -64,6 +72,7 @@ func newTxAppender( stateDB *stateDB, atx *addressTransactions, snapshotApplier *blockSnapshotsApplier, + bUpdatesExtension *BlockchainUpdatesExtension, ) (*txAppender, error) { buildAPIData, err := stateDB.stateStoresApiData() if err != nil { @@ -112,6 +121,7 @@ func newTxAppender( diffApplier: diffApplier, buildApiData: buildAPIData, ethTxKindResolver: ethKindResolver, + bUpdatesExtension: bUpdatesExtension, }, nil } @@ -820,6 +830,15 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { if err != nil { return err } + + // write updates into the updatesChannel here + // TODO possibly run it in a goroutine? make sure goroutines run in order? + if a.bUpdatesExtension != nil { + if a.bUpdatesExtension.EnableBlockchainUpdatesPlugin { + a.updateBlockchainUpdateInfo(blockInfo, params.block) + } + } + // check whether the calculated snapshot state hash equals with the provided one if blockStateHash, present := params.block.GetStateHash(); present && blockStateHash != stateHash { return errors.Wrapf(errBlockSnapshotStateHashMismatch, "state hash mismatch; provided '%s', caluclated '%s'", @@ -840,6 +859,17 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { return a.blockDiffer.saveCurFeeDistr(params.block) } +func (a *txAppender) updateBlockchainUpdateInfo(blockInfo *proto.BlockInfo, blockHeader *proto.BlockHeader) { + bUpdatesInfo := blockchainupdates.BUpdatesInfo{ + Height: blockInfo.Height, + VRF: blockInfo.VRF, + BlockID: blockHeader.BlockID(), + BlockHeader: blockHeader, + } + + a.bUpdatesExtension.BUpdatesChannel <- bUpdatesInfo +} + func (a *txAppender) createCheckerInfo(params *appendBlockParams) (*checkerInfo, error) { rideV5Activated, err := a.stor.features.newestIsActivated(int16(settings.RideV5)) if err != nil { diff --git a/pkg/state/state.go b/pkg/state/state.go index d25a37e05..0c07d3988 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -497,6 +497,7 @@ func newStateManager( params StateParams, settings *settings.BlockchainSettings, enableLightNode bool, + bUpdatesExtension *BlockchainUpdatesExtension, ) (*stateManager, error) { if err := validateSettings(settings); err != nil { return nil, err @@ -562,7 +563,7 @@ func newStateManager( // Set fields which depend on state. // Consensus validator is needed to check block headers. snapshotApplier := newBlockSnapshotsApplier(nil, newSnapshotApplierStorages(stor, rw)) - appender, err := newTxAppender(state, rw, stor, settings, sdb, atx, &snapshotApplier) + appender, err := newTxAppender(state, rw, stor, settings, sdb, atx, &snapshotApplier, bUpdatesExtension) if err != nil { return nil, wrapErr(Other, err) } diff --git a/pkg/state/state_test.go b/pkg/state/state_test.go index 8b9954ebc..b18d2b24d 100644 --- a/pkg/state/state_test.go +++ b/pkg/state/state_test.go @@ -36,7 +36,7 @@ func bigFromStr(s string) *big.Int { func newTestState(t *testing.T, amend bool, params StateParams, settings *settings.BlockchainSettings) State { dataDir := t.TempDir() - m, err := NewState(dataDir, amend, params, settings, false) + m, err := NewState(dataDir, amend, params, settings, false, nil) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, m.Close(), "manager.Close() failed") @@ -46,7 +46,7 @@ func newTestState(t *testing.T, amend bool, params StateParams, settings *settin func newTestStateManager(t *testing.T, amend bool, params StateParams, settings *settings.BlockchainSettings) *stateManager { dataDir := t.TempDir() - m, err := newStateManager(dataDir, amend, params, settings, false) + m, err := newStateManager(dataDir, amend, params, settings, false, nil) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, m.Close(), "manager.Close() failed") @@ -57,7 +57,7 @@ func newTestStateManager(t *testing.T, amend bool, params StateParams, settings func TestHandleAmendFlag(t *testing.T) { dataDir := t.TempDir() // first open with false amend - manager, err := newStateManager(dataDir, false, DefaultTestingStateParams(), settings.MainNetSettings, false) + manager, err := newStateManager(dataDir, false, DefaultTestingStateParams(), settings.MainNetSettings, false, nil) assert.NoError(t, err, "newStateManager() failed") t.Cleanup(func() { assert.NoError(t, manager.Close(), "manager.Close() failed") @@ -66,18 +66,18 @@ func TestHandleAmendFlag(t *testing.T) { // open with true amend assert.NoError(t, manager.Close(), "manager.Close() failed") - manager, err = newStateManager(dataDir, true, DefaultTestingStateParams(), settings.MainNetSettings, false) + manager, err = newStateManager(dataDir, true, DefaultTestingStateParams(), settings.MainNetSettings, false, nil) assert.NoError(t, err, "newStateManager() failed") assert.True(t, manager.stor.hs.amend) // open with false amend again. Result amend should be true assert.NoError(t, manager.Close(), "manager.Close() failed") - manager, err = newStateManager(dataDir, false, DefaultTestingStateParams(), settings.MainNetSettings, false) + manager, err = newStateManager(dataDir, false, DefaultTestingStateParams(), settings.MainNetSettings, false, nil) assert.NoError(t, err, "newStateManager() failed") assert.True(t, manager.stor.hs.amend) // first open with true amend - newManager, err := newStateManager(t.TempDir(), true, DefaultTestingStateParams(), settings.MainNetSettings, false) + newManager, err := newStateManager(t.TempDir(), true, DefaultTestingStateParams(), settings.MainNetSettings, false, nil) assert.NoError(t, err, "newStateManager() failed") t.Cleanup(func() { assert.NoError(t, newManager.Close(), "newManager.Close() failed") @@ -376,7 +376,7 @@ func TestStateManager_TopBlock(t *testing.T) { blocksPath, err := blocksPath() assert.NoError(t, err) dataDir := t.TempDir() - manager, err := newStateManager(dataDir, true, DefaultTestingStateParams(), settings.MainNetSettings, false) + manager, err := newStateManager(dataDir, true, DefaultTestingStateParams(), settings.MainNetSettings, false, nil) assert.NoError(t, err, "newStateManager() failed") t.Cleanup(func() { @@ -410,7 +410,7 @@ func TestStateManager_TopBlock(t *testing.T) { // Test after closure. err = manager.Close() assert.NoError(t, err, "manager.Close() failed") - manager, err = newStateManager(dataDir, true, DefaultTestingStateParams(), settings.MainNetSettings, false) + manager, err = newStateManager(dataDir, true, DefaultTestingStateParams(), settings.MainNetSettings, false, nil) assert.NoError(t, err, "newStateManager() failed") assert.Equal(t, correct, manager.TopBlock()) } From 527289924bba54f262744454bfb708c078f44322 Mon Sep 17 00:00:00 2001 From: esuwu Date: Thu, 20 Jun 2024 15:42:28 -0500 Subject: [PATCH 06/50] Added some design comments --- pkg/blockchainupdates/nuts_publisher.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/blockchainupdates/nuts_publisher.go b/pkg/blockchainupdates/nuts_publisher.go index 43e7b9aab..af9153255 100644 --- a/pkg/blockchainupdates/nuts_publisher.go +++ b/pkg/blockchainupdates/nuts_publisher.go @@ -44,7 +44,14 @@ func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(updatesChannel < func(ctx context.Context, updatesChannel <-chan BUpdatesInfo) { for { select { - case <-updatesChannel: + case updates := <-updatesChannel: + // update current state + + // compare the current state to the previous state + + // if there is any diff, send the update + + fmt.Println(updates.Height) var msg string // Publish blockchain updates topic := block_updates From 4fef6e3b23eb5d9e73ac9cc003ef071f5615f1b7 Mon Sep 17 00:00:00 2001 From: esuwu Date: Thu, 20 Jun 2024 15:45:06 -0500 Subject: [PATCH 07/50] Context in the updates function --- cmd/node/node.go | 2 +- pkg/blockchainupdates/nuts_publisher.go | 10 +--------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/cmd/node/node.go b/cmd/node/node.go index 9d3f3f524..67678d765 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -401,7 +401,7 @@ func main() { BUpdatesChannel: updatesChannel, } - bUpdatesExtensionState.RunBlockchainUpdatesPublisher(updatesChannel) + bUpdatesExtensionState.RunBlockchainUpdatesPublisher(ctx, updatesChannel) } // Send updatesChannel into BlockchainSettings. Write updates into this channel diff --git a/pkg/blockchainupdates/nuts_publisher.go b/pkg/blockchainupdates/nuts_publisher.go index af9153255..89a69b0ff 100644 --- a/pkg/blockchainupdates/nuts_publisher.go +++ b/pkg/blockchainupdates/nuts_publisher.go @@ -6,9 +6,6 @@ import ( "github.com/nats-io/nats.go" "github.com/wavesplatform/gowaves/pkg/proto" "log" - "os" - "os/signal" - "syscall" ) type BUpdatesInfo struct { @@ -31,16 +28,13 @@ func (bu *BUpdatesExtensionState) hasStateChanged() { } -func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(updatesChannel <-chan BUpdatesInfo) { +func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(ctx context.Context, updatesChannel <-chan BUpdatesInfo) { nc, err := nats.Connect(nats.DefaultURL) if err != nil { log.Fatal(err) } defer nc.Close() - ctx, done := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) - defer done() - func(ctx context.Context, updatesChannel <-chan BUpdatesInfo) { for { select { @@ -66,6 +60,4 @@ func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(updatesChannel < } } }(ctx, updatesChannel) - <-ctx.Done() - } From 3cc00d5cf574bf2949c5be0936d8eec5d02cf253 Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 1 Jul 2024 18:23:04 -0500 Subject: [PATCH 08/50] Added protobuf --- Makefile | 2 + cmd/node/node.go | 10 +- .../waves/bupdates/blockchain_updates.pb.go | 198 +++++++++++ go.mod | 9 +- go.sum | 19 +- pkg/blockchainupdates/nuts_publisher.go | 38 +- pkg/blockchainupdates/nuts_server.go | 28 ++ .../waves/bupdates/blockchain_updates.pb.go | 198 +++++++++++ .../bupdates/blockchain_updates_vtproto.pb.go | 334 ++++++++++++++++++ pkg/ride/environment.go | 4 + pkg/ride/smart_state_moq_test.go | 44 +++ pkg/state/appender.go | 19 +- pkg/state/smart_state_moq_test.go | 44 +++ pkg/types/types.go | 1 + 14 files changed, 928 insertions(+), 20 deletions(-) create mode 100644 github.com/wavesplatform/gowaves/pkg/grpc/generated/waves/bupdates/blockchain_updates.pb.go create mode 100644 pkg/blockchainupdates/nuts_server.go create mode 100644 pkg/grpc/generated/waves/bupdates/blockchain_updates.pb.go create mode 100644 pkg/grpc/generated/waves/bupdates/blockchain_updates_vtproto.pb.go diff --git a/Makefile b/Makefile index d51ca49ba..bb484ebca 100644 --- a/Makefile +++ b/Makefile @@ -226,6 +226,8 @@ proto: @protoc --proto_path=pkg/grpc/protobuf-schemas/proto/ --go_out=./ --go_opt=module=$(MODULE) --go-vtproto_out=./ --go-vtproto_opt=features=marshal_strict+unmarshal+size --go-vtproto_opt=module=$(MODULE) pkg/grpc/protobuf-schemas/proto/waves/lang/*.proto @protoc --proto_path=pkg/grpc/protobuf-schemas/proto/ --go_out=./ --go_opt=module=$(MODULE) --go-vtproto_out=./ --go-vtproto_opt=features=marshal_strict+unmarshal+size --go-vtproto_opt=module=$(MODULE) pkg/grpc/protobuf-schemas/proto/waves/events/*.proto @protoc --proto_path=pkg/grpc/protobuf-schemas/proto/ --go_out=./ --go_opt=module=$(MODULE) --go-grpc_out=./ --go-grpc_opt=require_unimplemented_servers=false --go-grpc_opt=module=$(MODULE) pkg/grpc/protobuf-schemas/proto/waves/events/grpc/*.proto +proto1: + @protoc --proto_path=pkg/grpc/protobuf-schemas/proto/ --go_out=./ --go_opt=module=$(MODULE) --go-vtproto_out=./ --go-vtproto_opt=features=marshal_strict+unmarshal+size --go-vtproto_opt=module=$(MODULE) pkg/grpc/protobuf-schemas/proto/waves/bupdates/*.proto build-node-mainnet-amd64-deb-package: release-node @mkdir -p build/dist diff --git a/cmd/node/node.go b/cmd/node/node.go index 67678d765..1070efe60 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -394,14 +394,20 @@ func main() { var bUpdatesExtension *state.BlockchainUpdatesExtension if nc.enableBlockchainUpdatesPlugin { updatesChannel := make(chan blockchainupdates.BUpdatesInfo) - bUpdatesExtensionState := blockchainupdates.NewBUpdatesExtensionState() + bUpdatesExtensionState := blockchainupdates.NewBUpdatesExtensionState(2000) + l2address, err := proto.NewAddressFromString("3MsqKJ6o1ABE37676cHHBxJRs6huYTt72ch") + if err != nil { + zap.S().Errorf("Failed to initialize L2 contract address") + return + } bUpdatesExtension = &state.BlockchainUpdatesExtension{ EnableBlockchainUpdatesPlugin: true, BUpdatesChannel: updatesChannel, + L2ContractAddress: l2address, } - bUpdatesExtensionState.RunBlockchainUpdatesPublisher(ctx, updatesChannel) + go bUpdatesExtensionState.RunBlockchainUpdatesPublisher(ctx, updatesChannel) } // Send updatesChannel into BlockchainSettings. Write updates into this channel diff --git a/github.com/wavesplatform/gowaves/pkg/grpc/generated/waves/bupdates/blockchain_updates.pb.go b/github.com/wavesplatform/gowaves/pkg/grpc/generated/waves/bupdates/blockchain_updates.pb.go new file mode 100644 index 000000000..fe60e44f1 --- /dev/null +++ b/github.com/wavesplatform/gowaves/pkg/grpc/generated/waves/bupdates/blockchain_updates.pb.go @@ -0,0 +1,198 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v3.12.4 +// source: waves/bupdates/blockchain_updates.proto + +package bupdates + +import ( + waves "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type BUpdates struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Height uint64 `protobuf:"varint,1,opt,name=Height,proto3" json:"Height,omitempty"` + VRF []byte `protobuf:"bytes,2,opt,name=VRF,proto3" json:"VRF,omitempty"` + BlockID []byte `protobuf:"bytes,3,opt,name=BlockID,proto3" json:"BlockID,omitempty"` + BlockHeader *waves.Block_Header `protobuf:"bytes,4,opt,name=BlockHeader,proto3" json:"BlockHeader,omitempty"` + DataEntries []*waves.DataEntry `protobuf:"bytes,5,rep,name=DataEntries,proto3" json:"DataEntries,omitempty"` +} + +func (x *BUpdates) Reset() { + *x = BUpdates{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_bupdates_blockchain_updates_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BUpdates) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BUpdates) ProtoMessage() {} + +func (x *BUpdates) ProtoReflect() protoreflect.Message { + mi := &file_waves_bupdates_blockchain_updates_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BUpdates.ProtoReflect.Descriptor instead. +func (*BUpdates) Descriptor() ([]byte, []int) { + return file_waves_bupdates_blockchain_updates_proto_rawDescGZIP(), []int{0} +} + +func (x *BUpdates) GetHeight() uint64 { + if x != nil { + return x.Height + } + return 0 +} + +func (x *BUpdates) GetVRF() []byte { + if x != nil { + return x.VRF + } + return nil +} + +func (x *BUpdates) GetBlockID() []byte { + if x != nil { + return x.BlockID + } + return nil +} + +func (x *BUpdates) GetBlockHeader() *waves.Block_Header { + if x != nil { + return x.BlockHeader + } + return nil +} + +func (x *BUpdates) GetDataEntries() []*waves.DataEntry { + if x != nil { + return x.DataEntries + } + return nil +} + +var File_waves_bupdates_blockchain_updates_proto protoreflect.FileDescriptor + +var file_waves_bupdates_blockchain_updates_proto_rawDesc = []byte{ + 0x0a, 0x27, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x62, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, + 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x1a, 0x17, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x11, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb9, 0x01, 0x0a, + 0x08, 0x42, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x48, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x48, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x12, 0x10, 0x0a, 0x03, 0x56, 0x52, 0x46, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, + 0x56, 0x52, 0x46, 0x12, 0x18, 0x0a, 0x07, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x12, 0x35, 0x0a, + 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, + 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x77, 0x61, 0x76, 0x65, + 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x44, 0x61, 0x74, + 0x61, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x42, 0x68, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, + 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, + 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, + 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x77, 0x61, 0x76, 0x65, + 0x73, 0x2f, 0x62, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0xaa, 0x02, 0x05, 0x57, 0x61, 0x76, + 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_waves_bupdates_blockchain_updates_proto_rawDescOnce sync.Once + file_waves_bupdates_blockchain_updates_proto_rawDescData = file_waves_bupdates_blockchain_updates_proto_rawDesc +) + +func file_waves_bupdates_blockchain_updates_proto_rawDescGZIP() []byte { + file_waves_bupdates_blockchain_updates_proto_rawDescOnce.Do(func() { + file_waves_bupdates_blockchain_updates_proto_rawDescData = protoimpl.X.CompressGZIP(file_waves_bupdates_blockchain_updates_proto_rawDescData) + }) + return file_waves_bupdates_blockchain_updates_proto_rawDescData +} + +var file_waves_bupdates_blockchain_updates_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_waves_bupdates_blockchain_updates_proto_goTypes = []interface{}{ + (*BUpdates)(nil), // 0: waves.BUpdates + (*waves.Block_Header)(nil), // 1: waves.Block.Header + (*waves.DataEntry)(nil), // 2: waves.DataEntry +} +var file_waves_bupdates_blockchain_updates_proto_depIdxs = []int32{ + 1, // 0: waves.BUpdates.BlockHeader:type_name -> waves.Block.Header + 2, // 1: waves.BUpdates.DataEntries:type_name -> waves.DataEntry + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_waves_bupdates_blockchain_updates_proto_init() } +func file_waves_bupdates_blockchain_updates_proto_init() { + if File_waves_bupdates_blockchain_updates_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_waves_bupdates_blockchain_updates_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BUpdates); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_waves_bupdates_blockchain_updates_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_waves_bupdates_blockchain_updates_proto_goTypes, + DependencyIndexes: file_waves_bupdates_blockchain_updates_proto_depIdxs, + MessageInfos: file_waves_bupdates_blockchain_updates_proto_msgTypes, + }.Build() + File_waves_bupdates_blockchain_updates_proto = out.File + file_waves_bupdates_blockchain_updates_proto_rawDesc = nil + file_waves_bupdates_blockchain_updates_proto_goTypes = nil + file_waves_bupdates_blockchain_updates_proto_depIdxs = nil +} diff --git a/go.mod b/go.mod index 5975005cb..6adf6908d 100644 --- a/go.mod +++ b/go.mod @@ -22,10 +22,12 @@ require ( github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab github.com/jinzhu/copier v0.4.0 github.com/mr-tron/base58 v1.2.0 - github.com/nats-io/nats.go v1.35.0 + github.com/nats-io/nats-server/v2 v2.10.17 + github.com/nats-io/nats.go v1.36.0 github.com/ory/dockertest/v3 v3.10.0 github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/pkg/errors v0.9.1 + github.com/planetscale/vtprotobuf v0.6.0 github.com/prometheus/client_golang v1.19.1 github.com/qmuntal/stateless v1.7.0 github.com/semrush/zenrpc/v2 v2.1.1 @@ -80,12 +82,14 @@ require ( github.com/imdario/mergo v0.3.12 // indirect github.com/ingonyama-zk/icicle v0.0.0-20230928131117-97f0079e5c71 // indirect github.com/ingonyama-zk/iciclegnark v0.1.0 // indirect - github.com/klauspost/compress v1.17.2 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect + github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect + github.com/nats-io/jwt/v2 v2.5.7 // indirect github.com/nats-io/nkeys v0.4.7 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect @@ -110,6 +114,7 @@ require ( golang.org/x/net v0.25.0 // indirect golang.org/x/term v0.21.0 // indirect golang.org/x/text v0.16.0 // indirect + golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index d5c1e4157..1f06254a3 100644 --- a/go.sum +++ b/go.sum @@ -148,8 +148,8 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= -github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -171,6 +171,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= +github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= @@ -185,8 +187,12 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/nats.go v1.35.0 h1:XFNqNM7v5B+MQMKqVGAyHwYhyKb48jrenXNxIU20ULk= -github.com/nats-io/nats.go v1.35.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= +github.com/nats-io/jwt/v2 v2.5.7 h1:j5lH1fUXCnJnY8SsQeB/a/z9Azgu2bYIDvtPVNdxe2c= +github.com/nats-io/jwt/v2 v2.5.7/go.mod h1:ZdWS1nZa6WMZfFwwgpEaqBV8EPGVgOTDHN/wTbz0Y5A= +github.com/nats-io/nats-server/v2 v2.10.17 h1:PTVObNBD3TZSNUDgzFb1qQsQX4mOgFmOuG9vhT+KBUY= +github.com/nats-io/nats-server/v2 v2.10.17/go.mod h1:5OUyc4zg42s/p2i92zbbqXvUNsbF0ivdTLKshVMn2YQ= +github.com/nats-io/nats.go v1.36.0 h1:suEUPuWzTSse/XhESwqLxXGuj8vGRuPRoG7MoRN/qyU= +github.com/nats-io/nats.go v1.36.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= @@ -217,6 +223,8 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/planetscale/vtprotobuf v0.6.0 h1:nBeETjudeJ5ZgBHUz1fVHvbqUKnYOXNhsIEabROxmNA= +github.com/planetscale/vtprotobuf v0.6.0/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -381,6 +389,7 @@ golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -418,6 +427,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= diff --git a/pkg/blockchainupdates/nuts_publisher.go b/pkg/blockchainupdates/nuts_publisher.go index 89a69b0ff..52df09523 100644 --- a/pkg/blockchainupdates/nuts_publisher.go +++ b/pkg/blockchainupdates/nuts_publisher.go @@ -3,25 +3,30 @@ package blockchainupdates import ( "context" "fmt" + "github.com/nats-io/nats-server/v2/server" "github.com/nats-io/nats.go" "github.com/wavesplatform/gowaves/pkg/proto" "log" ) +// protoc --go_out=. --go_opt=paths=source_relative blockchainupdates.proto + type BUpdatesInfo struct { - Height uint64 - VRF proto.B58Bytes - BlockID proto.BlockID - BlockHeader *proto.BlockHeader + Height uint64 + VRF proto.B58Bytes + BlockID proto.BlockID + BlockHeader *proto.BlockHeader + AllDataEntries []proto.DataEntry } type BUpdatesExtensionState struct { currentState *BUpdatesInfo previousState *BUpdatesInfo // this information is what was just published + Limit uint64 } -func NewBUpdatesExtensionState() *BUpdatesExtensionState { - return &BUpdatesExtensionState{} +func NewBUpdatesExtensionState(limit uint64) *BUpdatesExtensionState { + return &BUpdatesExtensionState{Limit: limit} } func (bu *BUpdatesExtensionState) hasStateChanged() { @@ -29,6 +34,20 @@ func (bu *BUpdatesExtensionState) hasStateChanged() { } func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(ctx context.Context, updatesChannel <-chan BUpdatesInfo) { + opts := &server.Options{ + Host: "127.0.0.1", + Port: 4222, + } + s, err := server.NewServer(opts) + if err != nil { + log.Fatalf("failed to create NATS server: %v", err) + } + go s.Start() + if !s.ReadyForConnections(5 * server.AUTH_TIMEOUT) { + log.Fatal("NATS Server not ready for connections") + } + log.Printf("NATS Server is running on port %d", 4222) + nc, err := nats.Connect(nats.DefaultURL) if err != nil { log.Fatal(err) @@ -38,7 +57,11 @@ func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(ctx context.Cont func(ctx context.Context, updatesChannel <-chan BUpdatesInfo) { for { select { - case updates := <-updatesChannel: + case updates, ok := <-updatesChannel: + if !ok { + log.Printf("the updates channel for publisher was closed") + return + } // update current state // compare the current state to the previous state @@ -47,6 +70,7 @@ func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(ctx context.Cont fmt.Println(updates.Height) var msg string + msg = "hello" // Publish blockchain updates topic := block_updates err := nc.Publish(topic, []byte(msg)) diff --git a/pkg/blockchainupdates/nuts_server.go b/pkg/blockchainupdates/nuts_server.go new file mode 100644 index 000000000..92ee1e977 --- /dev/null +++ b/pkg/blockchainupdates/nuts_server.go @@ -0,0 +1,28 @@ +package blockchainupdates + +import ( + "github.com/nats-io/nats-server/v2/server" + "log" +) + +func RunBlockchainUpdatesServer() { + opts := &server.Options{ + Host: "127.0.0.1", + Port: 4222, + } + s, err := server.NewServer(opts) + if err != nil { + log.Fatalf("failed to create NATS server: %v", err) + } + + go s.Start() + + if !s.ReadyForConnections(10 * server.AUTH_TIMEOUT) { + log.Fatal("NATS Server not ready for connections") + } + + log.Println("NATS Server is running on port 4222") + + // Block main goroutine so the server keeps running + select {} +} diff --git a/pkg/grpc/generated/waves/bupdates/blockchain_updates.pb.go b/pkg/grpc/generated/waves/bupdates/blockchain_updates.pb.go new file mode 100644 index 000000000..fe60e44f1 --- /dev/null +++ b/pkg/grpc/generated/waves/bupdates/blockchain_updates.pb.go @@ -0,0 +1,198 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v3.12.4 +// source: waves/bupdates/blockchain_updates.proto + +package bupdates + +import ( + waves "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type BUpdates struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Height uint64 `protobuf:"varint,1,opt,name=Height,proto3" json:"Height,omitempty"` + VRF []byte `protobuf:"bytes,2,opt,name=VRF,proto3" json:"VRF,omitempty"` + BlockID []byte `protobuf:"bytes,3,opt,name=BlockID,proto3" json:"BlockID,omitempty"` + BlockHeader *waves.Block_Header `protobuf:"bytes,4,opt,name=BlockHeader,proto3" json:"BlockHeader,omitempty"` + DataEntries []*waves.DataEntry `protobuf:"bytes,5,rep,name=DataEntries,proto3" json:"DataEntries,omitempty"` +} + +func (x *BUpdates) Reset() { + *x = BUpdates{} + if protoimpl.UnsafeEnabled { + mi := &file_waves_bupdates_blockchain_updates_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BUpdates) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BUpdates) ProtoMessage() {} + +func (x *BUpdates) ProtoReflect() protoreflect.Message { + mi := &file_waves_bupdates_blockchain_updates_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BUpdates.ProtoReflect.Descriptor instead. +func (*BUpdates) Descriptor() ([]byte, []int) { + return file_waves_bupdates_blockchain_updates_proto_rawDescGZIP(), []int{0} +} + +func (x *BUpdates) GetHeight() uint64 { + if x != nil { + return x.Height + } + return 0 +} + +func (x *BUpdates) GetVRF() []byte { + if x != nil { + return x.VRF + } + return nil +} + +func (x *BUpdates) GetBlockID() []byte { + if x != nil { + return x.BlockID + } + return nil +} + +func (x *BUpdates) GetBlockHeader() *waves.Block_Header { + if x != nil { + return x.BlockHeader + } + return nil +} + +func (x *BUpdates) GetDataEntries() []*waves.DataEntry { + if x != nil { + return x.DataEntries + } + return nil +} + +var File_waves_bupdates_blockchain_updates_proto protoreflect.FileDescriptor + +var file_waves_bupdates_blockchain_updates_proto_rawDesc = []byte{ + 0x0a, 0x27, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x62, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, + 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x1a, 0x17, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x11, 0x77, 0x61, 0x76, 0x65, 0x73, + 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb9, 0x01, 0x0a, + 0x08, 0x42, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x48, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x48, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x12, 0x10, 0x0a, 0x03, 0x56, 0x52, 0x46, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, + 0x56, 0x52, 0x46, 0x12, 0x18, 0x0a, 0x07, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x12, 0x35, 0x0a, + 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, + 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x77, 0x61, 0x76, 0x65, + 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x44, 0x61, 0x74, + 0x61, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x42, 0x68, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, + 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, + 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, + 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x77, 0x61, 0x76, 0x65, + 0x73, 0x2f, 0x62, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0xaa, 0x02, 0x05, 0x57, 0x61, 0x76, + 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_waves_bupdates_blockchain_updates_proto_rawDescOnce sync.Once + file_waves_bupdates_blockchain_updates_proto_rawDescData = file_waves_bupdates_blockchain_updates_proto_rawDesc +) + +func file_waves_bupdates_blockchain_updates_proto_rawDescGZIP() []byte { + file_waves_bupdates_blockchain_updates_proto_rawDescOnce.Do(func() { + file_waves_bupdates_blockchain_updates_proto_rawDescData = protoimpl.X.CompressGZIP(file_waves_bupdates_blockchain_updates_proto_rawDescData) + }) + return file_waves_bupdates_blockchain_updates_proto_rawDescData +} + +var file_waves_bupdates_blockchain_updates_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_waves_bupdates_blockchain_updates_proto_goTypes = []interface{}{ + (*BUpdates)(nil), // 0: waves.BUpdates + (*waves.Block_Header)(nil), // 1: waves.Block.Header + (*waves.DataEntry)(nil), // 2: waves.DataEntry +} +var file_waves_bupdates_blockchain_updates_proto_depIdxs = []int32{ + 1, // 0: waves.BUpdates.BlockHeader:type_name -> waves.Block.Header + 2, // 1: waves.BUpdates.DataEntries:type_name -> waves.DataEntry + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_waves_bupdates_blockchain_updates_proto_init() } +func file_waves_bupdates_blockchain_updates_proto_init() { + if File_waves_bupdates_blockchain_updates_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_waves_bupdates_blockchain_updates_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BUpdates); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_waves_bupdates_blockchain_updates_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_waves_bupdates_blockchain_updates_proto_goTypes, + DependencyIndexes: file_waves_bupdates_blockchain_updates_proto_depIdxs, + MessageInfos: file_waves_bupdates_blockchain_updates_proto_msgTypes, + }.Build() + File_waves_bupdates_blockchain_updates_proto = out.File + file_waves_bupdates_blockchain_updates_proto_rawDesc = nil + file_waves_bupdates_blockchain_updates_proto_goTypes = nil + file_waves_bupdates_blockchain_updates_proto_depIdxs = nil +} diff --git a/pkg/grpc/generated/waves/bupdates/blockchain_updates_vtproto.pb.go b/pkg/grpc/generated/waves/bupdates/blockchain_updates_vtproto.pb.go new file mode 100644 index 000000000..83efb89a2 --- /dev/null +++ b/pkg/grpc/generated/waves/bupdates/blockchain_updates_vtproto.pb.go @@ -0,0 +1,334 @@ +// Code generated by protoc-gen-go-vtproto. DO NOT EDIT. +// protoc-gen-go-vtproto version: v0.6.0 +// source: waves/bupdates/blockchain_updates.proto + +package bupdates + +import ( + fmt "fmt" + protohelpers "github.com/planetscale/vtprotobuf/protohelpers" + waves "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + io "io" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +func (m *BUpdates) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BUpdates) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *BUpdates) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.DataEntries) > 0 { + for iNdEx := len(m.DataEntries) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.DataEntries[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x2a + } + } + if m.BlockHeader != nil { + size, err := m.BlockHeader.MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } + if len(m.BlockID) > 0 { + i -= len(m.BlockID) + copy(dAtA[i:], m.BlockID) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.BlockID))) + i-- + dAtA[i] = 0x1a + } + if len(m.VRF) > 0 { + i -= len(m.VRF) + copy(dAtA[i:], m.VRF) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.VRF))) + i-- + dAtA[i] = 0x12 + } + if m.Height != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *BUpdates) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Height)) + } + l = len(m.VRF) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.BlockID) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.BlockHeader != nil { + l = m.BlockHeader.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if len(m.DataEntries) > 0 { + for _, e := range m.DataEntries { + l = e.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + } + n += len(m.unknownFields) + return n +} + +func (m *BUpdates) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BUpdates: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BUpdates: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VRF", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.VRF = append(m.VRF[:0], dAtA[iNdEx:postIndex]...) + if m.VRF == nil { + m.VRF = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockID", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BlockID = append(m.BlockID[:0], dAtA[iNdEx:postIndex]...) + if m.BlockID == nil { + m.BlockID = []byte{} + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockHeader", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.BlockHeader == nil { + m.BlockHeader = &waves.Block_Header{} + } + if err := m.BlockHeader.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DataEntries", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DataEntries = append(m.DataEntries, &waves.DataEntry{}) + if err := m.DataEntries[len(m.DataEntries)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} diff --git a/pkg/ride/environment.go b/pkg/ride/environment.go index 9a2765215..2f8c324f1 100644 --- a/pkg/ride/environment.go +++ b/pkg/ride/environment.go @@ -78,6 +78,10 @@ func (ws *WrappedState) NewestTransactionByID(id []byte) (proto.Transaction, err return ws.diff.state.NewestTransactionByID(id) } +func (ws *WrappedState) RetrieveEntries(account proto.Recipient) ([]proto.DataEntry, error) { + return ws.diff.state.RetrieveEntries(account) +} + func (ws *WrappedState) NewestTransactionHeightByID(id []byte) (uint64, error) { return ws.diff.state.NewestTransactionHeightByID(id) } diff --git a/pkg/ride/smart_state_moq_test.go b/pkg/ride/smart_state_moq_test.go index 4fd0eacc2..21755cd21 100644 --- a/pkg/ride/smart_state_moq_test.go +++ b/pkg/ride/smart_state_moq_test.go @@ -87,6 +87,9 @@ var _ types.SmartState = &MockSmartState{} // NewestWavesBalanceFunc: func(account proto.Recipient) (uint64, error) { // panic("mock out the NewestWavesBalance method") // }, +// RetrieveEntriesFunc: func(account proto.Recipient) ([]proto.DataEntry, error) { +// panic("mock out the RetrieveEntries method") +// }, // RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { // panic("mock out the RetrieveNewestBinaryEntry method") // }, @@ -175,6 +178,9 @@ type MockSmartState struct { // NewestWavesBalanceFunc mocks the NewestWavesBalance method. NewestWavesBalanceFunc func(account proto.Recipient) (uint64, error) + // RetrieveEntriesFunc mocks the RetrieveEntries method. + RetrieveEntriesFunc func(account proto.Recipient) ([]proto.DataEntry, error) + // RetrieveNewestBinaryEntryFunc mocks the RetrieveNewestBinaryEntry method. RetrieveNewestBinaryEntryFunc func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) @@ -302,6 +308,11 @@ type MockSmartState struct { // Account is the account argument value. Account proto.Recipient } + // RetrieveEntries holds details about calls to the RetrieveEntries method. + RetrieveEntries []struct { + // Account is the account argument value. + Account proto.Recipient + } // RetrieveNewestBinaryEntry holds details about calls to the RetrieveNewestBinaryEntry method. RetrieveNewestBinaryEntry []struct { // Account is the account argument value. @@ -358,6 +369,7 @@ type MockSmartState struct { lockNewestTransactionByID sync.RWMutex lockNewestTransactionHeightByID sync.RWMutex lockNewestWavesBalance sync.RWMutex + lockRetrieveEntries sync.RWMutex lockRetrieveNewestBinaryEntry sync.RWMutex lockRetrieveNewestBooleanEntry sync.RWMutex lockRetrieveNewestIntegerEntry sync.RWMutex @@ -1067,6 +1079,38 @@ func (mock *MockSmartState) NewestWavesBalanceCalls() []struct { return calls } +// RetrieveEntries calls RetrieveEntriesFunc. +func (mock *MockSmartState) RetrieveEntries(account proto.Recipient) ([]proto.DataEntry, error) { + if mock.RetrieveEntriesFunc == nil { + panic("MockSmartState.RetrieveEntriesFunc: method is nil but SmartState.RetrieveEntries was just called") + } + callInfo := struct { + Account proto.Recipient + }{ + Account: account, + } + mock.lockRetrieveEntries.Lock() + mock.calls.RetrieveEntries = append(mock.calls.RetrieveEntries, callInfo) + mock.lockRetrieveEntries.Unlock() + return mock.RetrieveEntriesFunc(account) +} + +// RetrieveEntriesCalls gets all the calls that were made to RetrieveEntries. +// Check the length with: +// +// len(mockedSmartState.RetrieveEntriesCalls()) +func (mock *MockSmartState) RetrieveEntriesCalls() []struct { + Account proto.Recipient +} { + var calls []struct { + Account proto.Recipient + } + mock.lockRetrieveEntries.RLock() + calls = mock.calls.RetrieveEntries + mock.lockRetrieveEntries.RUnlock() + return calls +} + // RetrieveNewestBinaryEntry calls RetrieveNewestBinaryEntryFunc. func (mock *MockSmartState) RetrieveNewestBinaryEntry(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { if mock.RetrieveNewestBinaryEntryFunc == nil { diff --git a/pkg/state/appender.go b/pkg/state/appender.go index f97f53821..0648a658f 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -61,6 +61,7 @@ type txAppender struct { type BlockchainUpdatesExtension struct { EnableBlockchainUpdatesPlugin bool + L2ContractAddress proto.WavesAddress BUpdatesChannel chan<- blockchainupdates.BUpdatesInfo } @@ -859,15 +860,23 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { return a.blockDiffer.saveCurFeeDistr(params.block) } -func (a *txAppender) updateBlockchainUpdateInfo(blockInfo *proto.BlockInfo, blockHeader *proto.BlockHeader) { +func (a *txAppender) updateBlockchainUpdateInfo(blockInfo *proto.BlockInfo, blockHeader *proto.BlockHeader) error { + // TODO improve this by using diffs instead grabbing all the records every time + dataEntries, err := a.ia.state.RetrieveEntries(proto.NewRecipientFromAddress(a.bUpdatesExtension.L2ContractAddress)) + if err != nil { + return err + } + bUpdatesInfo := blockchainupdates.BUpdatesInfo{ - Height: blockInfo.Height, - VRF: blockInfo.VRF, - BlockID: blockHeader.BlockID(), - BlockHeader: blockHeader, + Height: blockInfo.Height, + VRF: blockInfo.VRF, + BlockID: blockHeader.BlockID(), + BlockHeader: blockHeader, + AllDataEntries: dataEntries, } a.bUpdatesExtension.BUpdatesChannel <- bUpdatesInfo + return nil } func (a *txAppender) createCheckerInfo(params *appendBlockParams) (*checkerInfo, error) { diff --git a/pkg/state/smart_state_moq_test.go b/pkg/state/smart_state_moq_test.go index 4b3bcd149..54d4a704e 100644 --- a/pkg/state/smart_state_moq_test.go +++ b/pkg/state/smart_state_moq_test.go @@ -87,6 +87,9 @@ var _ types.SmartState = &AnotherMockSmartState{} // NewestWavesBalanceFunc: func(account proto.Recipient) (uint64, error) { // panic("mock out the NewestWavesBalance method") // }, +// RetrieveEntriesFunc: func(account proto.Recipient) ([]proto.DataEntry, error) { +// panic("mock out the RetrieveEntries method") +// }, // RetrieveNewestBinaryEntryFunc: func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { // panic("mock out the RetrieveNewestBinaryEntry method") // }, @@ -175,6 +178,9 @@ type AnotherMockSmartState struct { // NewestWavesBalanceFunc mocks the NewestWavesBalance method. NewestWavesBalanceFunc func(account proto.Recipient) (uint64, error) + // RetrieveEntriesFunc mocks the RetrieveEntries method. + RetrieveEntriesFunc func(account proto.Recipient) ([]proto.DataEntry, error) + // RetrieveNewestBinaryEntryFunc mocks the RetrieveNewestBinaryEntry method. RetrieveNewestBinaryEntryFunc func(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) @@ -302,6 +308,11 @@ type AnotherMockSmartState struct { // Account is the account argument value. Account proto.Recipient } + // RetrieveEntries holds details about calls to the RetrieveEntries method. + RetrieveEntries []struct { + // Account is the account argument value. + Account proto.Recipient + } // RetrieveNewestBinaryEntry holds details about calls to the RetrieveNewestBinaryEntry method. RetrieveNewestBinaryEntry []struct { // Account is the account argument value. @@ -358,6 +369,7 @@ type AnotherMockSmartState struct { lockNewestTransactionByID sync.RWMutex lockNewestTransactionHeightByID sync.RWMutex lockNewestWavesBalance sync.RWMutex + lockRetrieveEntries sync.RWMutex lockRetrieveNewestBinaryEntry sync.RWMutex lockRetrieveNewestBooleanEntry sync.RWMutex lockRetrieveNewestIntegerEntry sync.RWMutex @@ -1067,6 +1079,38 @@ func (mock *AnotherMockSmartState) NewestWavesBalanceCalls() []struct { return calls } +// RetrieveEntries calls RetrieveEntriesFunc. +func (mock *AnotherMockSmartState) RetrieveEntries(account proto.Recipient) ([]proto.DataEntry, error) { + if mock.RetrieveEntriesFunc == nil { + panic("AnotherMockSmartState.RetrieveEntriesFunc: method is nil but SmartState.RetrieveEntries was just called") + } + callInfo := struct { + Account proto.Recipient + }{ + Account: account, + } + mock.lockRetrieveEntries.Lock() + mock.calls.RetrieveEntries = append(mock.calls.RetrieveEntries, callInfo) + mock.lockRetrieveEntries.Unlock() + return mock.RetrieveEntriesFunc(account) +} + +// RetrieveEntriesCalls gets all the calls that were made to RetrieveEntries. +// Check the length with: +// +// len(mockedSmartState.RetrieveEntriesCalls()) +func (mock *AnotherMockSmartState) RetrieveEntriesCalls() []struct { + Account proto.Recipient +} { + var calls []struct { + Account proto.Recipient + } + mock.lockRetrieveEntries.RLock() + calls = mock.calls.RetrieveEntries + mock.lockRetrieveEntries.RUnlock() + return calls +} + // RetrieveNewestBinaryEntry calls RetrieveNewestBinaryEntryFunc. func (mock *AnotherMockSmartState) RetrieveNewestBinaryEntry(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) { if mock.RetrieveNewestBinaryEntryFunc == nil { diff --git a/pkg/types/types.go b/pkg/types/types.go index 636002b4c..05d2a3555 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -68,6 +68,7 @@ type SmartState interface { RetrieveNewestBooleanEntry(account proto.Recipient, key string) (*proto.BooleanDataEntry, error) RetrieveNewestStringEntry(account proto.Recipient, key string) (*proto.StringDataEntry, error) RetrieveNewestBinaryEntry(account proto.Recipient, key string) (*proto.BinaryDataEntry, error) + RetrieveEntries(account proto.Recipient) ([]proto.DataEntry, error) NewestAssetIsSponsored(assetID crypto.Digest) (bool, error) NewestAssetConstInfo(assetID proto.AssetID) (*proto.AssetConstInfo, error) NewestAssetInfo(assetID crypto.Digest) (*proto.AssetInfo, error) From 6752f8a113e3e9b62abfa9ff5d3d71eb6dd9de04 Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 15 Jul 2024 21:36:18 -0500 Subject: [PATCH 09/50] Moved proto, added conversion --- Makefile | 4 +- cmd/blockchaininfo/nuts_subscriber.go | 81 ++++++ cmd/blockchainupdates/nuts_subscriber.go | 27 -- cmd/node/node.go | 10 +- .../nuts_publisher.go | 54 +++- .../nuts_server.go | 2 +- pkg/blockchaininfo/proto_converters.go | 82 ++++++ pkg/blockchaininfo/topics.go | 27 ++ pkg/blockchainupdates/topics.go | 10 - .../waves/bupdates/blockchain_updates.pb.go | 198 -------------- .../l2/blockchain_info/blockchain_info.pb.go | 251 ++++++++++++++++++ .../l2/blockchain_info/blockchain_info.proto | 24 ++ .../blockchain_info_vtproto.pb.go} | 203 ++++++++++++-- pkg/proto/block.go | 56 ++++ pkg/proto/types.go | 14 +- pkg/state/accounts_data_storage.go | 2 +- pkg/state/appender.go | 14 +- pkg/state/state.go | 3 + 18 files changed, 763 insertions(+), 299 deletions(-) create mode 100644 cmd/blockchaininfo/nuts_subscriber.go delete mode 100644 cmd/blockchainupdates/nuts_subscriber.go rename pkg/{blockchainupdates => blockchaininfo}/nuts_publisher.go (56%) rename pkg/{blockchainupdates => blockchaininfo}/nuts_server.go (95%) create mode 100644 pkg/blockchaininfo/proto_converters.go create mode 100644 pkg/blockchaininfo/topics.go delete mode 100644 pkg/blockchainupdates/topics.go delete mode 100644 pkg/grpc/generated/waves/bupdates/blockchain_updates.pb.go create mode 100644 pkg/grpc/l2/blockchain_info/blockchain_info.pb.go create mode 100644 pkg/grpc/l2/blockchain_info/blockchain_info.proto rename pkg/grpc/{generated/waves/bupdates/blockchain_updates_vtproto.pb.go => l2/blockchain_info/blockchain_info_vtproto.pb.go} (59%) diff --git a/Makefile b/Makefile index bb484ebca..cdd39b98a 100644 --- a/Makefile +++ b/Makefile @@ -226,8 +226,8 @@ proto: @protoc --proto_path=pkg/grpc/protobuf-schemas/proto/ --go_out=./ --go_opt=module=$(MODULE) --go-vtproto_out=./ --go-vtproto_opt=features=marshal_strict+unmarshal+size --go-vtproto_opt=module=$(MODULE) pkg/grpc/protobuf-schemas/proto/waves/lang/*.proto @protoc --proto_path=pkg/grpc/protobuf-schemas/proto/ --go_out=./ --go_opt=module=$(MODULE) --go-vtproto_out=./ --go-vtproto_opt=features=marshal_strict+unmarshal+size --go-vtproto_opt=module=$(MODULE) pkg/grpc/protobuf-schemas/proto/waves/events/*.proto @protoc --proto_path=pkg/grpc/protobuf-schemas/proto/ --go_out=./ --go_opt=module=$(MODULE) --go-grpc_out=./ --go-grpc_opt=require_unimplemented_servers=false --go-grpc_opt=module=$(MODULE) pkg/grpc/protobuf-schemas/proto/waves/events/grpc/*.proto -proto1: - @protoc --proto_path=pkg/grpc/protobuf-schemas/proto/ --go_out=./ --go_opt=module=$(MODULE) --go-vtproto_out=./ --go-vtproto_opt=features=marshal_strict+unmarshal+size --go-vtproto_opt=module=$(MODULE) pkg/grpc/protobuf-schemas/proto/waves/bupdates/*.proto +proto-l2: + @protoc --proto_path=pkg/grpc/protobuf-schemas/proto/ --proto_path=pkg/grpc/l2/blockchain_info/ --go_out=./ --go_opt=module=$(MODULE) --go-vtproto_out=./ --go-vtproto_opt=features=marshal_strict+unmarshal+size --go-vtproto_opt=module=$(MODULE) pkg/grpc/l2/blockchain_info/*.proto build-node-mainnet-amd64-deb-package: release-node @mkdir -p build/dist diff --git a/cmd/blockchaininfo/nuts_subscriber.go b/cmd/blockchaininfo/nuts_subscriber.go new file mode 100644 index 000000000..825ba030f --- /dev/null +++ b/cmd/blockchaininfo/nuts_subscriber.go @@ -0,0 +1,81 @@ +package main + +import ( + "encoding/json" + "fmt" + "github.com/nats-io/nats.go" + "github.com/wavesplatform/gowaves/pkg/blockchaininfo" + g "github.com/wavesplatform/gowaves/pkg/grpc/l2/blockchain_info" + "log" +) + +func printBlockInfo(blockInfoProto *g.BlockInfo) error { + blockInfo, err := blockchaininfo.BUpdatesInfoFromProto(blockInfoProto) + if err != nil { + return err + } + blockInfoJson, err := json.Marshal(blockInfo) + fmt.Println(string(blockInfoJson)) + return nil +} + +func printContractInfo(contractInfoProto *g.L2ContractDataEntries) error { + contractInfo, err := blockchaininfo.L2ContractDataEntriesFromProto(contractInfoProto) + if err != nil { + return err + } + contractInfoJson, err := json.Marshal(contractInfo) + fmt.Println(string(contractInfoJson)) + return nil +} + +func main() { + // Connect to a NATS server + nc, err := nats.Connect(nats.DefaultURL) + if err != nil { + log.Fatal(err) + } + defer nc.Close() + + topic := blockchaininfo.BlockUpdates + //for _, topic := range blockchaininfo.Topics { + _, err = nc.Subscribe(topic, func(msg *nats.Msg) { + + //log.Printf("Received on %s: %s\n", msg.Subject, string(msg.Data)) + if topic == blockchaininfo.BlockUpdates { + blockUpdatesInfo := new(g.BlockInfo) + err := blockUpdatesInfo.UnmarshalVT(msg.Data) + if err != nil { + return + } + + err = printBlockInfo(blockUpdatesInfo) + if err != nil { + return + } + log.Printf("Received on %s:\n", msg.Subject) + } + + if topic == blockchaininfo.ContractUpdates { + contractUpdatesInfo := new(g.L2ContractDataEntries) + err := contractUpdatesInfo.UnmarshalVT(msg.Data) + if err != nil { + return + } + log.Printf("Received on %s:\n", msg.Subject) + + err = printContractInfo(contractUpdatesInfo) + if err != nil { + return + } + + } + + }) + if err != nil { + log.Fatal(err) + } + //} + // Block main goroutine so the server keeps running + select {} +} diff --git a/cmd/blockchainupdates/nuts_subscriber.go b/cmd/blockchainupdates/nuts_subscriber.go deleted file mode 100644 index c6bba0a28..000000000 --- a/cmd/blockchainupdates/nuts_subscriber.go +++ /dev/null @@ -1,27 +0,0 @@ -package blockchainupdates - -import ( - "github.com/nats-io/nats.go" - "github.com/wavesplatform/gowaves/pkg/blockchainupdates" - "log" - "runtime" -) - -func main() { - // Connect to a NATS server - nc, err := nats.Connect(nats.DefaultURL) - if err != nil { - log.Fatal(err) - } - defer nc.Close() - - for _, topic := range blockchainupdates.Topics { - _, err = nc.Subscribe(topic, func(msg *nats.Msg) { - log.Printf("Received on %s: %s\n", msg.Subject, string(msg.Data)) - }) - if err != nil { - log.Fatal(err) - } - } - runtime.Goexit() -} diff --git a/cmd/node/node.go b/cmd/node/node.go index 1070efe60..45a1a044f 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -6,7 +6,7 @@ import ( "errors" "flag" "fmt" - "github.com/wavesplatform/gowaves/pkg/blockchainupdates" + "github.com/wavesplatform/gowaves/pkg/blockchaininfo" "math" "math/big" "net/http" @@ -241,7 +241,7 @@ func (c *config) parse() { flag.BoolVar(&c.enableLightMode, "enable-light-mode", false, "Start node in light mode") - flag.BoolVar(&c.enableBlockchainUpdatesPlugin, "enable-blockchain-updates", false, + flag.BoolVar(&c.enableBlockchainUpdatesPlugin, "enable-blockchain-info", false, "Turn on blockchain updates plugin") flag.Parse() c.logLevel = *l @@ -393,8 +393,8 @@ func main() { var bUpdatesExtension *state.BlockchainUpdatesExtension if nc.enableBlockchainUpdatesPlugin { - updatesChannel := make(chan blockchainupdates.BUpdatesInfo) - bUpdatesExtensionState := blockchainupdates.NewBUpdatesExtensionState(2000) + updatesChannel := make(chan blockchaininfo.BUpdatesInfo) + bUpdatesExtensionState := blockchaininfo.NewBUpdatesExtensionState(2000) l2address, err := proto.NewAddressFromString("3MsqKJ6o1ABE37676cHHBxJRs6huYTt72ch") if err != nil { @@ -407,7 +407,7 @@ func main() { L2ContractAddress: l2address, } - go bUpdatesExtensionState.RunBlockchainUpdatesPublisher(ctx, updatesChannel) + go bUpdatesExtensionState.RunBlockchainUpdatesPublisher(ctx, updatesChannel, cfg.AddressSchemeCharacter) } // Send updatesChannel into BlockchainSettings. Write updates into this channel diff --git a/pkg/blockchainupdates/nuts_publisher.go b/pkg/blockchaininfo/nuts_publisher.go similarity index 56% rename from pkg/blockchainupdates/nuts_publisher.go rename to pkg/blockchaininfo/nuts_publisher.go index 52df09523..d41888cab 100644 --- a/pkg/blockchainupdates/nuts_publisher.go +++ b/pkg/blockchaininfo/nuts_publisher.go @@ -1,4 +1,4 @@ -package blockchainupdates +package blockchaininfo import ( "context" @@ -9,8 +9,6 @@ import ( "log" ) -// protoc --go_out=. --go_opt=paths=source_relative blockchainupdates.proto - type BUpdatesInfo struct { Height uint64 VRF proto.B58Bytes @@ -33,7 +31,42 @@ func (bu *BUpdatesExtensionState) hasStateChanged() { } -func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(ctx context.Context, updatesChannel <-chan BUpdatesInfo) { +func (bu *BUpdatesExtensionState) publishUpdates(updates BUpdatesInfo, nc *nats.Conn, scheme proto.Scheme) error { + /* first publish block related info */ + blockInfo, err := BUpdatesInfoToProto(updates, scheme) + if err != nil { + return err + } + blockInfoProtobuf, err := blockInfo.MarshalVTStrict() + if err != nil { + return err + } + err = nc.Publish(BlockUpdates, blockInfoProtobuf) + if err != nil { + log.Printf("failed to publish message on topic %s", BlockUpdates) + return err + } + fmt.Printf("Published on topic: %s\n", BlockUpdates) + + /* second publish contract data entries */ + dataEntries := L2ContractDataEntriesToProto(updates.AllDataEntries) + dataEntriesProtobuf, err := dataEntries.MarshalVTStrict() + if err != nil { + return err + } + if dataEntries.DataEntries != nil { + err = nc.Publish(ContractUpdates, dataEntriesProtobuf) + if err != nil { + log.Printf("failed to publish message on topic %s", ContractUpdates) + return err + } + fmt.Printf("Published on topic: %s\n", ContractUpdates) + } + + return nil +} + +func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(ctx context.Context, updatesChannel <-chan BUpdatesInfo, scheme proto.Scheme) { opts := &server.Options{ Host: "127.0.0.1", Port: 4222, @@ -67,18 +100,11 @@ func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(ctx context.Cont // compare the current state to the previous state // if there is any diff, send the update - - fmt.Println(updates.Height) - var msg string - msg = "hello" - // Publish blockchain updates - topic := block_updates - err := nc.Publish(topic, []byte(msg)) + err := bu.publishUpdates(updates, nc, scheme) + log.Printf("published") if err != nil { - log.Printf("failed to publish message %s on topic %s", msg, topic) + log.Printf("failed to publish updates") } - fmt.Printf("Published: %s\n", msg) - case <-ctx.Done(): return } diff --git a/pkg/blockchainupdates/nuts_server.go b/pkg/blockchaininfo/nuts_server.go similarity index 95% rename from pkg/blockchainupdates/nuts_server.go rename to pkg/blockchaininfo/nuts_server.go index 92ee1e977..6bb307adc 100644 --- a/pkg/blockchainupdates/nuts_server.go +++ b/pkg/blockchaininfo/nuts_server.go @@ -1,4 +1,4 @@ -package blockchainupdates +package blockchaininfo import ( "github.com/nats-io/nats-server/v2/server" diff --git a/pkg/blockchaininfo/proto_converters.go b/pkg/blockchaininfo/proto_converters.go new file mode 100644 index 000000000..f598ed69c --- /dev/null +++ b/pkg/blockchaininfo/proto_converters.go @@ -0,0 +1,82 @@ +package blockchaininfo + +import ( + "errors" + "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" + g "github.com/wavesplatform/gowaves/pkg/grpc/l2/blockchain_info" + "github.com/wavesplatform/gowaves/pkg/proto" +) + +func BUpdatesInfoToProto(blockInfo BUpdatesInfo, scheme proto.Scheme) (*g.BlockInfo, error) { + blockHeader, err := blockInfo.BlockHeader.HeaderToProtobufHeader(scheme) + if err != nil { + return nil, err + } + return &g.BlockInfo{ + Height: blockInfo.Height, + VRF: blockInfo.VRF, + BlockID: blockInfo.BlockID.Bytes(), + BlockHeader: blockHeader, + }, nil +} + +func BUpdatesInfoFromProto(blockInfoProto *g.BlockInfo) (BUpdatesInfo, error) { + blockID, err := proto.NewBlockIDFromBytes(blockInfoProto.BlockID) + if err != nil { + return BUpdatesInfo{}, err + } + blockHeader, err := proto.ProtobufHeaderToBlockHeader(blockInfoProto.BlockHeader) + if err != nil { + return BUpdatesInfo{}, err + } + return BUpdatesInfo{ + Height: blockInfoProto.Height, + VRF: blockInfoProto.VRF, + BlockID: blockID, + BlockHeader: blockHeader, + AllDataEntries: nil, + }, nil +} + +func L2ContractDataEntriesToProto(dataEntries []proto.DataEntry) *g.L2ContractDataEntries { + var protobufDataEntries []*waves.DataEntry + for _, entry := range dataEntries { + entryProto := entry.ToProtobuf() + protobufDataEntries = append(protobufDataEntries, entryProto) + } + return &g.L2ContractDataEntries{ + DataEntries: protobufDataEntries, + } +} + +func L2ContractDataEntriesFromProto(protoDataEntries *g.L2ContractDataEntries) (L2ContractDataEntries, error) { + var dataEntries []proto.DataEntry + for _, protoEntry := range protoDataEntries.DataEntries { + dataEntryType := proto.DataEntryType{Type: protoEntry.Key} + entry, err := proto.GuessDataEntryType(dataEntryType) + if err != nil { + return L2ContractDataEntries{}, err + } + entry.SetKey(protoEntry.Key) + switch e := entry.(type) { + case *proto.IntegerDataEntry: + e.Value = protoEntry.GetIntValue() + entry = e + case *proto.BooleanDataEntry: + e.Value = protoEntry.GetBoolValue() + entry = e + case *proto.BinaryDataEntry: + e.Value = protoEntry.GetBinaryValue() + entry = e + case *proto.StringDataEntry: + e.Value = protoEntry.GetStringValue() + entry = e + case *proto.DeleteDataEntry: + default: + return L2ContractDataEntries{}, errors.New("failed to convert proto data entries into data entries") + } + dataEntries = append(dataEntries, entry) + } + + return L2ContractDataEntries{AllDataEntries: dataEntries}, nil +} diff --git a/pkg/blockchaininfo/topics.go b/pkg/blockchaininfo/topics.go new file mode 100644 index 000000000..167e9d730 --- /dev/null +++ b/pkg/blockchaininfo/topics.go @@ -0,0 +1,27 @@ +package blockchaininfo + +import "github.com/wavesplatform/gowaves/pkg/proto" + +/* Topics */ +const ( + BlockUpdates = "block_topic" + microblockUpdates = "microblock_topic" + ContractUpdates = "contract_topi" +) + +var Topics = []string{BlockUpdates, microblockUpdates, ContractUpdates} + +// block updates + +type BlockUpdatesInfo struct { + Height uint64 `json:"height"` + VRF proto.B58Bytes `json:"vrf"` + BlockID proto.BlockID `json:"block_id"` + BlockHeader *proto.BlockHeader `json:"block_header"` +} + +// l2 contract data entries + +type L2ContractDataEntries struct { + AllDataEntries []proto.DataEntry `json:"all_data_entries"` +} diff --git a/pkg/blockchainupdates/topics.go b/pkg/blockchainupdates/topics.go deleted file mode 100644 index 7755bf3c7..000000000 --- a/pkg/blockchainupdates/topics.go +++ /dev/null @@ -1,10 +0,0 @@ -package blockchainupdates - -/* Topics */ -const ( - block_updates = "block_topic" - microblock_updates = "microblock_topic" - contract_uptdates = "contract_topi" -) - -var Topics = []string{block_updates, microblock_updates, contract_uptdates} diff --git a/pkg/grpc/generated/waves/bupdates/blockchain_updates.pb.go b/pkg/grpc/generated/waves/bupdates/blockchain_updates.pb.go deleted file mode 100644 index fe60e44f1..000000000 --- a/pkg/grpc/generated/waves/bupdates/blockchain_updates.pb.go +++ /dev/null @@ -1,198 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.12.4 -// source: waves/bupdates/blockchain_updates.proto - -package bupdates - -import ( - waves "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type BUpdates struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Height uint64 `protobuf:"varint,1,opt,name=Height,proto3" json:"Height,omitempty"` - VRF []byte `protobuf:"bytes,2,opt,name=VRF,proto3" json:"VRF,omitempty"` - BlockID []byte `protobuf:"bytes,3,opt,name=BlockID,proto3" json:"BlockID,omitempty"` - BlockHeader *waves.Block_Header `protobuf:"bytes,4,opt,name=BlockHeader,proto3" json:"BlockHeader,omitempty"` - DataEntries []*waves.DataEntry `protobuf:"bytes,5,rep,name=DataEntries,proto3" json:"DataEntries,omitempty"` -} - -func (x *BUpdates) Reset() { - *x = BUpdates{} - if protoimpl.UnsafeEnabled { - mi := &file_waves_bupdates_blockchain_updates_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BUpdates) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BUpdates) ProtoMessage() {} - -func (x *BUpdates) ProtoReflect() protoreflect.Message { - mi := &file_waves_bupdates_blockchain_updates_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BUpdates.ProtoReflect.Descriptor instead. -func (*BUpdates) Descriptor() ([]byte, []int) { - return file_waves_bupdates_blockchain_updates_proto_rawDescGZIP(), []int{0} -} - -func (x *BUpdates) GetHeight() uint64 { - if x != nil { - return x.Height - } - return 0 -} - -func (x *BUpdates) GetVRF() []byte { - if x != nil { - return x.VRF - } - return nil -} - -func (x *BUpdates) GetBlockID() []byte { - if x != nil { - return x.BlockID - } - return nil -} - -func (x *BUpdates) GetBlockHeader() *waves.Block_Header { - if x != nil { - return x.BlockHeader - } - return nil -} - -func (x *BUpdates) GetDataEntries() []*waves.DataEntry { - if x != nil { - return x.DataEntries - } - return nil -} - -var File_waves_bupdates_blockchain_updates_proto protoreflect.FileDescriptor - -var file_waves_bupdates_blockchain_updates_proto_rawDesc = []byte{ - 0x0a, 0x27, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x62, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, - 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x75, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x77, 0x61, 0x76, 0x65, 0x73, - 0x1a, 0x17, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x11, 0x77, 0x61, 0x76, 0x65, 0x73, - 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb9, 0x01, 0x0a, - 0x08, 0x42, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x48, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x48, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x12, 0x10, 0x0a, 0x03, 0x56, 0x52, 0x46, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, - 0x56, 0x52, 0x46, 0x12, 0x18, 0x0a, 0x07, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x12, 0x35, 0x0a, - 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, - 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x77, 0x61, 0x76, 0x65, - 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x44, 0x61, 0x74, - 0x61, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x42, 0x68, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, - 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, - 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, - 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x77, 0x61, 0x76, 0x65, - 0x73, 0x2f, 0x62, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0xaa, 0x02, 0x05, 0x57, 0x61, 0x76, - 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_waves_bupdates_blockchain_updates_proto_rawDescOnce sync.Once - file_waves_bupdates_blockchain_updates_proto_rawDescData = file_waves_bupdates_blockchain_updates_proto_rawDesc -) - -func file_waves_bupdates_blockchain_updates_proto_rawDescGZIP() []byte { - file_waves_bupdates_blockchain_updates_proto_rawDescOnce.Do(func() { - file_waves_bupdates_blockchain_updates_proto_rawDescData = protoimpl.X.CompressGZIP(file_waves_bupdates_blockchain_updates_proto_rawDescData) - }) - return file_waves_bupdates_blockchain_updates_proto_rawDescData -} - -var file_waves_bupdates_blockchain_updates_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_waves_bupdates_blockchain_updates_proto_goTypes = []interface{}{ - (*BUpdates)(nil), // 0: waves.BUpdates - (*waves.Block_Header)(nil), // 1: waves.Block.Header - (*waves.DataEntry)(nil), // 2: waves.DataEntry -} -var file_waves_bupdates_blockchain_updates_proto_depIdxs = []int32{ - 1, // 0: waves.BUpdates.BlockHeader:type_name -> waves.Block.Header - 2, // 1: waves.BUpdates.DataEntries:type_name -> waves.DataEntry - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_waves_bupdates_blockchain_updates_proto_init() } -func file_waves_bupdates_blockchain_updates_proto_init() { - if File_waves_bupdates_blockchain_updates_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_waves_bupdates_blockchain_updates_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BUpdates); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_waves_bupdates_blockchain_updates_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_waves_bupdates_blockchain_updates_proto_goTypes, - DependencyIndexes: file_waves_bupdates_blockchain_updates_proto_depIdxs, - MessageInfos: file_waves_bupdates_blockchain_updates_proto_msgTypes, - }.Build() - File_waves_bupdates_blockchain_updates_proto = out.File - file_waves_bupdates_blockchain_updates_proto_rawDesc = nil - file_waves_bupdates_blockchain_updates_proto_goTypes = nil - file_waves_bupdates_blockchain_updates_proto_depIdxs = nil -} diff --git a/pkg/grpc/l2/blockchain_info/blockchain_info.pb.go b/pkg/grpc/l2/blockchain_info/blockchain_info.pb.go new file mode 100644 index 000000000..f7a08cc5e --- /dev/null +++ b/pkg/grpc/l2/blockchain_info/blockchain_info.pb.go @@ -0,0 +1,251 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v3.12.4 +// source: blockchain_info.proto + +package blockchain_info + +import ( + waves "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type BlockInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Height uint64 `protobuf:"varint,1,opt,name=Height,proto3" json:"Height,omitempty"` + VRF []byte `protobuf:"bytes,2,opt,name=VRF,proto3" json:"VRF,omitempty"` + BlockID []byte `protobuf:"bytes,3,opt,name=BlockID,proto3" json:"BlockID,omitempty"` + BlockHeader *waves.Block_Header `protobuf:"bytes,4,opt,name=BlockHeader,proto3" json:"BlockHeader,omitempty"` +} + +func (x *BlockInfo) Reset() { + *x = BlockInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_blockchain_info_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BlockInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BlockInfo) ProtoMessage() {} + +func (x *BlockInfo) ProtoReflect() protoreflect.Message { + mi := &file_blockchain_info_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BlockInfo.ProtoReflect.Descriptor instead. +func (*BlockInfo) Descriptor() ([]byte, []int) { + return file_blockchain_info_proto_rawDescGZIP(), []int{0} +} + +func (x *BlockInfo) GetHeight() uint64 { + if x != nil { + return x.Height + } + return 0 +} + +func (x *BlockInfo) GetVRF() []byte { + if x != nil { + return x.VRF + } + return nil +} + +func (x *BlockInfo) GetBlockID() []byte { + if x != nil { + return x.BlockID + } + return nil +} + +func (x *BlockInfo) GetBlockHeader() *waves.Block_Header { + if x != nil { + return x.BlockHeader + } + return nil +} + +type L2ContractDataEntries struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DataEntries []*waves.DataEntry `protobuf:"bytes,5,rep,name=DataEntries,proto3" json:"DataEntries,omitempty"` +} + +func (x *L2ContractDataEntries) Reset() { + *x = L2ContractDataEntries{} + if protoimpl.UnsafeEnabled { + mi := &file_blockchain_info_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *L2ContractDataEntries) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*L2ContractDataEntries) ProtoMessage() {} + +func (x *L2ContractDataEntries) ProtoReflect() protoreflect.Message { + mi := &file_blockchain_info_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use L2ContractDataEntries.ProtoReflect.Descriptor instead. +func (*L2ContractDataEntries) Descriptor() ([]byte, []int) { + return file_blockchain_info_proto_rawDescGZIP(), []int{1} +} + +func (x *L2ContractDataEntries) GetDataEntries() []*waves.DataEntry { + if x != nil { + return x.DataEntries + } + return nil +} + +var File_blockchain_info_proto protoreflect.FileDescriptor + +var file_blockchain_info_proto_rawDesc = []byte{ + 0x0a, 0x15, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x66, + 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x1a, 0x17, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x1a, 0x11, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x86, 0x01, 0x0a, 0x09, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x6e, + 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x06, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x56, 0x52, + 0x46, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x56, 0x52, 0x46, 0x12, 0x18, 0x0a, 0x07, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x12, 0x35, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x61, + 0x76, 0x65, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x52, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, 0x4b, 0x0a, + 0x15, 0x4c, 0x32, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x44, 0x61, 0x74, 0x61, 0x45, + 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, + 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x77, 0x61, + 0x76, 0x65, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x44, + 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x42, 0x62, 0x0a, 0x1a, 0x63, 0x6f, + 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, + 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, + 0x72, 0x70, 0x63, 0x2f, 0x6c, 0x32, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0xaa, 0x02, 0x05, 0x57, 0x61, 0x76, 0x65, 0x73, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_blockchain_info_proto_rawDescOnce sync.Once + file_blockchain_info_proto_rawDescData = file_blockchain_info_proto_rawDesc +) + +func file_blockchain_info_proto_rawDescGZIP() []byte { + file_blockchain_info_proto_rawDescOnce.Do(func() { + file_blockchain_info_proto_rawDescData = protoimpl.X.CompressGZIP(file_blockchain_info_proto_rawDescData) + }) + return file_blockchain_info_proto_rawDescData +} + +var file_blockchain_info_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_blockchain_info_proto_goTypes = []interface{}{ + (*BlockInfo)(nil), // 0: blockchain_info.BlockInfo + (*L2ContractDataEntries)(nil), // 1: blockchain_info.L2ContractDataEntries + (*waves.Block_Header)(nil), // 2: waves.Block.Header + (*waves.DataEntry)(nil), // 3: waves.DataEntry +} +var file_blockchain_info_proto_depIdxs = []int32{ + 2, // 0: blockchain_info.BlockInfo.BlockHeader:type_name -> waves.Block.Header + 3, // 1: blockchain_info.L2ContractDataEntries.DataEntries:type_name -> waves.DataEntry + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_blockchain_info_proto_init() } +func file_blockchain_info_proto_init() { + if File_blockchain_info_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_blockchain_info_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BlockInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_blockchain_info_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*L2ContractDataEntries); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_blockchain_info_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_blockchain_info_proto_goTypes, + DependencyIndexes: file_blockchain_info_proto_depIdxs, + MessageInfos: file_blockchain_info_proto_msgTypes, + }.Build() + File_blockchain_info_proto = out.File + file_blockchain_info_proto_rawDesc = nil + file_blockchain_info_proto_goTypes = nil + file_blockchain_info_proto_depIdxs = nil +} diff --git a/pkg/grpc/l2/blockchain_info/blockchain_info.proto b/pkg/grpc/l2/blockchain_info/blockchain_info.proto new file mode 100644 index 000000000..f168f4fb6 --- /dev/null +++ b/pkg/grpc/l2/blockchain_info/blockchain_info.proto @@ -0,0 +1,24 @@ +syntax = "proto3"; + +package blockchain_info; +option java_package = "com.wavesplatform.protobuf"; +option csharp_namespace = "Waves"; +option go_package = "github.com/wavesplatform/gowaves/pkg/grpc/l2/blockchain_info"; + +import "waves/transaction.proto"; +import "waves/block.proto"; + + +message BlockInfo { + uint64 Height = 1; + bytes VRF = 2; + bytes BlockID = 3; + waves.Block.Header BlockHeader = 4; +} + +message L2ContractDataEntries { + repeated waves.DataEntry DataEntries = 5; +} + + + diff --git a/pkg/grpc/generated/waves/bupdates/blockchain_updates_vtproto.pb.go b/pkg/grpc/l2/blockchain_info/blockchain_info_vtproto.pb.go similarity index 59% rename from pkg/grpc/generated/waves/bupdates/blockchain_updates_vtproto.pb.go rename to pkg/grpc/l2/blockchain_info/blockchain_info_vtproto.pb.go index 83efb89a2..8ab85b253 100644 --- a/pkg/grpc/generated/waves/bupdates/blockchain_updates_vtproto.pb.go +++ b/pkg/grpc/l2/blockchain_info/blockchain_info_vtproto.pb.go @@ -1,13 +1,14 @@ // Code generated by protoc-gen-go-vtproto. DO NOT EDIT. // protoc-gen-go-vtproto version: v0.6.0 -// source: waves/bupdates/blockchain_updates.proto +// source: blockchain_info.proto -package bupdates +package blockchain_info import ( fmt "fmt" protohelpers "github.com/planetscale/vtprotobuf/protohelpers" waves "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" + proto "google.golang.org/protobuf/proto" protoimpl "google.golang.org/protobuf/runtime/protoimpl" io "io" ) @@ -19,7 +20,7 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -func (m *BUpdates) MarshalVTStrict() (dAtA []byte, err error) { +func (m *BlockInfo) MarshalVTStrict() (dAtA []byte, err error) { if m == nil { return nil, nil } @@ -32,12 +33,12 @@ func (m *BUpdates) MarshalVTStrict() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *BUpdates) MarshalToVTStrict(dAtA []byte) (int, error) { +func (m *BlockInfo) MarshalToVTStrict(dAtA []byte) (int, error) { size := m.SizeVT() return m.MarshalToSizedBufferVTStrict(dAtA[:size]) } -func (m *BUpdates) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { +func (m *BlockInfo) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { if m == nil { return 0, nil } @@ -49,25 +50,25 @@ func (m *BUpdates) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } - if len(m.DataEntries) > 0 { - for iNdEx := len(m.DataEntries) - 1; iNdEx >= 0; iNdEx-- { - size, err := m.DataEntries[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i]) + if m.BlockHeader != nil { + if vtmsg, ok := interface{}(m.BlockHeader).(interface { + MarshalToSizedBufferVTStrict([]byte) (int, error) + }); ok { + size, err := vtmsg.MarshalToSizedBufferVTStrict(dAtA[:i]) if err != nil { return 0, err } i -= size i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) - i-- - dAtA[i] = 0x2a - } - } - if m.BlockHeader != nil { - size, err := m.BlockHeader.MarshalToSizedBufferVTStrict(dAtA[:i]) - if err != nil { - return 0, err + } else { + encoded, err := proto.Marshal(m.BlockHeader) + if err != nil { + return 0, err + } + i -= len(encoded) + copy(dAtA[i:], encoded) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(encoded))) } - i -= size - i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) i-- dAtA[i] = 0x22 } @@ -93,7 +94,64 @@ func (m *BUpdates) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *BUpdates) SizeVT() (n int) { +func (m *L2ContractDataEntries) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *L2ContractDataEntries) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *L2ContractDataEntries) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.DataEntries) > 0 { + for iNdEx := len(m.DataEntries) - 1; iNdEx >= 0; iNdEx-- { + if vtmsg, ok := interface{}(m.DataEntries[iNdEx]).(interface { + MarshalToSizedBufferVTStrict([]byte) (int, error) + }); ok { + size, err := vtmsg.MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + } else { + encoded, err := proto.Marshal(m.DataEntries[iNdEx]) + if err != nil { + return 0, err + } + i -= len(encoded) + copy(dAtA[i:], encoded) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(encoded))) + } + i-- + dAtA[i] = 0x2a + } + } + return len(dAtA) - i, nil +} + +func (m *BlockInfo) SizeVT() (n int) { if m == nil { return 0 } @@ -111,12 +169,34 @@ func (m *BUpdates) SizeVT() (n int) { n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } if m.BlockHeader != nil { - l = m.BlockHeader.SizeVT() + if size, ok := interface{}(m.BlockHeader).(interface { + SizeVT() int + }); ok { + l = size.SizeVT() + } else { + l = proto.Size(m.BlockHeader) + } n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } + n += len(m.unknownFields) + return n +} + +func (m *L2ContractDataEntries) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l if len(m.DataEntries) > 0 { for _, e := range m.DataEntries { - l = e.SizeVT() + if size, ok := interface{}(e).(interface { + SizeVT() int + }); ok { + l = size.SizeVT() + } else { + l = proto.Size(e) + } n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) } } @@ -124,7 +204,7 @@ func (m *BUpdates) SizeVT() (n int) { return n } -func (m *BUpdates) UnmarshalVT(dAtA []byte) error { +func (m *BlockInfo) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -147,10 +227,10 @@ func (m *BUpdates) UnmarshalVT(dAtA []byte) error { fieldNum := int32(wire >> 3) wireType := int(wire & 0x7) if wireType == 4 { - return fmt.Errorf("proto: BUpdates: wiretype end group for non-group") + return fmt.Errorf("proto: BlockInfo: wiretype end group for non-group") } if fieldNum <= 0 { - return fmt.Errorf("proto: BUpdates: illegal tag %d (wire type %d)", fieldNum, wire) + return fmt.Errorf("proto: BlockInfo: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { case 1: @@ -272,10 +352,69 @@ func (m *BUpdates) UnmarshalVT(dAtA []byte) error { if m.BlockHeader == nil { m.BlockHeader = &waves.Block_Header{} } - if err := m.BlockHeader.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err + if unmarshal, ok := interface{}(m.BlockHeader).(interface { + UnmarshalVT([]byte) error + }); ok { + if err := unmarshal.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + } else { + if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.BlockHeader); err != nil { + return err + } } iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *L2ContractDataEntries) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: L2ContractDataEntries: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: L2ContractDataEntries: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field DataEntries", wireType) @@ -306,8 +445,16 @@ func (m *BUpdates) UnmarshalVT(dAtA []byte) error { return io.ErrUnexpectedEOF } m.DataEntries = append(m.DataEntries, &waves.DataEntry{}) - if err := m.DataEntries[len(m.DataEntries)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { - return err + if unmarshal, ok := interface{}(m.DataEntries[len(m.DataEntries)-1]).(interface { + UnmarshalVT([]byte) error + }); ok { + if err := unmarshal.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + } else { + if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.DataEntries[len(m.DataEntries)-1]); err != nil { + return err + } } iNdEx = postIndex default: diff --git a/pkg/proto/block.go b/pkg/proto/block.go index 2afc18a5c..c7ed9d351 100644 --- a/pkg/proto/block.go +++ b/pkg/proto/block.go @@ -473,6 +473,62 @@ func (b *BlockHeader) UnmarshalHeaderFromBinary(data []byte, scheme Scheme) (err return nil } +func ProtobufHeaderToBlockHeader(ph *g.Block_Header) (*BlockHeader, error) { + if ph == nil { + return nil, errors.New("input protobuf header is nil") + } + var challengedHeader *ChallengedHeader + if ph.ChallengedHeader != nil { + ch, err := FromProtobufChallengedHeader(ph.ChallengedHeader) + if err != nil { + return nil, err + } + challengedHeader = ch + } + var stateHash *crypto.Digest + if len(ph.StateHash) > 0 { + sh, err := crypto.NewDigestFromBytes(ph.StateHash) + if err != nil { + return nil, err + } + stateHash = &sh + } + parentBlockID, err := NewBlockIDFromBytes(ph.Reference) + if err != nil { + return nil, err + } + generatorPK, err := crypto.NewPublicKeyFromBytes(ph.Generator) + if err != nil { + return nil, err + } + blockHeader := &BlockHeader{ + Version: BlockVersion(ph.Version), + Timestamp: uint64(ph.Timestamp), + Parent: parentBlockID, + Features: uint32SliceToInt16(ph.FeatureVotes), + RewardVote: ph.RewardVote, + GeneratorPublicKey: generatorPK, + TransactionsRoot: B58Bytes(ph.TransactionsRoot), + StateHash: stateHash, + ChallengedHeader: challengedHeader, + } + return blockHeader, nil +} + +func uint32SliceToInt16(s []uint32) []int16 { + var res []int16 + for _, v := range s { + res = append(res, int16(v)) + } + return res +} + +func FromProtobufChallengedHeader(ph *g.Block_Header_ChallengedHeader) (*ChallengedHeader, error) { + // Implement the conversion from g.Block_Header_ChallengedHeader to ChallengedHeader + // This function should be defined according to your ChallengedHeader structure and conversion logic + return &ChallengedHeader{}, nil +} + func AppendHeaderBytesToTransactions(headerBytes, transactions []byte) ([]byte, error) { headerLen := len(headerBytes) if headerLen < 1 { diff --git a/pkg/proto/types.go b/pkg/proto/types.go index 2d7d6d931..93758a4c7 100644 --- a/pkg/proto/types.go +++ b/pkg/proto/types.go @@ -3119,12 +3119,12 @@ func (e *DeleteDataEntry) UnmarshalJSON(value []byte) error { return nil } -// dataEntryType is the assistive structure used to get the type of DataEntry while unmarshal form JSON. -type dataEntryType struct { +// DataEntryType is the assistive structure used to get the type of DataEntry while unmarshal form JSON. +type DataEntryType struct { Type string `json:"type"` } -func guessDataEntryType(dataEntryType dataEntryType) (DataEntry, error) { +func GuessDataEntryType(dataEntryType DataEntryType) (DataEntry, error) { var r DataEntry switch dataEntryType.Type { case "integer": @@ -3147,11 +3147,11 @@ func guessDataEntryType(dataEntryType dataEntryType) (DataEntry, error) { func NewDataEntryFromJSON(data []byte) (DataEntry, error) { wrapError := func(err error) error { return errors.Wrap(err, "failed to unmarshal DataEntry from JSON") } - var et dataEntryType + var et DataEntryType if err := json.Unmarshal(data, &et); err != nil { return nil, wrapError(err) } - entry, err := guessDataEntryType(et) + entry, err := GuessDataEntryType(et) if err != nil { return nil, wrapError(err) } @@ -3196,7 +3196,7 @@ func (e DataEntries) Valid(forbidEmptyKey, utf16KeyLen bool) error { func (e *DataEntries) UnmarshalJSON(data []byte) error { wrapError := func(err error) error { return errors.Wrap(err, "failed to unmarshal DataEntries from JSON") } - var ets []dataEntryType + var ets []DataEntryType err := json.Unmarshal(data, &ets) if err != nil { return wrapError(err) @@ -3204,7 +3204,7 @@ func (e *DataEntries) UnmarshalJSON(data []byte) error { entries := make([]DataEntry, len(ets)) for i, row := range ets { - et, err := guessDataEntryType(row) + et, err := GuessDataEntryType(row) if err != nil { return wrapError(err) } diff --git a/pkg/state/accounts_data_storage.go b/pkg/state/accounts_data_storage.go index 5369d7f4e..fd9bdf3e3 100644 --- a/pkg/state/accounts_data_storage.go +++ b/pkg/state/accounts_data_storage.go @@ -242,7 +242,7 @@ func (s *accountsDataStorage) entryBytes(addr proto.Address, entryKey string) ([ func (s *accountsDataStorage) retrieveEntries(addr proto.Address) ([]proto.DataEntry, error) { addrNum, err := s.addrToNum(addr) if err != nil { - return nil, err + return nil, proto.ErrNotFound } key := accountsDataStorKey{addrNum: addrNum} iter, err := s.hs.newTopEntryIteratorByPrefix(key.accountPrefix()) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 0648a658f..8fc74110e 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -2,10 +2,9 @@ package state import ( "fmt" - "github.com/wavesplatform/gowaves/pkg/blockchainupdates" - "github.com/mr-tron/base58/base58" "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/blockchaininfo" "go.uber.org/zap" "github.com/wavesplatform/gowaves/pkg/crypto" @@ -62,7 +61,7 @@ type txAppender struct { type BlockchainUpdatesExtension struct { EnableBlockchainUpdatesPlugin bool L2ContractAddress proto.WavesAddress - BUpdatesChannel chan<- blockchainupdates.BUpdatesInfo + BUpdatesChannel chan<- blockchaininfo.BUpdatesInfo } func newTxAppender( @@ -836,7 +835,10 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { // TODO possibly run it in a goroutine? make sure goroutines run in order? if a.bUpdatesExtension != nil { if a.bUpdatesExtension.EnableBlockchainUpdatesPlugin { - a.updateBlockchainUpdateInfo(blockInfo, params.block) + err := a.updateBlockchainUpdateInfo(blockInfo, params.block) + if err != nil { + return err + } } } @@ -863,11 +865,11 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { func (a *txAppender) updateBlockchainUpdateInfo(blockInfo *proto.BlockInfo, blockHeader *proto.BlockHeader) error { // TODO improve this by using diffs instead grabbing all the records every time dataEntries, err := a.ia.state.RetrieveEntries(proto.NewRecipientFromAddress(a.bUpdatesExtension.L2ContractAddress)) - if err != nil { + if err != nil && !errors.Is(err, proto.ErrNotFound) { return err } - bUpdatesInfo := blockchainupdates.BUpdatesInfo{ + bUpdatesInfo := blockchaininfo.BUpdatesInfo{ Height: blockInfo.Height, VRF: blockInfo.VRF, BlockID: blockHeader.BlockID(), diff --git a/pkg/state/state.go b/pkg/state/state.go index 0c07d3988..8d5343756 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -2200,6 +2200,9 @@ func (s *stateManager) RetrieveEntries(account proto.Recipient) ([]proto.DataEnt } entries, err := s.stor.accountsDataStor.retrieveEntries(addr) if err != nil { + if errors.Is(err, proto.ErrNotFound) { + return nil, err + } return nil, wrapErr(RetrievalError, err) } return entries, nil From bdc88540d94de21d7d2f7f8d04c772e1aaffb69b Mon Sep 17 00:00:00 2001 From: esuwu Date: Thu, 18 Jul 2024 23:56:26 -0500 Subject: [PATCH 10/50] Added state comparison --- cmd/blockchaininfo/nats_subscriber.go | 82 +++++++++++++ cmd/blockchaininfo/nuts_subscriber.go | 81 ------------- cmd/node/node.go | 2 +- .../{nuts_publisher.go => nats_publisher.go} | 45 ++++--- .../{nuts_server.go => nats_server.go} | 0 pkg/blockchaininfo/proto_converters.go | 25 +--- pkg/blockchaininfo/topics.go | 17 --- pkg/blockchaininfo/types.go | 114 ++++++++++++++++++ 8 files changed, 227 insertions(+), 139 deletions(-) create mode 100644 cmd/blockchaininfo/nats_subscriber.go delete mode 100644 cmd/blockchaininfo/nuts_subscriber.go rename pkg/blockchaininfo/{nuts_publisher.go => nats_publisher.go} (74%) rename pkg/blockchaininfo/{nuts_server.go => nats_server.go} (100%) create mode 100644 pkg/blockchaininfo/types.go diff --git a/cmd/blockchaininfo/nats_subscriber.go b/cmd/blockchaininfo/nats_subscriber.go new file mode 100644 index 000000000..bc1938154 --- /dev/null +++ b/cmd/blockchaininfo/nats_subscriber.go @@ -0,0 +1,82 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "github.com/nats-io/nats.go" + "github.com/wavesplatform/gowaves/pkg/blockchaininfo" + g "github.com/wavesplatform/gowaves/pkg/grpc/l2/blockchain_info" + "github.com/wavesplatform/gowaves/pkg/proto" + "log" + "os" + "os/signal" + "syscall" +) + +func printBlockInfo(blockInfoProto *g.BlockInfo) error { + blockInfo, err := blockchaininfo.BUpdatesInfoFromProto(blockInfoProto) + if err != nil { + return err + } + blockInfoJson, err := json.Marshal(blockInfo) + fmt.Println(string(blockInfoJson)) + return nil +} + +func printContractInfo(contractInfoProto *g.L2ContractDataEntries, scheme proto.Scheme) error { + contractInfo, err := blockchaininfo.L2ContractDataEntriesFromProto(contractInfoProto, scheme) + if err != nil { + return err + } + contractInfoJson, err := json.Marshal(contractInfo) + fmt.Println(string(contractInfoJson)) + return nil +} + +func main() { + scheme := proto.TestNetScheme + ctx, done := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) + defer done() + // Connect to a NATS server + nc, err := nats.Connect(nats.DefaultURL) + if err != nil { + log.Fatal(err) + } + defer nc.Close() + + _, err = nc.Subscribe(blockchaininfo.BlockUpdates, func(msg *nats.Msg) { + blockUpdatesInfo := new(g.BlockInfo) + err := blockUpdatesInfo.UnmarshalVT(msg.Data) + if err != nil { + return + } + + err = printBlockInfo(blockUpdatesInfo) + if err != nil { + return + } + log.Printf("Received on %s:\n", msg.Subject) + }) + if err != nil { + log.Fatal(err) + } + _, err = nc.Subscribe(blockchaininfo.ContractUpdates, func(msg *nats.Msg) { + contractUpdatesInfo := new(g.L2ContractDataEntries) + err := contractUpdatesInfo.UnmarshalVT(msg.Data) + if err != nil { + return + } + log.Printf("Received on %s:\n", msg.Subject) + + err = printContractInfo(contractUpdatesInfo, scheme) + if err != nil { + return + } + }) + if err != nil { + log.Fatal(err) + } + <-ctx.Done() + log.Println("Terminations of nats subscriber") +} diff --git a/cmd/blockchaininfo/nuts_subscriber.go b/cmd/blockchaininfo/nuts_subscriber.go deleted file mode 100644 index 825ba030f..000000000 --- a/cmd/blockchaininfo/nuts_subscriber.go +++ /dev/null @@ -1,81 +0,0 @@ -package main - -import ( - "encoding/json" - "fmt" - "github.com/nats-io/nats.go" - "github.com/wavesplatform/gowaves/pkg/blockchaininfo" - g "github.com/wavesplatform/gowaves/pkg/grpc/l2/blockchain_info" - "log" -) - -func printBlockInfo(blockInfoProto *g.BlockInfo) error { - blockInfo, err := blockchaininfo.BUpdatesInfoFromProto(blockInfoProto) - if err != nil { - return err - } - blockInfoJson, err := json.Marshal(blockInfo) - fmt.Println(string(blockInfoJson)) - return nil -} - -func printContractInfo(contractInfoProto *g.L2ContractDataEntries) error { - contractInfo, err := blockchaininfo.L2ContractDataEntriesFromProto(contractInfoProto) - if err != nil { - return err - } - contractInfoJson, err := json.Marshal(contractInfo) - fmt.Println(string(contractInfoJson)) - return nil -} - -func main() { - // Connect to a NATS server - nc, err := nats.Connect(nats.DefaultURL) - if err != nil { - log.Fatal(err) - } - defer nc.Close() - - topic := blockchaininfo.BlockUpdates - //for _, topic := range blockchaininfo.Topics { - _, err = nc.Subscribe(topic, func(msg *nats.Msg) { - - //log.Printf("Received on %s: %s\n", msg.Subject, string(msg.Data)) - if topic == blockchaininfo.BlockUpdates { - blockUpdatesInfo := new(g.BlockInfo) - err := blockUpdatesInfo.UnmarshalVT(msg.Data) - if err != nil { - return - } - - err = printBlockInfo(blockUpdatesInfo) - if err != nil { - return - } - log.Printf("Received on %s:\n", msg.Subject) - } - - if topic == blockchaininfo.ContractUpdates { - contractUpdatesInfo := new(g.L2ContractDataEntries) - err := contractUpdatesInfo.UnmarshalVT(msg.Data) - if err != nil { - return - } - log.Printf("Received on %s:\n", msg.Subject) - - err = printContractInfo(contractUpdatesInfo) - if err != nil { - return - } - - } - - }) - if err != nil { - log.Fatal(err) - } - //} - // Block main goroutine so the server keeps running - select {} -} diff --git a/cmd/node/node.go b/cmd/node/node.go index 45a1a044f..d79d908b8 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -394,7 +394,7 @@ func main() { var bUpdatesExtension *state.BlockchainUpdatesExtension if nc.enableBlockchainUpdatesPlugin { updatesChannel := make(chan blockchaininfo.BUpdatesInfo) - bUpdatesExtensionState := blockchaininfo.NewBUpdatesExtensionState(2000) + bUpdatesExtensionState := blockchaininfo.NewBUpdatesExtensionState(2000, cfg.AddressSchemeCharacter) l2address, err := proto.NewAddressFromString("3MsqKJ6o1ABE37676cHHBxJRs6huYTt72ch") if err != nil { diff --git a/pkg/blockchaininfo/nuts_publisher.go b/pkg/blockchaininfo/nats_publisher.go similarity index 74% rename from pkg/blockchaininfo/nuts_publisher.go rename to pkg/blockchaininfo/nats_publisher.go index d41888cab..f23b0c975 100644 --- a/pkg/blockchaininfo/nuts_publisher.go +++ b/pkg/blockchaininfo/nats_publisher.go @@ -9,26 +9,26 @@ import ( "log" ) -type BUpdatesInfo struct { - Height uint64 - VRF proto.B58Bytes - BlockID proto.BlockID - BlockHeader *proto.BlockHeader - AllDataEntries []proto.DataEntry -} - type BUpdatesExtensionState struct { currentState *BUpdatesInfo previousState *BUpdatesInfo // this information is what was just published Limit uint64 + scheme proto.Scheme } -func NewBUpdatesExtensionState(limit uint64) *BUpdatesExtensionState { - return &BUpdatesExtensionState{Limit: limit} +func NewBUpdatesExtensionState(limit uint64, scheme proto.Scheme) *BUpdatesExtensionState { + return &BUpdatesExtensionState{Limit: limit, scheme: scheme} } -func (bu *BUpdatesExtensionState) hasStateChanged() { - +func (bu *BUpdatesExtensionState) hasStateChanged() (bool, error) { + statesAreEqual, err := statesEqual(*bu, bu.scheme) + if err != nil { + return false, err + } + if statesAreEqual { + return false, nil + } + return true, nil } func (bu *BUpdatesExtensionState) publishUpdates(updates BUpdatesInfo, nc *nats.Conn, scheme proto.Scheme) error { @@ -96,15 +96,24 @@ func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(ctx context.Cont return } // update current state - + bu.currentState = &updates // compare the current state to the previous state - - // if there is any diff, send the update - err := bu.publishUpdates(updates, nc, scheme) - log.Printf("published") + stateChanged, err := bu.hasStateChanged() if err != nil { - log.Printf("failed to publish updates") + log.Printf("failed to compare current and previous states, %v", err) + return } + // if there is any diff, send the update + fmt.Println(stateChanged) + if stateChanged { + err := bu.publishUpdates(updates, nc, scheme) + log.Printf("published") + if err != nil { + log.Printf("failed to publish updates") + } + bu.previousState = &updates + } + case <-ctx.Done(): return } diff --git a/pkg/blockchaininfo/nuts_server.go b/pkg/blockchaininfo/nats_server.go similarity index 100% rename from pkg/blockchaininfo/nuts_server.go rename to pkg/blockchaininfo/nats_server.go diff --git a/pkg/blockchaininfo/proto_converters.go b/pkg/blockchaininfo/proto_converters.go index f598ed69c..5511c840f 100644 --- a/pkg/blockchaininfo/proto_converters.go +++ b/pkg/blockchaininfo/proto_converters.go @@ -1,7 +1,6 @@ package blockchaininfo import ( - "errors" "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" g "github.com/wavesplatform/gowaves/pkg/grpc/l2/blockchain_info" "github.com/wavesplatform/gowaves/pkg/proto" @@ -49,32 +48,14 @@ func L2ContractDataEntriesToProto(dataEntries []proto.DataEntry) *g.L2ContractDa } } -func L2ContractDataEntriesFromProto(protoDataEntries *g.L2ContractDataEntries) (L2ContractDataEntries, error) { +func L2ContractDataEntriesFromProto(protoDataEntries *g.L2ContractDataEntries, scheme proto.Scheme) (L2ContractDataEntries, error) { + converter := proto.ProtobufConverter{FallbackChainID: scheme} var dataEntries []proto.DataEntry for _, protoEntry := range protoDataEntries.DataEntries { - dataEntryType := proto.DataEntryType{Type: protoEntry.Key} - entry, err := proto.GuessDataEntryType(dataEntryType) + entry, err := converter.Entry(protoEntry) if err != nil { return L2ContractDataEntries{}, err } - entry.SetKey(protoEntry.Key) - switch e := entry.(type) { - case *proto.IntegerDataEntry: - e.Value = protoEntry.GetIntValue() - entry = e - case *proto.BooleanDataEntry: - e.Value = protoEntry.GetBoolValue() - entry = e - case *proto.BinaryDataEntry: - e.Value = protoEntry.GetBinaryValue() - entry = e - case *proto.StringDataEntry: - e.Value = protoEntry.GetStringValue() - entry = e - case *proto.DeleteDataEntry: - default: - return L2ContractDataEntries{}, errors.New("failed to convert proto data entries into data entries") - } dataEntries = append(dataEntries, entry) } diff --git a/pkg/blockchaininfo/topics.go b/pkg/blockchaininfo/topics.go index 167e9d730..a94cecf71 100644 --- a/pkg/blockchaininfo/topics.go +++ b/pkg/blockchaininfo/topics.go @@ -1,7 +1,5 @@ package blockchaininfo -import "github.com/wavesplatform/gowaves/pkg/proto" - /* Topics */ const ( BlockUpdates = "block_topic" @@ -10,18 +8,3 @@ const ( ) var Topics = []string{BlockUpdates, microblockUpdates, ContractUpdates} - -// block updates - -type BlockUpdatesInfo struct { - Height uint64 `json:"height"` - VRF proto.B58Bytes `json:"vrf"` - BlockID proto.BlockID `json:"block_id"` - BlockHeader *proto.BlockHeader `json:"block_header"` -} - -// l2 contract data entries - -type L2ContractDataEntries struct { - AllDataEntries []proto.DataEntry `json:"all_data_entries"` -} diff --git a/pkg/blockchaininfo/types.go b/pkg/blockchaininfo/types.go new file mode 100644 index 000000000..b0cbf1ff9 --- /dev/null +++ b/pkg/blockchaininfo/types.go @@ -0,0 +1,114 @@ +package blockchaininfo + +import ( + "bytes" + "github.com/wavesplatform/gowaves/pkg/proto" +) + +// block updates +type BlockUpdatesInfo struct { + Height uint64 `json:"height"` + VRF proto.B58Bytes `json:"vrf"` + BlockID proto.BlockID `json:"block_id"` + BlockHeader *proto.BlockHeader `json:"block_header"` +} + +// l2 contract data entries +type L2ContractDataEntries struct { + AllDataEntries []proto.DataEntry `json:"all_data_entries"` +} + +type BUpdatesInfo struct { + Height uint64 + VRF proto.B58Bytes + BlockID proto.BlockID + BlockHeader *proto.BlockHeader + AllDataEntries []proto.DataEntry +} + +// TODO wrap errors + +func compareBUpdatesInfo(a, b BUpdatesInfo, scheme proto.Scheme) (bool, error) { + if a.Height != b.Height { + return false, nil + } + if !bytes.Equal(a.VRF, b.VRF) { + return false, nil + } + if !bytes.Equal(a.BlockID.Bytes(), b.BlockID.Bytes()) { + return false, nil + } + equalHeaders, err := compareBlockHeader(a.BlockHeader, b.BlockHeader, scheme) + if err != nil { + return false, err + } + if !equalHeaders { + return false, nil + } + + equalEntries, err := compareDataEntries(a.AllDataEntries, b.AllDataEntries) + if err != nil { + return false, err + } + if !equalEntries { + return false, nil + } + + return true, nil +} + +func compareBlockHeader(a, b *proto.BlockHeader, scheme proto.Scheme) (bool, error) { + if a == nil || b == nil { + return a == b, nil // both nil or one of them is nil + } + blockAbytes, err := a.MarshalHeader(scheme) + if err != nil { + return false, err + } + + blockBbytes, err := b.MarshalHeader(scheme) + if err != nil { + return false, err + } + + return bytes.Equal(blockAbytes, blockBbytes), nil +} + +func compareDataEntries(a, b []proto.DataEntry) (bool, error) { + if len(a) != len(b) { + return false, nil + } + for i := range a { + equal, err := areEntriesEqual(a[i], b[i]) + if err != nil { + return false, err + } + if !equal { + return false, nil + } + } + return true, nil +} + +func areEntriesEqual(a, b proto.DataEntry) (bool, error) { + if a.GetKey() != b.GetKey() { + return false, nil + } + aValueBytes, err := a.MarshalValue() + if err != nil { + return false, err + } + bValue, err := b.MarshalValue() + if err != nil { + return false, err + } + + return bytes.Equal(aValueBytes, bValue), nil +} + +func statesEqual(state BUpdatesExtensionState, scheme proto.Scheme) (bool, error) { + if state.currentState == nil || state.previousState == nil { + return state.currentState == state.previousState, nil // both nil or one of them is nil + } + return compareBUpdatesInfo(*state.currentState, *state.previousState, scheme) +} From 19cc3028fa91c1a15b9cbb2db12018d65470d4ee Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 22 Jul 2024 00:19:35 -0500 Subject: [PATCH 11/50] Added a draft for retrieving history entries --- pkg/state/accounts_data_storage.go | 73 ++++++++++++++++++++++++++++++ pkg/state/state.go | 15 ++++++ 2 files changed, 88 insertions(+) diff --git a/pkg/state/accounts_data_storage.go b/pkg/state/accounts_data_storage.go index fd9bdf3e3..731f9b58f 100644 --- a/pkg/state/accounts_data_storage.go +++ b/pkg/state/accounts_data_storage.go @@ -282,6 +282,79 @@ func (s *accountsDataStorage) retrieveEntries(addr proto.Address) ([]proto.DataE return entries, nil } +func (s *accountsDataStorage) RetrieveEntriesAtHeight(addr proto.Address, height uint64) ([]proto.DataEntry, error) { + addrNum, err := s.addrToNum(addr) + if err != nil { + return nil, proto.ErrNotFound + } + key := accountsDataStorKey{addrNum: addrNum} + + recordBytes, err := s.hs.entryDataAtHeight(key.bytes(), height) + if errors.Is(err, keyvalue.ErrNotFound) || errors.Is(err, errEmptyHist) || recordBytes == nil { + // 0 votes for unknown feature. + return nil, keyvalue.ErrNotFound + } + if err != nil { + return nil, errors.Wrap(err, "failed to retrieve data at height") + } + + var dataEntries proto.DataEntries + pos := 0 + + for { + // Check if there's enough data for a key size + if pos+2 > len(recordBytes) { + break + } + + keySize := binary.BigEndian.Uint16(recordBytes[pos : pos+2]) + pos += 2 + + // Check if there's enough data for the key + if pos+int(keySize) > len(recordBytes) { + break + } + + key := recordBytes[pos : pos+int(keySize)] + pos += int(keySize) + + // Check if there's enough data for a value size + if pos+2 > len(recordBytes) { + break + } + + valueSize := binary.BigEndian.Uint16(recordBytes[pos : pos+2]) + pos += 2 + + // Check if there's enough data for the value + if pos+int(valueSize) > len(recordBytes) { + break + } + + value := recordBytes[pos : pos+int(valueSize)] + pos += int(valueSize) + + var record dataEntryRecord + if err := record.unmarshalBinary(value); err != nil { + return nil, err + } + + var entryKey accountsDataStorKey + if err := entryKey.unmarshal(key); err != nil { + return nil, err + } + + entry, err := proto.NewDataEntryFromValueBytes(record.value) + if err != nil { + return nil, err + } + + entry.SetKey(entryKey.entryKey) + dataEntries = append(dataEntries, entry) + } + return dataEntries, nil +} + func (s *accountsDataStorage) newestEntryExists(addr proto.Address) (bool, error) { addrNum, newest, err := s.newestAddrToNum(addr) if err != nil { diff --git a/pkg/state/state.go b/pkg/state/state.go index 8d5343756..adaa4c119 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -2208,6 +2208,21 @@ func (s *stateManager) RetrieveEntries(account proto.Recipient) ([]proto.DataEnt return entries, nil } +func (s *stateManager) RetrieveEntriesAtHeight(account proto.Recipient) ([]proto.DataEntry, error) { + addr, err := s.recipientToAddress(account) + if err != nil { + return nil, wrapErr(RetrievalError, err) + } + entries, err := s.stor.accountsDataStor.retrieveEntries(addr) + if err != nil { + if errors.Is(err, proto.ErrNotFound) { + return nil, err + } + return nil, wrapErr(RetrievalError, err) + } + return entries, nil +} + func (s *stateManager) IsStateUntouched(account proto.Recipient) (bool, error) { addr, err := s.recipientToAddress(account) if err != nil { From b6fb33c76371aff14a61636eb39c2e5dbb3a098c Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 22 Jul 2024 00:21:00 -0500 Subject: [PATCH 12/50] Renamed a function --- pkg/state/accounts_data_storage.go | 2 +- pkg/state/state.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/state/accounts_data_storage.go b/pkg/state/accounts_data_storage.go index 731f9b58f..19acbf51a 100644 --- a/pkg/state/accounts_data_storage.go +++ b/pkg/state/accounts_data_storage.go @@ -282,7 +282,7 @@ func (s *accountsDataStorage) retrieveEntries(addr proto.Address) ([]proto.DataE return entries, nil } -func (s *accountsDataStorage) RetrieveEntriesAtHeight(addr proto.Address, height uint64) ([]proto.DataEntry, error) { +func (s *accountsDataStorage) retrieveEntriesAtHeight(addr proto.Address, height uint64) ([]proto.DataEntry, error) { addrNum, err := s.addrToNum(addr) if err != nil { return nil, proto.ErrNotFound diff --git a/pkg/state/state.go b/pkg/state/state.go index adaa4c119..9eef87727 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -2208,12 +2208,12 @@ func (s *stateManager) RetrieveEntries(account proto.Recipient) ([]proto.DataEnt return entries, nil } -func (s *stateManager) RetrieveEntriesAtHeight(account proto.Recipient) ([]proto.DataEntry, error) { +func (s *stateManager) RetrieveEntriesAtHeight(account proto.Recipient, height uint64) ([]proto.DataEntry, error) { addr, err := s.recipientToAddress(account) if err != nil { return nil, wrapErr(RetrievalError, err) } - entries, err := s.stor.accountsDataStor.retrieveEntries(addr) + entries, err := s.stor.accountsDataStor.retrieveEntriesAtHeight(addr, height) if err != nil { if errors.Is(err, proto.ErrNotFound) { return nil, err From dca31ee29d22a27314b40a4f63e0b2c5ed4d6251 Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 31 Jul 2024 23:54:22 -0500 Subject: [PATCH 13/50] Fixed most of the linter issues --- cmd/blockchaininfo/nats_subscriber.go | 43 ++++++----- cmd/node/node.go | 14 ++-- pkg/blockchaininfo/nats_publisher.go | 99 +++++++++++++++----------- pkg/blockchaininfo/nats_server.go | 9 +-- pkg/blockchaininfo/proto_converters.go | 28 ++++---- pkg/blockchaininfo/topics.go | 4 +- pkg/blockchaininfo/types.go | 24 +++---- pkg/proto/block.go | 41 +++++++++-- pkg/proto/types.go | 6 +- pkg/state/accounts_data_storage.go | 14 ++-- pkg/state/appender.go | 22 +++--- pkg/state/invoke_applier_test.go | 2 +- pkg/state/state_test.go | 6 +- 13 files changed, 187 insertions(+), 125 deletions(-) diff --git a/cmd/blockchaininfo/nats_subscriber.go b/cmd/blockchaininfo/nats_subscriber.go index bc1938154..b84e4e7c3 100644 --- a/cmd/blockchaininfo/nats_subscriber.go +++ b/cmd/blockchaininfo/nats_subscriber.go @@ -3,15 +3,15 @@ package main import ( "context" "encoding/json" - "fmt" - "github.com/nats-io/nats.go" - "github.com/wavesplatform/gowaves/pkg/blockchaininfo" - g "github.com/wavesplatform/gowaves/pkg/grpc/l2/blockchain_info" - "github.com/wavesplatform/gowaves/pkg/proto" "log" "os" "os/signal" "syscall" + + "github.com/nats-io/nats.go" + "github.com/wavesplatform/gowaves/pkg/blockchaininfo" + g "github.com/wavesplatform/gowaves/pkg/grpc/l2/blockchain_info" + "github.com/wavesplatform/gowaves/pkg/proto" ) func printBlockInfo(blockInfoProto *g.BlockInfo) error { @@ -19,8 +19,11 @@ func printBlockInfo(blockInfoProto *g.BlockInfo) error { if err != nil { return err } - blockInfoJson, err := json.Marshal(blockInfo) - fmt.Println(string(blockInfoJson)) + blockInfoJSON, err := json.Marshal(blockInfo) + if err != nil { + return err + } + log.Println(string(blockInfoJSON)) return nil } @@ -29,8 +32,11 @@ func printContractInfo(contractInfoProto *g.L2ContractDataEntries, scheme proto. if err != nil { return err } - contractInfoJson, err := json.Marshal(contractInfo) - fmt.Println(string(contractInfoJson)) + contractInfoJSON, err := json.Marshal(contractInfo) + if err != nil { + return err + } + log.Println(string(contractInfoJSON)) return nil } @@ -41,14 +47,16 @@ func main() { // Connect to a NATS server nc, err := nats.Connect(nats.DefaultURL) if err != nil { - log.Fatal(err) + log.Print(err) + return } defer nc.Close() _, err = nc.Subscribe(blockchaininfo.BlockUpdates, func(msg *nats.Msg) { blockUpdatesInfo := new(g.BlockInfo) - err := blockUpdatesInfo.UnmarshalVT(msg.Data) - if err != nil { + unmrshlErr := blockUpdatesInfo.UnmarshalVT(msg.Data) + if unmrshlErr != nil { + log.Printf("failed to unmarshal block updates, %v", unmrshlErr) return } @@ -59,12 +67,14 @@ func main() { log.Printf("Received on %s:\n", msg.Subject) }) if err != nil { - log.Fatal(err) + log.Printf("failed to subscribe to block updates, %v", err) + return } _, err = nc.Subscribe(blockchaininfo.ContractUpdates, func(msg *nats.Msg) { contractUpdatesInfo := new(g.L2ContractDataEntries) - err := contractUpdatesInfo.UnmarshalVT(msg.Data) - if err != nil { + unmrshlErr := contractUpdatesInfo.UnmarshalVT(msg.Data) + if unmrshlErr != nil { + log.Printf("failed to unmarshal contract updates, %v", unmrshlErr) return } log.Printf("Received on %s:\n", msg.Subject) @@ -75,7 +85,8 @@ func main() { } }) if err != nil { - log.Fatal(err) + log.Printf("failed to subscribe to contract updates, %v", err) + return } <-ctx.Done() log.Println("Terminations of nats subscriber") diff --git a/cmd/node/node.go b/cmd/node/node.go index d79d908b8..024094dc1 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -6,7 +6,6 @@ import ( "errors" "flag" "fmt" - "github.com/wavesplatform/gowaves/pkg/blockchaininfo" "math" "math/big" "net/http" @@ -19,10 +18,8 @@ import ( "time" "github.com/prometheus/client_golang/prometheus/promhttp" - "go.uber.org/zap" - "go.uber.org/zap/zapcore" - "github.com/wavesplatform/gowaves/pkg/api" + "github.com/wavesplatform/gowaves/pkg/blockchaininfo" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/grpc/server" "github.com/wavesplatform/gowaves/pkg/libs/microblock_cache" @@ -49,6 +46,8 @@ import ( "github.com/wavesplatform/gowaves/pkg/util/fdlimit" "github.com/wavesplatform/gowaves/pkg/versioning" "github.com/wavesplatform/gowaves/pkg/wallet" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" ) const ( @@ -394,10 +393,11 @@ func main() { var bUpdatesExtension *state.BlockchainUpdatesExtension if nc.enableBlockchainUpdatesPlugin { updatesChannel := make(chan blockchaininfo.BUpdatesInfo) - bUpdatesExtensionState := blockchaininfo.NewBUpdatesExtensionState(2000, cfg.AddressSchemeCharacter) + bUpdatesExtensionState := blockchaininfo.NewBUpdatesExtensionState(blockchaininfo.StoreBlocksLimit, + cfg.AddressSchemeCharacter) - l2address, err := proto.NewAddressFromString("3MsqKJ6o1ABE37676cHHBxJRs6huYTt72ch") - if err != nil { + l2address, cnvrtErr := proto.NewAddressFromString("3MsqKJ6o1ABE37676cHHBxJRs6huYTt72ch") + if cnvrtErr != nil { zap.S().Errorf("Failed to initialize L2 contract address") return } diff --git a/pkg/blockchaininfo/nats_publisher.go b/pkg/blockchaininfo/nats_publisher.go index f23b0c975..43a3181ed 100644 --- a/pkg/blockchaininfo/nats_publisher.go +++ b/pkg/blockchaininfo/nats_publisher.go @@ -2,13 +2,18 @@ package blockchaininfo import ( "context" - "fmt" + "log" + "github.com/nats-io/nats-server/v2/server" "github.com/nats-io/nats.go" "github.com/wavesplatform/gowaves/pkg/proto" - "log" ) +const StoreBlocksLimit = 2000 +const PortDefault = 4222 +const HostDefault = "127.0.0.1" +const ConnectionsTimeoutDefault = 5 * server.AUTH_TIMEOUT + type BUpdatesExtensionState struct { currentState *BUpdatesInfo previousState *BUpdatesInfo // this information is what was just published @@ -46,10 +51,10 @@ func (bu *BUpdatesExtensionState) publishUpdates(updates BUpdatesInfo, nc *nats. log.Printf("failed to publish message on topic %s", BlockUpdates) return err } - fmt.Printf("Published on topic: %s\n", BlockUpdates) + log.Printf("Published on topic: %s\n", BlockUpdates) /* second publish contract data entries */ - dataEntries := L2ContractDataEntriesToProto(updates.AllDataEntries) + dataEntries := L2ContractDataEntriesToProto(updates.ContractUpdatesInfo.AllDataEntries) dataEntriesProtobuf, err := dataEntries.MarshalVTStrict() if err != nil { return err @@ -60,26 +65,67 @@ func (bu *BUpdatesExtensionState) publishUpdates(updates BUpdatesInfo, nc *nats. log.Printf("failed to publish message on topic %s", ContractUpdates) return err } - fmt.Printf("Published on topic: %s\n", ContractUpdates) + log.Printf("Published on topic: %s\n", ContractUpdates) } return nil } -func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(ctx context.Context, updatesChannel <-chan BUpdatesInfo, scheme proto.Scheme) { +func handleBlockchainUpdates(updates BUpdatesInfo, ok bool, + bu *BUpdatesExtensionState, scheme proto.Scheme, nc *nats.Conn) { + if !ok { + log.Printf("the updates channel for publisher was closed") + return + } + // update current state + bu.currentState = &updates + // compare the current state to the previous state + stateChanged, cmprErr := bu.hasStateChanged() + if cmprErr != nil { + log.Printf("failed to compare current and previous states, %v", cmprErr) + return + } + // if there is any diff, send the update + if stateChanged { + pblshErr := bu.publishUpdates(updates, nc, scheme) + log.Printf("published") + if pblshErr != nil { + log.Printf("failed to publish updates, %v", pblshErr) + } + bu.previousState = &updates + } +} + +func runPublisher(ctx context.Context, updatesChannel <-chan BUpdatesInfo, + bu *BUpdatesExtensionState, scheme proto.Scheme, nc *nats.Conn) { + func(ctx context.Context, updatesChannel <-chan BUpdatesInfo) { + for { + select { + case updates, ok := <-updatesChannel: + handleBlockchainUpdates(updates, ok, bu, scheme, nc) + + case <-ctx.Done(): + return + } + } + }(ctx, updatesChannel) +} + +func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(ctx context.Context, + updatesChannel <-chan BUpdatesInfo, scheme proto.Scheme) { opts := &server.Options{ - Host: "127.0.0.1", - Port: 4222, + Host: HostDefault, + Port: PortDefault, } s, err := server.NewServer(opts) if err != nil { log.Fatalf("failed to create NATS server: %v", err) } go s.Start() - if !s.ReadyForConnections(5 * server.AUTH_TIMEOUT) { + if !s.ReadyForConnections(ConnectionsTimeoutDefault) { log.Fatal("NATS Server not ready for connections") } - log.Printf("NATS Server is running on port %d", 4222) + log.Printf("NATS Server is running on port %d", PortDefault) nc, err := nats.Connect(nats.DefaultURL) if err != nil { @@ -87,36 +133,5 @@ func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(ctx context.Cont } defer nc.Close() - func(ctx context.Context, updatesChannel <-chan BUpdatesInfo) { - for { - select { - case updates, ok := <-updatesChannel: - if !ok { - log.Printf("the updates channel for publisher was closed") - return - } - // update current state - bu.currentState = &updates - // compare the current state to the previous state - stateChanged, err := bu.hasStateChanged() - if err != nil { - log.Printf("failed to compare current and previous states, %v", err) - return - } - // if there is any diff, send the update - fmt.Println(stateChanged) - if stateChanged { - err := bu.publishUpdates(updates, nc, scheme) - log.Printf("published") - if err != nil { - log.Printf("failed to publish updates") - } - bu.previousState = &updates - } - - case <-ctx.Done(): - return - } - } - }(ctx, updatesChannel) + runPublisher(ctx, updatesChannel, bu, scheme, nc) } diff --git a/pkg/blockchaininfo/nats_server.go b/pkg/blockchaininfo/nats_server.go index 6bb307adc..75d0f6481 100644 --- a/pkg/blockchaininfo/nats_server.go +++ b/pkg/blockchaininfo/nats_server.go @@ -1,14 +1,15 @@ package blockchaininfo import ( - "github.com/nats-io/nats-server/v2/server" "log" + + "github.com/nats-io/nats-server/v2/server" ) func RunBlockchainUpdatesServer() { opts := &server.Options{ - Host: "127.0.0.1", - Port: 4222, + Host: HostDefault, + Port: PortDefault, } s, err := server.NewServer(opts) if err != nil { @@ -17,7 +18,7 @@ func RunBlockchainUpdatesServer() { go s.Start() - if !s.ReadyForConnections(10 * server.AUTH_TIMEOUT) { + if !s.ReadyForConnections(ConnectionsTimeoutDefault) { log.Fatal("NATS Server not ready for connections") } diff --git a/pkg/blockchaininfo/proto_converters.go b/pkg/blockchaininfo/proto_converters.go index 5511c840f..924e11f70 100644 --- a/pkg/blockchaininfo/proto_converters.go +++ b/pkg/blockchaininfo/proto_converters.go @@ -7,33 +7,32 @@ import ( ) func BUpdatesInfoToProto(blockInfo BUpdatesInfo, scheme proto.Scheme) (*g.BlockInfo, error) { - blockHeader, err := blockInfo.BlockHeader.HeaderToProtobufHeader(scheme) + blockHeader, err := blockInfo.BlockUpdatesInfo.BlockHeader.HeaderToProtobufHeader(scheme) if err != nil { return nil, err } return &g.BlockInfo{ - Height: blockInfo.Height, - VRF: blockInfo.VRF, - BlockID: blockInfo.BlockID.Bytes(), + Height: blockInfo.BlockUpdatesInfo.Height, + VRF: blockInfo.BlockUpdatesInfo.VRF, + BlockID: blockInfo.BlockUpdatesInfo.BlockID.Bytes(), BlockHeader: blockHeader, }, nil } -func BUpdatesInfoFromProto(blockInfoProto *g.BlockInfo) (BUpdatesInfo, error) { +func BUpdatesInfoFromProto(blockInfoProto *g.BlockInfo) (BlockUpdatesInfo, error) { blockID, err := proto.NewBlockIDFromBytes(blockInfoProto.BlockID) if err != nil { - return BUpdatesInfo{}, err + return BlockUpdatesInfo{}, err } blockHeader, err := proto.ProtobufHeaderToBlockHeader(blockInfoProto.BlockHeader) if err != nil { - return BUpdatesInfo{}, err + return BlockUpdatesInfo{}, err } - return BUpdatesInfo{ - Height: blockInfoProto.Height, - VRF: blockInfoProto.VRF, - BlockID: blockID, - BlockHeader: blockHeader, - AllDataEntries: nil, + return BlockUpdatesInfo{ + Height: blockInfoProto.Height, + VRF: blockInfoProto.VRF, + BlockID: blockID, + BlockHeader: blockHeader, }, nil } @@ -48,7 +47,8 @@ func L2ContractDataEntriesToProto(dataEntries []proto.DataEntry) *g.L2ContractDa } } -func L2ContractDataEntriesFromProto(protoDataEntries *g.L2ContractDataEntries, scheme proto.Scheme) (L2ContractDataEntries, error) { +func L2ContractDataEntriesFromProto(protoDataEntries *g.L2ContractDataEntries, + scheme proto.Scheme) (L2ContractDataEntries, error) { converter := proto.ProtobufConverter{FallbackChainID: scheme} var dataEntries []proto.DataEntry for _, protoEntry := range protoDataEntries.DataEntries { diff --git a/pkg/blockchaininfo/topics.go b/pkg/blockchaininfo/topics.go index a94cecf71..4e269c4e1 100644 --- a/pkg/blockchaininfo/topics.go +++ b/pkg/blockchaininfo/topics.go @@ -1,10 +1,10 @@ package blockchaininfo -/* Topics */ +/* Topics. */ const ( BlockUpdates = "block_topic" microblockUpdates = "microblock_topic" ContractUpdates = "contract_topi" ) -var Topics = []string{BlockUpdates, microblockUpdates, ContractUpdates} +// var Topics = []string{BlockUpdates, microblockUpdates, ContractUpdates} diff --git a/pkg/blockchaininfo/types.go b/pkg/blockchaininfo/types.go index b0cbf1ff9..ee2932bac 100644 --- a/pkg/blockchaininfo/types.go +++ b/pkg/blockchaininfo/types.go @@ -2,10 +2,11 @@ package blockchaininfo import ( "bytes" + "github.com/wavesplatform/gowaves/pkg/proto" ) -// block updates +// Block updates. type BlockUpdatesInfo struct { Height uint64 `json:"height"` VRF proto.B58Bytes `json:"vrf"` @@ -13,32 +14,29 @@ type BlockUpdatesInfo struct { BlockHeader *proto.BlockHeader `json:"block_header"` } -// l2 contract data entries +// L2 contract data entries. type L2ContractDataEntries struct { AllDataEntries []proto.DataEntry `json:"all_data_entries"` } type BUpdatesInfo struct { - Height uint64 - VRF proto.B58Bytes - BlockID proto.BlockID - BlockHeader *proto.BlockHeader - AllDataEntries []proto.DataEntry + BlockUpdatesInfo BlockUpdatesInfo + ContractUpdatesInfo L2ContractDataEntries } -// TODO wrap errors +// TODO wrap errors. func compareBUpdatesInfo(a, b BUpdatesInfo, scheme proto.Scheme) (bool, error) { - if a.Height != b.Height { + if a.BlockUpdatesInfo.Height != b.BlockUpdatesInfo.Height { return false, nil } - if !bytes.Equal(a.VRF, b.VRF) { + if !bytes.Equal(a.BlockUpdatesInfo.VRF, b.BlockUpdatesInfo.VRF) { return false, nil } - if !bytes.Equal(a.BlockID.Bytes(), b.BlockID.Bytes()) { + if !bytes.Equal(a.BlockUpdatesInfo.BlockID.Bytes(), b.BlockUpdatesInfo.BlockID.Bytes()) { return false, nil } - equalHeaders, err := compareBlockHeader(a.BlockHeader, b.BlockHeader, scheme) + equalHeaders, err := compareBlockHeader(a.BlockUpdatesInfo.BlockHeader, b.BlockUpdatesInfo.BlockHeader, scheme) if err != nil { return false, err } @@ -46,7 +44,7 @@ func compareBUpdatesInfo(a, b BUpdatesInfo, scheme proto.Scheme) (bool, error) { return false, nil } - equalEntries, err := compareDataEntries(a.AllDataEntries, b.AllDataEntries) + equalEntries, err := compareDataEntries(a.ContractUpdatesInfo.AllDataEntries, b.ContractUpdatesInfo.AllDataEntries) if err != nil { return false, err } diff --git a/pkg/proto/block.go b/pkg/proto/block.go index c7ed9d351..2da4031b3 100644 --- a/pkg/proto/block.go +++ b/pkg/proto/block.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/binary" "encoding/json" + "fmt" "io" "github.com/jinzhu/copier" @@ -523,10 +524,42 @@ func uint32SliceToInt16(s []uint32) []int16 { return res } -func FromProtobufChallengedHeader(ph *g.Block_Header_ChallengedHeader) (*ChallengedHeader, error) { - // Implement the conversion from g.Block_Header_ChallengedHeader to ChallengedHeader - // This function should be defined according to your ChallengedHeader structure and conversion logic - return &ChallengedHeader{}, nil +func FromProtobufChallengedHeader(pb *g.Block_Header_ChallengedHeader) (*ChallengedHeader, error) { + if pb == nil { + return nil, fmt.Errorf("input protobuf object is nil") + } + headerSig, err := crypto.NewSignatureFromBytes(pb.HeaderSignature) + if err != nil { + return nil, err + } + genPublicKey, err := crypto.NewPublicKeyFromBytes(pb.Generator) + if err != nil { + return nil, err + } + stateHash, err := crypto.NewDigestFromBytes(pb.StateHash) + if err != nil { + return nil, err + } + return &ChallengedHeader{ + NxtConsensus: NxtConsensus{ + BaseTarget: uint64(pb.BaseTarget), + GenSignature: pb.GenerationSignature, + }, + Features: int16SliceFromUint32(pb.FeatureVotes), + Timestamp: uint64(pb.Timestamp), + GeneratorPublicKey: genPublicKey, + RewardVote: pb.RewardVote, + StateHash: stateHash, + BlockSignature: headerSig, + }, nil +} + +func int16SliceFromUint32(data []uint32) []int16 { + result := make([]int16, len(data)) + for i, v := range data { + result[i] = int16(v) + } + return result } func AppendHeaderBytesToTransactions(headerBytes, transactions []byte) ([]byte, error) { diff --git a/pkg/proto/types.go b/pkg/proto/types.go index 93758a4c7..967aebece 100644 --- a/pkg/proto/types.go +++ b/pkg/proto/types.go @@ -3204,9 +3204,9 @@ func (e *DataEntries) UnmarshalJSON(data []byte) error { entries := make([]DataEntry, len(ets)) for i, row := range ets { - et, err := GuessDataEntryType(row) - if err != nil { - return wrapError(err) + et, guessErr := GuessDataEntryType(row) + if guessErr != nil { + return wrapError(guessErr) } entries[i] = et } diff --git a/pkg/state/accounts_data_storage.go b/pkg/state/accounts_data_storage.go index 19acbf51a..b4a7c8756 100644 --- a/pkg/state/accounts_data_storage.go +++ b/pkg/state/accounts_data_storage.go @@ -335,18 +335,18 @@ func (s *accountsDataStorage) retrieveEntriesAtHeight(addr proto.Address, height pos += int(valueSize) var record dataEntryRecord - if err := record.unmarshalBinary(value); err != nil { - return nil, err + if unmrshlErr := record.unmarshalBinary(value); unmrshlErr != nil { + return nil, unmrshlErr } var entryKey accountsDataStorKey - if err := entryKey.unmarshal(key); err != nil { - return nil, err + if unmrshlErr := entryKey.unmarshal(key); unmrshlErr != nil { + return nil, unmrshlErr } - entry, err := proto.NewDataEntryFromValueBytes(record.value) - if err != nil { - return nil, err + entry, cnvrtErr := proto.NewDataEntryFromValueBytes(record.value) + if cnvrtErr != nil { + return nil, cnvrtErr } entry.SetKey(entryKey.entryKey) diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 8fc74110e..b7b884c25 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -835,9 +835,9 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { // TODO possibly run it in a goroutine? make sure goroutines run in order? if a.bUpdatesExtension != nil { if a.bUpdatesExtension.EnableBlockchainUpdatesPlugin { - err := a.updateBlockchainUpdateInfo(blockInfo, params.block) - if err != nil { - return err + updtErr := a.updateBlockchainUpdateInfo(blockInfo, params.block) + if updtErr != nil { + return updtErr } } } @@ -868,15 +868,17 @@ func (a *txAppender) updateBlockchainUpdateInfo(blockInfo *proto.BlockInfo, bloc if err != nil && !errors.Is(err, proto.ErrNotFound) { return err } - bUpdatesInfo := blockchaininfo.BUpdatesInfo{ - Height: blockInfo.Height, - VRF: blockInfo.VRF, - BlockID: blockHeader.BlockID(), - BlockHeader: blockHeader, - AllDataEntries: dataEntries, + BlockUpdatesInfo: blockchaininfo.BlockUpdatesInfo{ + Height: blockInfo.Height, + VRF: blockInfo.VRF, + BlockID: blockHeader.BlockID(), + BlockHeader: blockHeader, + }, + ContractUpdatesInfo: blockchaininfo.L2ContractDataEntries{ + AllDataEntries: dataEntries, + }, } - a.bUpdatesExtension.BUpdatesChannel <- bUpdatesInfo return nil } diff --git a/pkg/state/invoke_applier_test.go b/pkg/state/invoke_applier_test.go index 2989ff51e..eb0a769f9 100644 --- a/pkg/state/invoke_applier_test.go +++ b/pkg/state/invoke_applier_test.go @@ -35,7 +35,7 @@ type invokeApplierTestObjects struct { } func createInvokeApplierTestObjects(t *testing.T) *invokeApplierTestObjects { - state, err := newStateManager(t.TempDir(), true, DefaultTestingStateParams(), settings.MainNetSettings, false) + state, err := newStateManager(t.TempDir(), true, DefaultTestingStateParams(), settings.MainNetSettings, false, nil) assert.NoError(t, err, "newStateManager() failed") to := &invokeApplierTestObjects{state} randGenesisBlockID := genRandBlockId(t) diff --git a/pkg/state/state_test.go b/pkg/state/state_test.go index b18d2b24d..8f3b9fc6f 100644 --- a/pkg/state/state_test.go +++ b/pkg/state/state_test.go @@ -72,12 +72,14 @@ func TestHandleAmendFlag(t *testing.T) { // open with false amend again. Result amend should be true assert.NoError(t, manager.Close(), "manager.Close() failed") - manager, err = newStateManager(dataDir, false, DefaultTestingStateParams(), settings.MainNetSettings, false, nil) + manager, err = newStateManager(dataDir, false, DefaultTestingStateParams(), settings.MainNetSettings, + false, nil) assert.NoError(t, err, "newStateManager() failed") assert.True(t, manager.stor.hs.amend) // first open with true amend - newManager, err := newStateManager(t.TempDir(), true, DefaultTestingStateParams(), settings.MainNetSettings, false, nil) + newManager, err := newStateManager(t.TempDir(), true, DefaultTestingStateParams(), settings.MainNetSettings, + false, nil) assert.NoError(t, err, "newStateManager() failed") t.Cleanup(func() { assert.NoError(t, newManager.Close(), "newManager.Close() failed") From 18eab8cd045d41fbdeeff3987ab874d64d838f28 Mon Sep 17 00:00:00 2001 From: esuwu Date: Fri, 9 Aug 2024 00:28:47 -0500 Subject: [PATCH 14/50] Added paging --- cmd/blockchaininfo/nats_subscriber.go | 94 ++++++++++---- pkg/blockchaininfo/nats_publisher.go | 117 ++++++++++++++++-- pkg/blockchaininfo/proto_converters.go | 5 +- pkg/blockchaininfo/types.go | 1 + .../l2/blockchain_info/blockchain_info.pb.go | 27 ++-- .../l2/blockchain_info/blockchain_info.proto | 1 + .../blockchain_info_vtproto.pb.go | 27 ++++ 7 files changed, 224 insertions(+), 48 deletions(-) diff --git a/cmd/blockchaininfo/nats_subscriber.go b/cmd/blockchaininfo/nats_subscriber.go index b84e4e7c3..d5003fc9b 100644 --- a/cmd/blockchaininfo/nats_subscriber.go +++ b/cmd/blockchaininfo/nats_subscriber.go @@ -3,9 +3,11 @@ package main import ( "context" "encoding/json" + "fmt" "log" "os" "os/signal" + "strconv" "syscall" "github.com/nats-io/nats.go" @@ -32,6 +34,21 @@ func printContractInfo(contractInfoProto *g.L2ContractDataEntries, scheme proto. if err != nil { return err } + // temporary + + prettyJSON, err := json.MarshalIndent(contractInfo, "", " ") + if err != nil { + fmt.Println("Error converting to pretty JSON:", err) + return err + } + heightStr := strconv.Itoa(int(contractInfoProto.Height)) + // Write the pretty JSON to a file named "index.json" + err = os.WriteFile("/media/alex/My_Book/dolgavin/waves/subscriber/contract_data/"+heightStr+".json", prettyJSON, 0644) + if err != nil { + fmt.Println("Error writing to file:", err) + return err + } + contractInfoJSON, err := json.Marshal(contractInfo) if err != nil { return err @@ -52,37 +69,62 @@ func main() { } defer nc.Close() - _, err = nc.Subscribe(blockchaininfo.BlockUpdates, func(msg *nats.Msg) { - blockUpdatesInfo := new(g.BlockInfo) - unmrshlErr := blockUpdatesInfo.UnmarshalVT(msg.Data) - if unmrshlErr != nil { - log.Printf("failed to unmarshal block updates, %v", unmrshlErr) - return - } + //_, err = nc.Subscribe(blockchaininfo.BlockUpdates, func(msg *nats.Msg) { + // blockUpdatesInfo := new(g.BlockInfo) + // unmrshlErr := blockUpdatesInfo.UnmarshalVT(msg.Data) + // if unmrshlErr != nil { + // log.Printf("failed to unmarshal block updates, %v", unmrshlErr) + // return + // } + // + // err = printBlockInfo(blockUpdatesInfo) + // if err != nil { + // return + // } + // log.Printf("Received on %s:\n", msg.Subject) + //}) + //if err != nil { + // log.Printf("failed to subscribe to block updates, %v", err) + // return + //} - err = printBlockInfo(blockUpdatesInfo) - if err != nil { - return - } - log.Printf("Received on %s:\n", msg.Subject) - }) - if err != nil { - log.Printf("failed to subscribe to block updates, %v", err) - return - } + var contractMsg []byte _, err = nc.Subscribe(blockchaininfo.ContractUpdates, func(msg *nats.Msg) { - contractUpdatesInfo := new(g.L2ContractDataEntries) - unmrshlErr := contractUpdatesInfo.UnmarshalVT(msg.Data) - if unmrshlErr != nil { - log.Printf("failed to unmarshal contract updates, %v", unmrshlErr) - return + if msg.Data[0] == blockchaininfo.NO_PAGING { + contractMsg = msg.Data[1:] + contractUpdatesInfo := new(g.L2ContractDataEntries) + unmrshlErr := contractUpdatesInfo.UnmarshalVT(contractMsg) + if unmrshlErr != nil { + log.Printf("failed to unmarshal contract updates, %v", unmrshlErr) + return + } + err = printContractInfo(contractUpdatesInfo, scheme) + if err != nil { + return + } + contractMsg = nil } - log.Printf("Received on %s:\n", msg.Subject) - err = printContractInfo(contractUpdatesInfo, scheme) - if err != nil { - return + if msg.Data[0] == blockchaininfo.START_PAGING { + contractMsg = append(contractMsg, msg.Data[1:]...) } + + if msg.Data[0] == blockchaininfo.END_PAGING && contractMsg != nil { + contractMsg = append(contractMsg, msg.Data[1:]...) + contractUpdatesInfo := new(g.L2ContractDataEntries) + unmrshlErr := contractUpdatesInfo.UnmarshalVT(contractMsg) + if unmrshlErr != nil { + log.Printf("failed to unmarshal contract updates, %v", unmrshlErr) + return + } + + err = printContractInfo(contractUpdatesInfo, scheme) + if err != nil { + return + } + contractMsg = nil + } + }) if err != nil { log.Printf("failed to subscribe to contract updates, %v", err) diff --git a/pkg/blockchaininfo/nats_publisher.go b/pkg/blockchaininfo/nats_publisher.go index 43a3181ed..95baaf4b2 100644 --- a/pkg/blockchaininfo/nats_publisher.go +++ b/pkg/blockchaininfo/nats_publisher.go @@ -2,7 +2,11 @@ package blockchaininfo import ( "context" + "encoding/json" + "fmt" "log" + "os" + "strconv" "github.com/nats-io/nats-server/v2/server" "github.com/nats-io/nats.go" @@ -14,6 +18,16 @@ const PortDefault = 4222 const HostDefault = "127.0.0.1" const ConnectionsTimeoutDefault = 5 * server.AUTH_TIMEOUT +const NATS_MAX_PAYLOAD_SIZE int32 = (1024 * 1024) * 64 // 64 MB + +//const NATS_MAX_PAYLOAD_SIZE int32 = 5 + +const ( + START_PAGING = iota + END_PAGING + NO_PAGING +) + type BUpdatesExtensionState struct { currentState *BUpdatesInfo previousState *BUpdatesInfo // this information is what was just published @@ -36,6 +50,74 @@ func (bu *BUpdatesExtensionState) hasStateChanged() (bool, error) { return true, nil } +func splitIntoChunks(array []byte, maxChunkSize int) [][]byte { + if maxChunkSize <= 0 { + return nil + } + var chunkedArray [][]byte + + for i := 0; i < len(array); i += maxChunkSize { + end := i + maxChunkSize + if end > len(array) { + end = len(array) + } + chunkedArray = append(chunkedArray, array[i:end]) + } + + return chunkedArray +} + +func (bu *BUpdatesExtensionState) publishContractUpdates(contractUpdates L2ContractDataEntries, nc *nats.Conn, scheme proto.Scheme) error { + dataEntriesProtobuf, err := L2ContractDataEntriesToProto(contractUpdates).MarshalVTStrict() + if err != nil { + return err + } + fmt.Println("Size in MB") + + fmt.Println(len(dataEntriesProtobuf) / 1024) + + if len(dataEntriesProtobuf) <= int(NATS_MAX_PAYLOAD_SIZE-1) { + var msg []byte + msg = append(msg, NO_PAGING) + msg = append(msg, dataEntriesProtobuf...) + err = nc.Publish(ContractUpdates, msg) + if err != nil { + log.Printf("failed to publish message on topic %s", ContractUpdates) + return err + } + log.Printf("Published on topic: %s\n", ContractUpdates) + return nil + } + + chunkedPayload := splitIntoChunks(dataEntriesProtobuf, int(NATS_MAX_PAYLOAD_SIZE-1)) + + for i, chunk := range chunkedPayload { + var msg []byte + + if i == len(chunkedPayload)-1 { + msg = append(msg, END_PAGING) + msg = append(msg, chunk...) + err = nc.Publish(ContractUpdates, msg) + if err != nil { + log.Printf("failed to publish message on topic %s", ContractUpdates) + return err + } + log.Printf("Published on topic: %s\n", ContractUpdates) + break + } + msg = append(msg, START_PAGING) + msg = append(msg, chunk...) + err = nc.Publish(ContractUpdates, msg) + if err != nil { + log.Printf("failed to publish message on topic %s", ContractUpdates) + return err + } + log.Printf("Published on topic: %s\n", ContractUpdates) + } + + return nil +} + func (bu *BUpdatesExtensionState) publishUpdates(updates BUpdatesInfo, nc *nats.Conn, scheme proto.Scheme) error { /* first publish block related info */ blockInfo, err := BUpdatesInfoToProto(updates, scheme) @@ -46,6 +128,21 @@ func (bu *BUpdatesExtensionState) publishUpdates(updates BUpdatesInfo, nc *nats. if err != nil { return err } + // temporary + prettyJSON, err := json.MarshalIndent(updates.ContractUpdatesInfo, "", " ") + if err != nil { + fmt.Println("Error converting to pretty JSON:", err) + return err + } + heightStr := strconv.Itoa(int(updates.BlockUpdatesInfo.Height)) + // Write the pretty JSON to a file named "index.json" + err = os.WriteFile("/media/alex/My_Book/dolgavin/waves/contract_data/"+heightStr+".json", prettyJSON, 0644) + if err != nil { + fmt.Println("Error writing to file:", err) + return err + } + + // err = nc.Publish(BlockUpdates, blockInfoProtobuf) if err != nil { log.Printf("failed to publish message on topic %s", BlockUpdates) @@ -54,16 +151,13 @@ func (bu *BUpdatesExtensionState) publishUpdates(updates BUpdatesInfo, nc *nats. log.Printf("Published on topic: %s\n", BlockUpdates) /* second publish contract data entries */ - dataEntries := L2ContractDataEntriesToProto(updates.ContractUpdatesInfo.AllDataEntries) - dataEntriesProtobuf, err := dataEntries.MarshalVTStrict() - if err != nil { - return err - } - if dataEntries.DataEntries != nil { - err = nc.Publish(ContractUpdates, dataEntriesProtobuf) - if err != nil { + if updates.ContractUpdatesInfo.AllDataEntries != nil { + //fmt.Println("Size in MB") + //fmt.Println(len(dataEntriesProtobuf) / 1024) + pblshErr := bu.publishContractUpdates(updates.ContractUpdatesInfo, nc, scheme) + if pblshErr != nil { log.Printf("failed to publish message on topic %s", ContractUpdates) - return err + return pblshErr } log.Printf("Published on topic: %s\n", ContractUpdates) } @@ -114,8 +208,9 @@ func runPublisher(ctx context.Context, updatesChannel <-chan BUpdatesInfo, func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(ctx context.Context, updatesChannel <-chan BUpdatesInfo, scheme proto.Scheme) { opts := &server.Options{ - Host: HostDefault, - Port: PortDefault, + MaxPayload: NATS_MAX_PAYLOAD_SIZE, + Host: HostDefault, + Port: PortDefault, } s, err := server.NewServer(opts) if err != nil { diff --git a/pkg/blockchaininfo/proto_converters.go b/pkg/blockchaininfo/proto_converters.go index 924e11f70..fcf267a23 100644 --- a/pkg/blockchaininfo/proto_converters.go +++ b/pkg/blockchaininfo/proto_converters.go @@ -36,14 +36,15 @@ func BUpdatesInfoFromProto(blockInfoProto *g.BlockInfo) (BlockUpdatesInfo, error }, nil } -func L2ContractDataEntriesToProto(dataEntries []proto.DataEntry) *g.L2ContractDataEntries { +func L2ContractDataEntriesToProto(contractData L2ContractDataEntries) *g.L2ContractDataEntries { var protobufDataEntries []*waves.DataEntry - for _, entry := range dataEntries { + for _, entry := range contractData.AllDataEntries { entryProto := entry.ToProtobuf() protobufDataEntries = append(protobufDataEntries, entryProto) } return &g.L2ContractDataEntries{ DataEntries: protobufDataEntries, + Height: contractData.Height, } } diff --git a/pkg/blockchaininfo/types.go b/pkg/blockchaininfo/types.go index ee2932bac..9989e3125 100644 --- a/pkg/blockchaininfo/types.go +++ b/pkg/blockchaininfo/types.go @@ -17,6 +17,7 @@ type BlockUpdatesInfo struct { // L2 contract data entries. type L2ContractDataEntries struct { AllDataEntries []proto.DataEntry `json:"all_data_entries"` + Height uint64 `json:"height"` } type BUpdatesInfo struct { diff --git a/pkg/grpc/l2/blockchain_info/blockchain_info.pb.go b/pkg/grpc/l2/blockchain_info/blockchain_info.pb.go index f7a08cc5e..a01810c98 100644 --- a/pkg/grpc/l2/blockchain_info/blockchain_info.pb.go +++ b/pkg/grpc/l2/blockchain_info/blockchain_info.pb.go @@ -98,6 +98,7 @@ type L2ContractDataEntries struct { unknownFields protoimpl.UnknownFields DataEntries []*waves.DataEntry `protobuf:"bytes,5,rep,name=DataEntries,proto3" json:"DataEntries,omitempty"` + Height uint64 `protobuf:"varint,1,opt,name=Height,proto3" json:"Height,omitempty"` } func (x *L2ContractDataEntries) Reset() { @@ -139,6 +140,13 @@ func (x *L2ContractDataEntries) GetDataEntries() []*waves.DataEntry { return nil } +func (x *L2ContractDataEntries) GetHeight() uint64 { + if x != nil { + return x.Height + } + return 0 +} + var File_blockchain_info_proto protoreflect.FileDescriptor var file_blockchain_info_proto_rawDesc = []byte{ @@ -155,19 +163,20 @@ var file_blockchain_info_proto_rawDesc = []byte{ 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x12, 0x35, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x52, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, 0x4b, 0x0a, + 0x52, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, 0x63, 0x0a, 0x15, 0x4c, 0x32, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x44, - 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x42, 0x62, 0x0a, 0x1a, 0x63, 0x6f, - 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, - 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, - 0x72, 0x70, 0x63, 0x2f, 0x6c, 0x32, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0xaa, 0x02, 0x05, 0x57, 0x61, 0x76, 0x65, 0x73, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x48, 0x65, + 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x48, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x42, 0x62, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, + 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, + 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x6c, 0x32, 0x2f, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0xaa, 0x02, + 0x05, 0x57, 0x61, 0x76, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/grpc/l2/blockchain_info/blockchain_info.proto b/pkg/grpc/l2/blockchain_info/blockchain_info.proto index f168f4fb6..ce2876402 100644 --- a/pkg/grpc/l2/blockchain_info/blockchain_info.proto +++ b/pkg/grpc/l2/blockchain_info/blockchain_info.proto @@ -18,6 +18,7 @@ message BlockInfo { message L2ContractDataEntries { repeated waves.DataEntry DataEntries = 5; + uint64 Height = 1; } diff --git a/pkg/grpc/l2/blockchain_info/blockchain_info_vtproto.pb.go b/pkg/grpc/l2/blockchain_info/blockchain_info_vtproto.pb.go index 8ab85b253..544628391 100644 --- a/pkg/grpc/l2/blockchain_info/blockchain_info_vtproto.pb.go +++ b/pkg/grpc/l2/blockchain_info/blockchain_info_vtproto.pb.go @@ -148,6 +148,11 @@ func (m *L2ContractDataEntries) MarshalToSizedBufferVTStrict(dAtA []byte) (int, dAtA[i] = 0x2a } } + if m.Height != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } return len(dAtA) - i, nil } @@ -188,6 +193,9 @@ func (m *L2ContractDataEntries) SizeVT() (n int) { } var l int _ = l + if m.Height != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Height)) + } if len(m.DataEntries) > 0 { for _, e := range m.DataEntries { if size, ok := interface{}(e).(interface { @@ -415,6 +423,25 @@ func (m *L2ContractDataEntries) UnmarshalVT(dAtA []byte) error { return fmt.Errorf("proto: L2ContractDataEntries: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } case 5: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field DataEntries", wireType) From e2da71e2ba4861a02fda1162d7b7fc6db5f75a3d Mon Sep 17 00:00:00 2001 From: esuwu Date: Tue, 27 Aug 2024 23:42:22 -0500 Subject: [PATCH 15/50] Added changes detector --- cmd/blockchaininfo/nats_subscriber.go | 48 +++++------ pkg/blockchaininfo/nats_publisher.go | 70 ++++++++++------ pkg/blockchaininfo/topics.go | 2 +- pkg/blockchaininfo/types.go | 110 ++++++++++++++++++-------- pkg/proto/types.go | 12 +++ 5 files changed, 159 insertions(+), 83 deletions(-) diff --git a/cmd/blockchaininfo/nats_subscriber.go b/cmd/blockchaininfo/nats_subscriber.go index d5003fc9b..0bacf0c15 100644 --- a/cmd/blockchaininfo/nats_subscriber.go +++ b/cmd/blockchaininfo/nats_subscriber.go @@ -4,16 +4,15 @@ import ( "context" "encoding/json" "fmt" + "github.com/nats-io/nats.go" + "github.com/wavesplatform/gowaves/pkg/blockchaininfo" + g "github.com/wavesplatform/gowaves/pkg/grpc/l2/blockchain_info" + "github.com/wavesplatform/gowaves/pkg/proto" "log" "os" "os/signal" "strconv" "syscall" - - "github.com/nats-io/nats.go" - "github.com/wavesplatform/gowaves/pkg/blockchaininfo" - g "github.com/wavesplatform/gowaves/pkg/grpc/l2/blockchain_info" - "github.com/wavesplatform/gowaves/pkg/proto" ) func printBlockInfo(blockInfoProto *g.BlockInfo) error { @@ -69,27 +68,29 @@ func main() { } defer nc.Close() - //_, err = nc.Subscribe(blockchaininfo.BlockUpdates, func(msg *nats.Msg) { - // blockUpdatesInfo := new(g.BlockInfo) - // unmrshlErr := blockUpdatesInfo.UnmarshalVT(msg.Data) - // if unmrshlErr != nil { - // log.Printf("failed to unmarshal block updates, %v", unmrshlErr) - // return - // } - // - // err = printBlockInfo(blockUpdatesInfo) - // if err != nil { - // return - // } - // log.Printf("Received on %s:\n", msg.Subject) - //}) - //if err != nil { - // log.Printf("failed to subscribe to block updates, %v", err) - // return - //} + _, err = nc.Subscribe(blockchaininfo.BlockUpdates, func(msg *nats.Msg) { + blockUpdatesInfo := new(g.BlockInfo) + unmrshlErr := blockUpdatesInfo.UnmarshalVT(msg.Data) + if unmrshlErr != nil { + log.Printf("failed to unmarshal block updates, %v", unmrshlErr) + return + } + + err = printBlockInfo(blockUpdatesInfo) + if err != nil { + return + } + log.Printf("Received on %s:\n", msg.Subject) + }) + if err != nil { + log.Printf("failed to subscribe to block updates, %v", err) + return + } var contractMsg []byte + //_, err = nc.Subscribe(blockchaininfo.ContractUpdates, func(msg *nats.Msg) { _, err = nc.Subscribe(blockchaininfo.ContractUpdates, func(msg *nats.Msg) { + log.Printf("Received on %s:\n", msg.Subject) if msg.Data[0] == blockchaininfo.NO_PAGING { contractMsg = msg.Data[1:] contractUpdatesInfo := new(g.L2ContractDataEntries) @@ -124,7 +125,6 @@ func main() { } contractMsg = nil } - }) if err != nil { log.Printf("failed to subscribe to contract updates, %v", err) diff --git a/pkg/blockchaininfo/nats_publisher.go b/pkg/blockchaininfo/nats_publisher.go index 95baaf4b2..90e831895 100644 --- a/pkg/blockchaininfo/nats_publisher.go +++ b/pkg/blockchaininfo/nats_publisher.go @@ -7,6 +7,7 @@ import ( "log" "os" "strconv" + "time" "github.com/nats-io/nats-server/v2/server" "github.com/nats-io/nats.go" @@ -18,7 +19,7 @@ const PortDefault = 4222 const HostDefault = "127.0.0.1" const ConnectionsTimeoutDefault = 5 * server.AUTH_TIMEOUT -const NATS_MAX_PAYLOAD_SIZE int32 = (1024 * 1024) * 64 // 64 MB +const NATS_MAX_PAYLOAD_SIZE int32 = 1024 * 1024 // 64 MB //const NATS_MAX_PAYLOAD_SIZE int32 = 5 @@ -39,15 +40,15 @@ func NewBUpdatesExtensionState(limit uint64, scheme proto.Scheme) *BUpdatesExten return &BUpdatesExtensionState{Limit: limit, scheme: scheme} } -func (bu *BUpdatesExtensionState) hasStateChanged() (bool, error) { - statesAreEqual, err := statesEqual(*bu, bu.scheme) +func (bu *BUpdatesExtensionState) hasStateChanged() (bool, BUpdatesInfo, error) { + statesAreEqual, changes, err := statesEqual(*bu, bu.scheme) if err != nil { - return false, err + return false, BUpdatesInfo{}, err } if statesAreEqual { - return false, nil + return false, BUpdatesInfo{}, nil } - return true, nil + return true, changes, nil } func splitIntoChunks(array []byte, maxChunkSize int) [][]byte { @@ -89,7 +90,7 @@ func (bu *BUpdatesExtensionState) publishContractUpdates(contractUpdates L2Contr return nil } - chunkedPayload := splitIntoChunks(dataEntriesProtobuf, int(NATS_MAX_PAYLOAD_SIZE-1)) + chunkedPayload := splitIntoChunks(dataEntriesProtobuf, int(NATS_MAX_PAYLOAD_SIZE-1)/2) for i, chunk := range chunkedPayload { var msg []byte @@ -113,28 +114,29 @@ func (bu *BUpdatesExtensionState) publishContractUpdates(contractUpdates L2Contr return err } log.Printf("Published on topic: %s\n", ContractUpdates) + time.Sleep(time.Millisecond) } return nil } func (bu *BUpdatesExtensionState) publishUpdates(updates BUpdatesInfo, nc *nats.Conn, scheme proto.Scheme) error { - /* first publish block related info */ - blockInfo, err := BUpdatesInfoToProto(updates, scheme) - if err != nil { - return err - } - blockInfoProtobuf, err := blockInfo.MarshalVTStrict() - if err != nil { - return err - } + ///* first publish block related info */ + //blockInfo, err := BUpdatesInfoToProto(updates, scheme) + //if err != nil { + // return err + //} + //blockInfoProtobuf, err := blockInfo.MarshalVTStrict() + //if err != nil { + // return err + //} // temporary prettyJSON, err := json.MarshalIndent(updates.ContractUpdatesInfo, "", " ") if err != nil { fmt.Println("Error converting to pretty JSON:", err) return err } - heightStr := strconv.Itoa(int(updates.BlockUpdatesInfo.Height)) + heightStr := strconv.Itoa(int(*updates.BlockUpdatesInfo.Height)) // Write the pretty JSON to a file named "index.json" err = os.WriteFile("/media/alex/My_Book/dolgavin/waves/contract_data/"+heightStr+".json", prettyJSON, 0644) if err != nil { @@ -143,12 +145,12 @@ func (bu *BUpdatesExtensionState) publishUpdates(updates BUpdatesInfo, nc *nats. } // - err = nc.Publish(BlockUpdates, blockInfoProtobuf) - if err != nil { - log.Printf("failed to publish message on topic %s", BlockUpdates) - return err - } - log.Printf("Published on topic: %s\n", BlockUpdates) + //err = nc.Publish(BlockUpdates, blockInfoProtobuf) + //if err != nil { + // log.Printf("failed to publish message on topic %s", BlockUpdates) + // return err + //} + //log.Printf("Published on topic: %s\n", BlockUpdates) /* second publish contract data entries */ if updates.ContractUpdatesInfo.AllDataEntries != nil { @@ -165,6 +167,10 @@ func (bu *BUpdatesExtensionState) publishUpdates(updates BUpdatesInfo, nc *nats. return nil } +func convertChangesToBlockchainUpdates() { + +} + func handleBlockchainUpdates(updates BUpdatesInfo, ok bool, bu *BUpdatesExtensionState, scheme proto.Scheme, nc *nats.Conn) { if !ok { @@ -174,17 +180,29 @@ func handleBlockchainUpdates(updates BUpdatesInfo, ok bool, // update current state bu.currentState = &updates // compare the current state to the previous state - stateChanged, cmprErr := bu.hasStateChanged() + if bu.previousState == nil { + // publish initial updates + pblshErr := bu.publishUpdates(updates, nc, scheme) + log.Printf("published initial updates") + if pblshErr != nil { + log.Printf("failed to publish updates, %v", pblshErr) + } + bu.previousState = &updates + return + } + + stateChanged, changes, cmprErr := bu.hasStateChanged() if cmprErr != nil { log.Printf("failed to compare current and previous states, %v", cmprErr) return } // if there is any diff, send the update if stateChanged { + updates = changes pblshErr := bu.publishUpdates(updates, nc, scheme) - log.Printf("published") + log.Printf("published changes") if pblshErr != nil { - log.Printf("failed to publish updates, %v", pblshErr) + log.Printf("failed to publish changes, %v", pblshErr) } bu.previousState = &updates } diff --git a/pkg/blockchaininfo/topics.go b/pkg/blockchaininfo/topics.go index 4e269c4e1..0fdb08b32 100644 --- a/pkg/blockchaininfo/topics.go +++ b/pkg/blockchaininfo/topics.go @@ -4,7 +4,7 @@ package blockchaininfo const ( BlockUpdates = "block_topic" microblockUpdates = "microblock_topic" - ContractUpdates = "contract_topi" + ContractUpdates = "contract_topic" ) // var Topics = []string{BlockUpdates, microblockUpdates, ContractUpdates} diff --git a/pkg/blockchaininfo/types.go b/pkg/blockchaininfo/types.go index 9989e3125..a8fa0205c 100644 --- a/pkg/blockchaininfo/types.go +++ b/pkg/blockchaininfo/types.go @@ -2,22 +2,23 @@ package blockchaininfo import ( "bytes" + "sort" "github.com/wavesplatform/gowaves/pkg/proto" ) // Block updates. type BlockUpdatesInfo struct { - Height uint64 `json:"height"` - VRF proto.B58Bytes `json:"vrf"` - BlockID proto.BlockID `json:"block_id"` + Height *uint64 `json:"height"` + VRF *proto.B58Bytes `json:"vrf"` + BlockID *proto.BlockID `json:"block_id"` BlockHeader *proto.BlockHeader `json:"block_header"` } // L2 contract data entries. type L2ContractDataEntries struct { - AllDataEntries []proto.DataEntry `json:"all_data_entries"` - Height uint64 `json:"height"` + AllDataEntries *[]proto.DataEntry `json:"all_data_entries"` + Height *uint64 `json:"height"` } type BUpdatesInfo struct { @@ -27,33 +28,61 @@ type BUpdatesInfo struct { // TODO wrap errors. -func compareBUpdatesInfo(a, b BUpdatesInfo, scheme proto.Scheme) (bool, error) { - if a.BlockUpdatesInfo.Height != b.BlockUpdatesInfo.Height { - return false, nil +type infoChanges map[string]interface{} + +const ( + heightKey = "heightChange" + VRFkey = "vrfChange" + blockIDkey = "blockIDChange" + blockHeaderKey = "blockHeaderChange" + dataEntriesKey = "dataEntriesKey" +) + +func compareBUpdatesInfo(current, previous BUpdatesInfo, scheme proto.Scheme) (bool, BUpdatesInfo, error) { + changes := BUpdatesInfo{ + BlockUpdatesInfo: BlockUpdatesInfo{}, + ContractUpdatesInfo: L2ContractDataEntries{}, } - if !bytes.Equal(a.BlockUpdatesInfo.VRF, b.BlockUpdatesInfo.VRF) { - return false, nil + + equal := true + + if current.BlockUpdatesInfo.Height != previous.BlockUpdatesInfo.Height { + equal = false + //changes[heightKey] = current.BlockUpdatesInfo.Height + changes.BlockUpdatesInfo.Height = current.BlockUpdatesInfo.Height } - if !bytes.Equal(a.BlockUpdatesInfo.BlockID.Bytes(), b.BlockUpdatesInfo.BlockID.Bytes()) { - return false, nil + if !bytes.Equal(*current.BlockUpdatesInfo.VRF, *previous.BlockUpdatesInfo.VRF) { + equal = false + changes.BlockUpdatesInfo.VRF = current.BlockUpdatesInfo.VRF + //changes[VRFkey] = current.BlockUpdatesInfo.VRF } - equalHeaders, err := compareBlockHeader(a.BlockUpdatesInfo.BlockHeader, b.BlockUpdatesInfo.BlockHeader, scheme) + if !bytes.Equal(current.BlockUpdatesInfo.BlockID.Bytes(), previous.BlockUpdatesInfo.BlockID.Bytes()) { + equal = false + changes.BlockUpdatesInfo.BlockID = current.BlockUpdatesInfo.BlockID + //changes[blockIDkey] = current.BlockUpdatesInfo.BlockID + } + equalHeaders, err := compareBlockHeader(current.BlockUpdatesInfo.BlockHeader, previous.BlockUpdatesInfo.BlockHeader, scheme) if err != nil { - return false, err + return false, BUpdatesInfo{}, err } if !equalHeaders { - return false, nil + equal = false + changes.BlockUpdatesInfo.BlockHeader = current.BlockUpdatesInfo.BlockHeader + //changes[blockHeaderKey] = current.BlockUpdatesInfo.BlockHeader } - equalEntries, err := compareDataEntries(a.ContractUpdatesInfo.AllDataEntries, b.ContractUpdatesInfo.AllDataEntries) + equalEntries, dataEntryChanges, err := compareDataEntries(*current.ContractUpdatesInfo.AllDataEntries, *previous.ContractUpdatesInfo.AllDataEntries) if err != nil { - return false, err + return false, BUpdatesInfo{}, err } if !equalEntries { - return false, nil + equal = false + changes.ContractUpdatesInfo.AllDataEntries = &dataEntryChanges + changes.ContractUpdatesInfo.Height = current.BlockUpdatesInfo.Height + //changes[dataEntriesKey] = dataEntryChanges } - return true, nil + return equal, changes, nil } func compareBlockHeader(a, b *proto.BlockHeader, scheme proto.Scheme) (bool, error) { @@ -73,20 +102,40 @@ func compareBlockHeader(a, b *proto.BlockHeader, scheme proto.Scheme) (bool, err return bytes.Equal(blockAbytes, blockBbytes), nil } -func compareDataEntries(a, b []proto.DataEntry) (bool, error) { - if len(a) != len(b) { - return false, nil +func compareDataEntries(current, previous proto.DataEntries) (bool, []proto.DataEntry, error) { + sort.Sort(current) + sort.Sort(previous) + var changes []proto.DataEntry + equal := true + if len(current) != len(previous) { + equal = false } - for i := range a { - equal, err := areEntriesEqual(a[i], b[i]) + + minLength := min(len(current), len(previous)) + maxLength := max(len(current), len(previous)) + + for i := 0; i < minLength; i++ { + entryEqual, err := areEntriesEqual(current[i], previous[i]) if err != nil { - return false, err + return false, nil, err } - if !equal { - return false, nil + if !entryEqual { + equal = false + changes = append(changes, current[i]) } } - return true, nil + // iterating through the rest + restIndex := maxLength - minLength + if len(current) > len(previous) { // this means that some keys were added + for i := restIndex; i < maxLength; i++ { + changes = append(changes, current[i]) + } + } else { // this means that some keys in the current map were deleted + for i := restIndex; i < maxLength; i++ { + changes = append(changes, &proto.DeleteDataEntry{Key: previous[i].GetKey()}) + } + } + return equal, changes, nil } func areEntriesEqual(a, b proto.DataEntry) (bool, error) { @@ -105,9 +154,6 @@ func areEntriesEqual(a, b proto.DataEntry) (bool, error) { return bytes.Equal(aValueBytes, bValue), nil } -func statesEqual(state BUpdatesExtensionState, scheme proto.Scheme) (bool, error) { - if state.currentState == nil || state.previousState == nil { - return state.currentState == state.previousState, nil // both nil or one of them is nil - } +func statesEqual(state BUpdatesExtensionState, scheme proto.Scheme) (bool, BUpdatesInfo, error) { return compareBUpdatesInfo(*state.currentState, *state.previousState, scheme) } diff --git a/pkg/proto/types.go b/pkg/proto/types.go index 967aebece..3dd17435c 100644 --- a/pkg/proto/types.go +++ b/pkg/proto/types.go @@ -3164,6 +3164,18 @@ func NewDataEntryFromJSON(data []byte) (DataEntry, error) { // DataEntries the slice of various entries of DataTransaction type DataEntries []DataEntry +func (e DataEntries) Len() int { + return len(e) +} + +func (e DataEntries) Less(i int, j int) bool { + return e[i].GetKey() < e[j].GetKey() +} + +func (e DataEntries) Swap(i int, j int) { + e[i], e[j] = e[j], e[i] +} + // PayloadSize returns summary payload size of all entries. func (e DataEntries) PayloadSize() int { pl := 0 From da488290254b686a81898a234e0d135b084838fb Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 11 Sep 2024 23:58:18 -0500 Subject: [PATCH 16/50] Fixed a bug --- cmd/blockchaininfo/nats_subscriber.go | 128 +++++++++++++------------ pkg/blockchaininfo/nats_publisher.go | 92 +++++++----------- pkg/blockchaininfo/proto_converters.go | 38 ++++++-- pkg/blockchaininfo/types.go | 105 +++++++++----------- pkg/state/appender.go | 10 +- 5 files changed, 182 insertions(+), 191 deletions(-) diff --git a/cmd/blockchaininfo/nats_subscriber.go b/cmd/blockchaininfo/nats_subscriber.go index 0bacf0c15..9ff2078b7 100644 --- a/cmd/blockchaininfo/nats_subscriber.go +++ b/cmd/blockchaininfo/nats_subscriber.go @@ -3,16 +3,16 @@ package main import ( "context" "encoding/json" - "fmt" - "github.com/nats-io/nats.go" - "github.com/wavesplatform/gowaves/pkg/blockchaininfo" - g "github.com/wavesplatform/gowaves/pkg/grpc/l2/blockchain_info" - "github.com/wavesplatform/gowaves/pkg/proto" "log" "os" "os/signal" "strconv" "syscall" + + "github.com/nats-io/nats.go" + "github.com/wavesplatform/gowaves/pkg/blockchaininfo" + g "github.com/wavesplatform/gowaves/pkg/grpc/l2/blockchain_info" + "github.com/wavesplatform/gowaves/pkg/proto" ) func printBlockInfo(blockInfoProto *g.BlockInfo) error { @@ -37,23 +37,75 @@ func printContractInfo(contractInfoProto *g.L2ContractDataEntries, scheme proto. prettyJSON, err := json.MarshalIndent(contractInfo, "", " ") if err != nil { - fmt.Println("Error converting to pretty JSON:", err) + log.Println("Error converting to pretty JSON:", err) return err } heightStr := strconv.Itoa(int(contractInfoProto.Height)) - // Write the pretty JSON to a file named "index.json" - err = os.WriteFile("/media/alex/My_Book/dolgavin/waves/subscriber/contract_data/"+heightStr+".json", prettyJSON, 0644) + // Write the pretty JSON to a file + err = os.WriteFile("/media/alex/My_Book/dolgavin/waves/subscriber/contract_data/"+heightStr+".json", prettyJSON, 0600) if err != nil { - fmt.Println("Error writing to file:", err) + log.Println("Error writing to file:", err) return err } - contractInfoJSON, err := json.Marshal(contractInfo) + return nil +} + +func receiveBlockUpdates(msg *nats.Msg) { + blockUpdatesInfo := new(g.BlockInfo) + unmrshlErr := blockUpdatesInfo.UnmarshalVT(msg.Data) + if unmrshlErr != nil { + log.Printf("failed to unmarshal block updates, %v", unmrshlErr) + return + } + + err := printBlockInfo(blockUpdatesInfo) if err != nil { - return err + return } - log.Println(string(contractInfoJSON)) - return nil + log.Printf("Received on %s:\n", msg.Subject) +} + +func receiveContractUpdates(msg *nats.Msg, contractMsg []byte, scheme proto.Scheme) []byte { + log.Printf("Received on %s:\n", msg.Subject) + if msg.Data[0] == blockchaininfo.NoPaging { + contractMsg = msg.Data[1:] + contractUpdatesInfo := new(g.L2ContractDataEntries) + unmrshlErr := contractUpdatesInfo.UnmarshalVT(contractMsg) + if unmrshlErr != nil { + log.Printf("failed to unmarshal contract updates, %v", unmrshlErr) + return contractMsg + } + err := printContractInfo(contractUpdatesInfo, scheme) + if err != nil { + return contractMsg + } + contractMsg = nil + return contractMsg + } + + if msg.Data[0] == blockchaininfo.StartPaging { + contractMsg = append(contractMsg, msg.Data[1:]...) + } + + if msg.Data[0] == blockchaininfo.EndPaging && contractMsg != nil { + contractMsg = append(contractMsg, msg.Data[1:]...) + contractUpdatesInfo := new(g.L2ContractDataEntries) + unmrshlErr := contractUpdatesInfo.UnmarshalVT(contractMsg) + if unmrshlErr != nil { + log.Printf("failed to unmarshal contract updates, %v", unmrshlErr) + return contractMsg + } + + go func() { + prntErr := printContractInfo(contractUpdatesInfo, scheme) + if prntErr != nil { + log.Printf("failed to print contract info updates") + } + }() + contractMsg = nil + } + return contractMsg } func main() { @@ -69,18 +121,7 @@ func main() { defer nc.Close() _, err = nc.Subscribe(blockchaininfo.BlockUpdates, func(msg *nats.Msg) { - blockUpdatesInfo := new(g.BlockInfo) - unmrshlErr := blockUpdatesInfo.UnmarshalVT(msg.Data) - if unmrshlErr != nil { - log.Printf("failed to unmarshal block updates, %v", unmrshlErr) - return - } - - err = printBlockInfo(blockUpdatesInfo) - if err != nil { - return - } - log.Printf("Received on %s:\n", msg.Subject) + receiveBlockUpdates(msg) }) if err != nil { log.Printf("failed to subscribe to block updates, %v", err) @@ -88,43 +129,8 @@ func main() { } var contractMsg []byte - //_, err = nc.Subscribe(blockchaininfo.ContractUpdates, func(msg *nats.Msg) { _, err = nc.Subscribe(blockchaininfo.ContractUpdates, func(msg *nats.Msg) { - log.Printf("Received on %s:\n", msg.Subject) - if msg.Data[0] == blockchaininfo.NO_PAGING { - contractMsg = msg.Data[1:] - contractUpdatesInfo := new(g.L2ContractDataEntries) - unmrshlErr := contractUpdatesInfo.UnmarshalVT(contractMsg) - if unmrshlErr != nil { - log.Printf("failed to unmarshal contract updates, %v", unmrshlErr) - return - } - err = printContractInfo(contractUpdatesInfo, scheme) - if err != nil { - return - } - contractMsg = nil - } - - if msg.Data[0] == blockchaininfo.START_PAGING { - contractMsg = append(contractMsg, msg.Data[1:]...) - } - - if msg.Data[0] == blockchaininfo.END_PAGING && contractMsg != nil { - contractMsg = append(contractMsg, msg.Data[1:]...) - contractUpdatesInfo := new(g.L2ContractDataEntries) - unmrshlErr := contractUpdatesInfo.UnmarshalVT(contractMsg) - if unmrshlErr != nil { - log.Printf("failed to unmarshal contract updates, %v", unmrshlErr) - return - } - - err = printContractInfo(contractUpdatesInfo, scheme) - if err != nil { - return - } - contractMsg = nil - } + contractMsg = receiveContractUpdates(msg, contractMsg, scheme) }) if err != nil { log.Printf("failed to subscribe to contract updates, %v", err) diff --git a/pkg/blockchaininfo/nats_publisher.go b/pkg/blockchaininfo/nats_publisher.go index 90e831895..db6263928 100644 --- a/pkg/blockchaininfo/nats_publisher.go +++ b/pkg/blockchaininfo/nats_publisher.go @@ -2,11 +2,7 @@ package blockchaininfo import ( "context" - "encoding/json" - "fmt" "log" - "os" - "strconv" "time" "github.com/nats-io/nats-server/v2/server" @@ -19,14 +15,14 @@ const PortDefault = 4222 const HostDefault = "127.0.0.1" const ConnectionsTimeoutDefault = 5 * server.AUTH_TIMEOUT -const NATS_MAX_PAYLOAD_SIZE int32 = 1024 * 1024 // 64 MB +const NatsMaxPayloadSize int32 = 1024 * 1024 // 1 MB -//const NATS_MAX_PAYLOAD_SIZE int32 = 5 +const PublisherWaitingTime = 100 * time.Millisecond const ( - START_PAGING = iota - END_PAGING - NO_PAGING + StartPaging = iota + EndPaging + NoPaging ) type BUpdatesExtensionState struct { @@ -68,18 +64,15 @@ func splitIntoChunks(array []byte, maxChunkSize int) [][]byte { return chunkedArray } -func (bu *BUpdatesExtensionState) publishContractUpdates(contractUpdates L2ContractDataEntries, nc *nats.Conn, scheme proto.Scheme) error { +func (bu *BUpdatesExtensionState) publishContractUpdates(contractUpdates L2ContractDataEntries, nc *nats.Conn) error { dataEntriesProtobuf, err := L2ContractDataEntriesToProto(contractUpdates).MarshalVTStrict() if err != nil { return err } - fmt.Println("Size in MB") - fmt.Println(len(dataEntriesProtobuf) / 1024) - - if len(dataEntriesProtobuf) <= int(NATS_MAX_PAYLOAD_SIZE-1) { + if len(dataEntriesProtobuf) <= int(NatsMaxPayloadSize-1) { var msg []byte - msg = append(msg, NO_PAGING) + msg = append(msg, NoPaging) msg = append(msg, dataEntriesProtobuf...) err = nc.Publish(ContractUpdates, msg) if err != nil { @@ -90,13 +83,13 @@ func (bu *BUpdatesExtensionState) publishContractUpdates(contractUpdates L2Contr return nil } - chunkedPayload := splitIntoChunks(dataEntriesProtobuf, int(NATS_MAX_PAYLOAD_SIZE-1)/2) + chunkedPayload := splitIntoChunks(dataEntriesProtobuf, int(NatsMaxPayloadSize-1)/2) for i, chunk := range chunkedPayload { var msg []byte if i == len(chunkedPayload)-1 { - msg = append(msg, END_PAGING) + msg = append(msg, EndPaging) msg = append(msg, chunk...) err = nc.Publish(ContractUpdates, msg) if err != nil { @@ -106,7 +99,7 @@ func (bu *BUpdatesExtensionState) publishContractUpdates(contractUpdates L2Contr log.Printf("Published on topic: %s\n", ContractUpdates) break } - msg = append(msg, START_PAGING) + msg = append(msg, StartPaging) msg = append(msg, chunk...) err = nc.Publish(ContractUpdates, msg) if err != nil { @@ -114,49 +107,41 @@ func (bu *BUpdatesExtensionState) publishContractUpdates(contractUpdates L2Contr return err } log.Printf("Published on topic: %s\n", ContractUpdates) - time.Sleep(time.Millisecond) + time.Sleep(PublisherWaitingTime) } return nil } -func (bu *BUpdatesExtensionState) publishUpdates(updates BUpdatesInfo, nc *nats.Conn, scheme proto.Scheme) error { - ///* first publish block related info */ - //blockInfo, err := BUpdatesInfoToProto(updates, scheme) - //if err != nil { - // return err - //} - //blockInfoProtobuf, err := blockInfo.MarshalVTStrict() - //if err != nil { - // return err - //} - // temporary - prettyJSON, err := json.MarshalIndent(updates.ContractUpdatesInfo, "", " ") +func (bu *BUpdatesExtensionState) publishBlockUpdates(updates BUpdatesInfo, nc *nats.Conn, scheme proto.Scheme) error { + blockInfo, err := BUpdatesInfoToProto(updates, scheme) + if err != nil { + return err + } + blockInfoProtobuf, err := blockInfo.MarshalVTStrict() if err != nil { - fmt.Println("Error converting to pretty JSON:", err) return err } - heightStr := strconv.Itoa(int(*updates.BlockUpdatesInfo.Height)) - // Write the pretty JSON to a file named "index.json" - err = os.WriteFile("/media/alex/My_Book/dolgavin/waves/contract_data/"+heightStr+".json", prettyJSON, 0644) + err = nc.Publish(BlockUpdates, blockInfoProtobuf) if err != nil { - fmt.Println("Error writing to file:", err) + log.Printf("failed to publish message on topic %s", BlockUpdates) return err } + log.Printf("Published on topic: %s\n", BlockUpdates) + return nil +} - // - //err = nc.Publish(BlockUpdates, blockInfoProtobuf) - //if err != nil { - // log.Printf("failed to publish message on topic %s", BlockUpdates) - // return err - //} - //log.Printf("Published on topic: %s\n", BlockUpdates) +func (bu *BUpdatesExtensionState) publishUpdates(updates BUpdatesInfo, nc *nats.Conn, scheme proto.Scheme) error { + /* first publish block data */ + err := bu.publishBlockUpdates(updates, nc, scheme) + if err != nil { + log.Printf("failed to publish message on topic %s", BlockUpdates) + return err + } /* second publish contract data entries */ if updates.ContractUpdatesInfo.AllDataEntries != nil { - //fmt.Println("Size in MB") - //fmt.Println(len(dataEntriesProtobuf) / 1024) - pblshErr := bu.publishContractUpdates(updates.ContractUpdatesInfo, nc, scheme) + pblshErr := bu.publishContractUpdates(updates.ContractUpdatesInfo, nc) if pblshErr != nil { log.Printf("failed to publish message on topic %s", ContractUpdates) return pblshErr @@ -167,10 +152,6 @@ func (bu *BUpdatesExtensionState) publishUpdates(updates BUpdatesInfo, nc *nats. return nil } -func convertChangesToBlockchainUpdates() { - -} - func handleBlockchainUpdates(updates BUpdatesInfo, ok bool, bu *BUpdatesExtensionState, scheme proto.Scheme, nc *nats.Conn) { if !ok { @@ -179,18 +160,17 @@ func handleBlockchainUpdates(updates BUpdatesInfo, ok bool, } // update current state bu.currentState = &updates - // compare the current state to the previous state if bu.previousState == nil { // publish initial updates pblshErr := bu.publishUpdates(updates, nc, scheme) - log.Printf("published initial updates") if pblshErr != nil { log.Printf("failed to publish updates, %v", pblshErr) + return } bu.previousState = &updates return } - + // compare the current state to the previous state stateChanged, changes, cmprErr := bu.hasStateChanged() if cmprErr != nil { log.Printf("failed to compare current and previous states, %v", cmprErr) @@ -198,8 +178,7 @@ func handleBlockchainUpdates(updates BUpdatesInfo, ok bool, } // if there is any diff, send the update if stateChanged { - updates = changes - pblshErr := bu.publishUpdates(updates, nc, scheme) + pblshErr := bu.publishUpdates(changes, nc, scheme) log.Printf("published changes") if pblshErr != nil { log.Printf("failed to publish changes, %v", pblshErr) @@ -215,7 +194,6 @@ func runPublisher(ctx context.Context, updatesChannel <-chan BUpdatesInfo, select { case updates, ok := <-updatesChannel: handleBlockchainUpdates(updates, ok, bu, scheme, nc) - case <-ctx.Done(): return } @@ -226,7 +204,7 @@ func runPublisher(ctx context.Context, updatesChannel <-chan BUpdatesInfo, func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(ctx context.Context, updatesChannel <-chan BUpdatesInfo, scheme proto.Scheme) { opts := &server.Options{ - MaxPayload: NATS_MAX_PAYLOAD_SIZE, + MaxPayload: NatsMaxPayloadSize, Host: HostDefault, Port: PortDefault, } diff --git a/pkg/blockchaininfo/proto_converters.go b/pkg/blockchaininfo/proto_converters.go index fcf267a23..4b1d3bc97 100644 --- a/pkg/blockchaininfo/proto_converters.go +++ b/pkg/blockchaininfo/proto_converters.go @@ -7,14 +7,31 @@ import ( ) func BUpdatesInfoToProto(blockInfo BUpdatesInfo, scheme proto.Scheme) (*g.BlockInfo, error) { - blockHeader, err := blockInfo.BlockUpdatesInfo.BlockHeader.HeaderToProtobufHeader(scheme) + var ( + height uint64 + vrf []byte + blockID []byte + blockHeader *waves.Block_Header + err error + ) + if blockInfo.BlockUpdatesInfo.Height != nil { + height = *blockInfo.BlockUpdatesInfo.Height + } + if blockInfo.BlockUpdatesInfo.VRF != nil { + vrf = *blockInfo.BlockUpdatesInfo.VRF + } + if blockInfo.BlockUpdatesInfo.BlockID != nil { + blockID = blockInfo.BlockUpdatesInfo.BlockID.Bytes() + } + + blockHeader, err = blockInfo.BlockUpdatesInfo.BlockHeader.HeaderToProtobufHeader(scheme) if err != nil { return nil, err } return &g.BlockInfo{ - Height: blockInfo.BlockUpdatesInfo.Height, - VRF: blockInfo.BlockUpdatesInfo.VRF, - BlockID: blockInfo.BlockUpdatesInfo.BlockID.Bytes(), + Height: height, + VRF: vrf, + BlockID: blockID, BlockHeader: blockHeader, }, nil } @@ -28,23 +45,24 @@ func BUpdatesInfoFromProto(blockInfoProto *g.BlockInfo) (BlockUpdatesInfo, error if err != nil { return BlockUpdatesInfo{}, err } + vrf := proto.B58Bytes(blockInfoProto.VRF) return BlockUpdatesInfo{ - Height: blockInfoProto.Height, - VRF: blockInfoProto.VRF, - BlockID: blockID, + Height: &blockInfoProto.Height, + VRF: &vrf, + BlockID: &blockID, BlockHeader: blockHeader, }, nil } func L2ContractDataEntriesToProto(contractData L2ContractDataEntries) *g.L2ContractDataEntries { var protobufDataEntries []*waves.DataEntry - for _, entry := range contractData.AllDataEntries { + for _, entry := range *contractData.AllDataEntries { entryProto := entry.ToProtobuf() protobufDataEntries = append(protobufDataEntries, entryProto) } return &g.L2ContractDataEntries{ DataEntries: protobufDataEntries, - Height: contractData.Height, + Height: *contractData.Height, } } @@ -60,5 +78,5 @@ func L2ContractDataEntriesFromProto(protoDataEntries *g.L2ContractDataEntries, dataEntries = append(dataEntries, entry) } - return L2ContractDataEntries{AllDataEntries: dataEntries}, nil + return L2ContractDataEntries{AllDataEntries: &dataEntries, Height: &protoDataEntries.Height}, nil } diff --git a/pkg/blockchaininfo/types.go b/pkg/blockchaininfo/types.go index a8fa0205c..f6b259b76 100644 --- a/pkg/blockchaininfo/types.go +++ b/pkg/blockchaininfo/types.go @@ -2,12 +2,11 @@ package blockchaininfo import ( "bytes" - "sort" "github.com/wavesplatform/gowaves/pkg/proto" ) -// Block updates. +// BlockUpdatesInfo Block updates. type BlockUpdatesInfo struct { Height *uint64 `json:"height"` VRF *proto.B58Bytes `json:"vrf"` @@ -15,7 +14,7 @@ type BlockUpdatesInfo struct { BlockHeader *proto.BlockHeader `json:"block_header"` } -// L2 contract data entries. +// L2ContractDataEntries L2 contract data entries. type L2ContractDataEntries struct { AllDataEntries *[]proto.DataEntry `json:"all_data_entries"` Height *uint64 `json:"height"` @@ -28,16 +27,6 @@ type BUpdatesInfo struct { // TODO wrap errors. -type infoChanges map[string]interface{} - -const ( - heightKey = "heightChange" - VRFkey = "vrfChange" - blockIDkey = "blockIDChange" - blockHeaderKey = "blockHeaderChange" - dataEntriesKey = "dataEntriesKey" -) - func compareBUpdatesInfo(current, previous BUpdatesInfo, scheme proto.Scheme) (bool, BUpdatesInfo, error) { changes := BUpdatesInfo{ BlockUpdatesInfo: BlockUpdatesInfo{}, @@ -48,30 +37,28 @@ func compareBUpdatesInfo(current, previous BUpdatesInfo, scheme proto.Scheme) (b if current.BlockUpdatesInfo.Height != previous.BlockUpdatesInfo.Height { equal = false - //changes[heightKey] = current.BlockUpdatesInfo.Height changes.BlockUpdatesInfo.Height = current.BlockUpdatesInfo.Height } if !bytes.Equal(*current.BlockUpdatesInfo.VRF, *previous.BlockUpdatesInfo.VRF) { equal = false changes.BlockUpdatesInfo.VRF = current.BlockUpdatesInfo.VRF - //changes[VRFkey] = current.BlockUpdatesInfo.VRF } if !bytes.Equal(current.BlockUpdatesInfo.BlockID.Bytes(), previous.BlockUpdatesInfo.BlockID.Bytes()) { equal = false changes.BlockUpdatesInfo.BlockID = current.BlockUpdatesInfo.BlockID - //changes[blockIDkey] = current.BlockUpdatesInfo.BlockID } - equalHeaders, err := compareBlockHeader(current.BlockUpdatesInfo.BlockHeader, previous.BlockUpdatesInfo.BlockHeader, scheme) + equalHeaders, err := compareBlockHeader(current.BlockUpdatesInfo.BlockHeader, + previous.BlockUpdatesInfo.BlockHeader, scheme) if err != nil { return false, BUpdatesInfo{}, err } if !equalHeaders { equal = false changes.BlockUpdatesInfo.BlockHeader = current.BlockUpdatesInfo.BlockHeader - //changes[blockHeaderKey] = current.BlockUpdatesInfo.BlockHeader } - equalEntries, dataEntryChanges, err := compareDataEntries(*current.ContractUpdatesInfo.AllDataEntries, *previous.ContractUpdatesInfo.AllDataEntries) + equalEntries, dataEntryChanges, err := compareDataEntries(*current.ContractUpdatesInfo.AllDataEntries, + *previous.ContractUpdatesInfo.AllDataEntries) if err != nil { return false, BUpdatesInfo{}, err } @@ -79,9 +66,7 @@ func compareBUpdatesInfo(current, previous BUpdatesInfo, scheme proto.Scheme) (b equal = false changes.ContractUpdatesInfo.AllDataEntries = &dataEntryChanges changes.ContractUpdatesInfo.Height = current.BlockUpdatesInfo.Height - //changes[dataEntriesKey] = dataEntryChanges } - return equal, changes, nil } @@ -103,55 +88,57 @@ func compareBlockHeader(a, b *proto.BlockHeader, scheme proto.Scheme) (bool, err } func compareDataEntries(current, previous proto.DataEntries) (bool, []proto.DataEntry, error) { - sort.Sort(current) - sort.Sort(previous) - var changes []proto.DataEntry - equal := true - if len(current) != len(previous) { - equal = false - } - - minLength := min(len(current), len(previous)) - maxLength := max(len(current), len(previous)) + currentMap := make(map[string][]byte) // Data entries. + previousMap := make(map[string][]byte) // Data entries. - for i := 0; i < minLength; i++ { - entryEqual, err := areEntriesEqual(current[i], previous[i]) + for _, dataEntry := range current { + value, err := dataEntry.MarshalValue() if err != nil { return false, nil, err } - if !entryEqual { - equal = false - changes = append(changes, current[i]) - } + currentMap[dataEntry.GetKey()] = value } - // iterating through the rest - restIndex := maxLength - minLength - if len(current) > len(previous) { // this means that some keys were added - for i := restIndex; i < maxLength; i++ { - changes = append(changes, current[i]) - } - } else { // this means that some keys in the current map were deleted - for i := restIndex; i < maxLength; i++ { - changes = append(changes, &proto.DeleteDataEntry{Key: previous[i].GetKey()}) + + for _, dataEntry := range previous { + value, err := dataEntry.MarshalValue() + if err != nil { + return false, nil, err } + previousMap[dataEntry.GetKey()] = value } - return equal, changes, nil -} + var changes []proto.DataEntry -func areEntriesEqual(a, b proto.DataEntry) (bool, error) { - if a.GetKey() != b.GetKey() { - return false, nil - } - aValueBytes, err := a.MarshalValue() - if err != nil { - return false, err + for key, valueCur := range currentMap { + // Existing keys, not found in the previous state. This means that these keys were added. + if valuePrev, found := previousMap[key]; !found { + entryChange, err := proto.NewDataEntryFromValueBytes(valueCur) + if err != nil { + return false, nil, err + } + entryChange.SetKey(key) + changes = append(changes, entryChange) + // Existing keys, found in the previous state, different values. This means that data changed. + } else if !bytes.Equal(valuePrev, valueCur) { + entryChange, err := proto.NewDataEntryFromValueBytes(valueCur) + if err != nil { + return false, nil, err + } + entryChange.SetKey(key) + changes = append(changes, entryChange) + } } - bValue, err := b.MarshalValue() - if err != nil { - return false, err + + // Keys existing in the previous state, not found in the current state. This means that these keys were deleted. + for key := range previousMap { + if _, found := currentMap[key]; !found { + deleteEntry := &proto.DeleteDataEntry{} + deleteEntry.SetKey(key) + changes = append(changes, deleteEntry) + } } - return bytes.Equal(aValueBytes, bValue), nil + equal := changes == nil + return equal, changes, nil } func statesEqual(state BUpdatesExtensionState, scheme proto.Scheme) (bool, BUpdatesInfo, error) { diff --git a/pkg/state/appender.go b/pkg/state/appender.go index b7b884c25..7d6d258ad 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -868,15 +868,17 @@ func (a *txAppender) updateBlockchainUpdateInfo(blockInfo *proto.BlockInfo, bloc if err != nil && !errors.Is(err, proto.ErrNotFound) { return err } + blockID := blockHeader.BlockID() bUpdatesInfo := blockchaininfo.BUpdatesInfo{ BlockUpdatesInfo: blockchaininfo.BlockUpdatesInfo{ - Height: blockInfo.Height, - VRF: blockInfo.VRF, - BlockID: blockHeader.BlockID(), + Height: &blockInfo.Height, + VRF: &blockInfo.VRF, + BlockID: &blockID, BlockHeader: blockHeader, }, ContractUpdatesInfo: blockchaininfo.L2ContractDataEntries{ - AllDataEntries: dataEntries, + AllDataEntries: &dataEntries, + Height: &blockInfo.Height, }, } a.bUpdatesExtension.BUpdatesChannel <- bUpdatesInfo From b9318c244dc2028b7728c4c24c748e52d1b8076c Mon Sep 17 00:00:00 2001 From: esuwu Date: Thu, 12 Sep 2024 00:28:50 -0500 Subject: [PATCH 17/50] Renamed functions --- cmd/blockchaininfo/nats_subscriber.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cmd/blockchaininfo/nats_subscriber.go b/cmd/blockchaininfo/nats_subscriber.go index 9ff2078b7..24b3444d3 100644 --- a/cmd/blockchaininfo/nats_subscriber.go +++ b/cmd/blockchaininfo/nats_subscriber.go @@ -28,13 +28,11 @@ func printBlockInfo(blockInfoProto *g.BlockInfo) error { return nil } -func printContractInfo(contractInfoProto *g.L2ContractDataEntries, scheme proto.Scheme) error { +func printContractInfo(contractInfoProto *g.L2ContractDataEntries, scheme proto.Scheme, path string) error { contractInfo, err := blockchaininfo.L2ContractDataEntriesFromProto(contractInfoProto, scheme) if err != nil { return err } - // temporary - prettyJSON, err := json.MarshalIndent(contractInfo, "", " ") if err != nil { log.Println("Error converting to pretty JSON:", err) @@ -42,7 +40,7 @@ func printContractInfo(contractInfoProto *g.L2ContractDataEntries, scheme proto. } heightStr := strconv.Itoa(int(contractInfoProto.Height)) // Write the pretty JSON to a file - err = os.WriteFile("/media/alex/My_Book/dolgavin/waves/subscriber/contract_data/"+heightStr+".json", prettyJSON, 0600) + err = os.WriteFile(path+heightStr+".json", prettyJSON, 0600) if err != nil { log.Println("Error writing to file:", err) return err @@ -66,7 +64,7 @@ func receiveBlockUpdates(msg *nats.Msg) { log.Printf("Received on %s:\n", msg.Subject) } -func receiveContractUpdates(msg *nats.Msg, contractMsg []byte, scheme proto.Scheme) []byte { +func receiveContractUpdates(msg *nats.Msg, contractMsg []byte, scheme proto.Scheme, path string) []byte { log.Printf("Received on %s:\n", msg.Subject) if msg.Data[0] == blockchaininfo.NoPaging { contractMsg = msg.Data[1:] @@ -76,7 +74,7 @@ func receiveContractUpdates(msg *nats.Msg, contractMsg []byte, scheme proto.Sche log.Printf("failed to unmarshal contract updates, %v", unmrshlErr) return contractMsg } - err := printContractInfo(contractUpdatesInfo, scheme) + err := printContractInfo(contractUpdatesInfo, scheme, path) if err != nil { return contractMsg } @@ -98,7 +96,7 @@ func receiveContractUpdates(msg *nats.Msg, contractMsg []byte, scheme proto.Sche } go func() { - prntErr := printContractInfo(contractUpdatesInfo, scheme) + prntErr := printContractInfo(contractUpdatesInfo, scheme, path) if prntErr != nil { log.Printf("failed to print contract info updates") } @@ -108,8 +106,10 @@ func receiveContractUpdates(msg *nats.Msg, contractMsg []byte, scheme proto.Sche return contractMsg } +const scheme = proto.TestNetScheme +const path = "/media/alex/My_Book/dolgavin/waves/subscriber/contract_data/" + func main() { - scheme := proto.TestNetScheme ctx, done := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer done() // Connect to a NATS server @@ -130,7 +130,7 @@ func main() { var contractMsg []byte _, err = nc.Subscribe(blockchaininfo.ContractUpdates, func(msg *nats.Msg) { - contractMsg = receiveContractUpdates(msg, contractMsg, scheme) + contractMsg = receiveContractUpdates(msg, contractMsg, scheme, path) }) if err != nil { log.Printf("failed to subscribe to contract updates, %v", err) From 4dd8e5a9a1954c5e6305a76c3a3f661cc2c460be Mon Sep 17 00:00:00 2001 From: esuwu Date: Thu, 12 Sep 2024 01:00:13 -0500 Subject: [PATCH 18/50] Merged from master --- go.mod | 16 ++++++---------- go.sum | 18 ++++-------------- pkg/state/state_test.go | 1 + 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index cbebc6979..cc0e5f423 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/wavesplatform/gowaves -go 1.22 +go 1.22.0 require ( filippo.io/edwards25519 v1.1.0 @@ -24,10 +24,10 @@ require ( github.com/mr-tron/base58 v1.2.0 github.com/nats-io/nats-server/v2 v2.10.17 github.com/nats-io/nats.go v1.36.0 - github.com/planetscale/vtprotobuf v0.6.0 github.com/ory/dockertest/v3 v3.11.0 github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/pkg/errors v0.9.1 + github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 github.com/prometheus/client_golang v1.20.3 github.com/qmuntal/stateless v1.7.1 github.com/semrush/zenrpc/v2 v2.1.1 @@ -87,16 +87,13 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/minio/highwayhash v1.0.2 // indirect - github.com/mitchellh/mapstructure v1.4.1 // indirect - github.com/mmcloughlin/addchain v0.4.0 // indirect - github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect - github.com/nats-io/jwt/v2 v2.5.7 // indirect - github.com/nats-io/nkeys v0.4.7 // indirect - github.com/nats-io/nuid v1.0.1 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/term v0.5.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/nats-io/jwt/v2 v2.5.7 // indirect + github.com/nats-io/nkeys v0.4.7 // indirect + github.com/nats-io/nuid v1.0.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opencontainers/runc v1.1.14 // indirect @@ -115,11 +112,10 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.org/x/net v0.29.0 // indirect golang.org/x/term v0.24.0 // indirect golang.org/x/text v0.18.0 // indirect + golang.org/x/time v0.5.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 354f6d922..8e56a5ce5 100644 --- a/go.sum +++ b/go.sum @@ -176,13 +176,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -<<<<<<< HEAD github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -======= ->>>>>>> master github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= @@ -235,8 +230,8 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/planetscale/vtprotobuf v0.6.0 h1:nBeETjudeJ5ZgBHUz1fVHvbqUKnYOXNhsIEabROxmNA= -github.com/planetscale/vtprotobuf v0.6.0/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= +github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -435,15 +430,10 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -<<<<<<< HEAD -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -======= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= ->>>>>>> master +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= diff --git a/pkg/state/state_test.go b/pkg/state/state_test.go index 2e48a18eb..33c14ead9 100644 --- a/pkg/state/state_test.go +++ b/pkg/state/state_test.go @@ -513,6 +513,7 @@ func TestGeneratingBalanceValuesForNewestFunctions(t *testing.T) { state.stateDB, state.atx, &snapshotApplier, + nil, ) require.NoError(t, err, "newTxAppender() failed") state.appender = appender From 59f75f39b93f4b775423df0093917923adbb0774 Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 16 Sep 2024 19:48:10 -0500 Subject: [PATCH 19/50] Started writing the filter --- pkg/blockchaininfo/types.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/blockchaininfo/types.go b/pkg/blockchaininfo/types.go index f6b259b76..f6572c329 100644 --- a/pkg/blockchaininfo/types.go +++ b/pkg/blockchaininfo/types.go @@ -87,6 +87,12 @@ func compareBlockHeader(a, b *proto.BlockHeader, scheme proto.Scheme) (bool, err return bytes.Equal(blockAbytes, blockBbytes), nil } +func filterDataEntries(height uint64) { + // epoch_number, i.e. epoch_03198129 + + // block_0xhash, i.e. block_0xee7e9ae625c8be417f239337d82ed5e577458dec8d305a35746777fd17297a03 +} + func compareDataEntries(current, previous proto.DataEntries) (bool, []proto.DataEntry, error) { currentMap := make(map[string][]byte) // Data entries. previousMap := make(map[string][]byte) // Data entries. From 7b77774639e6585708ce5e558c1628711cb5a2cf Mon Sep 17 00:00:00 2001 From: esuwu Date: Mon, 16 Sep 2024 19:53:02 -0500 Subject: [PATCH 20/50] Commented an unused function --- pkg/blockchaininfo/types.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/blockchaininfo/types.go b/pkg/blockchaininfo/types.go index f6572c329..6137ddc85 100644 --- a/pkg/blockchaininfo/types.go +++ b/pkg/blockchaininfo/types.go @@ -87,11 +87,11 @@ func compareBlockHeader(a, b *proto.BlockHeader, scheme proto.Scheme) (bool, err return bytes.Equal(blockAbytes, blockBbytes), nil } -func filterDataEntries(height uint64) { - // epoch_number, i.e. epoch_03198129 - - // block_0xhash, i.e. block_0xee7e9ae625c8be417f239337d82ed5e577458dec8d305a35746777fd17297a03 -} +//func filterDataEntries(height uint64) { +// // epoch_number, i.e. epoch_03198129 +// +// // block_0xhash, i.e. block_0xee7e9ae625c8be417f239337d82ed5e577458dec8d305a35746777fd17297a03 +//} func compareDataEntries(current, previous proto.DataEntries) (bool, []proto.DataEntry, error) { currentMap := make(map[string][]byte) // Data entries. From 4d9419f3a4e524e8ee076cfd437d227f2a8de9cc Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 2 Oct 2024 19:30:50 -0500 Subject: [PATCH 21/50] Added a basic filter --- pkg/blockchaininfo/filter.go | 121 +++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 pkg/blockchaininfo/filter.go diff --git a/pkg/blockchaininfo/filter.go b/pkg/blockchaininfo/filter.go new file mode 100644 index 000000000..225a2d5da --- /dev/null +++ b/pkg/blockchaininfo/filter.go @@ -0,0 +1,121 @@ +package blockchaininfo + +import ( + "bytes" + "encoding/base64" + "encoding/binary" + "errors" + "fmt" + "github.com/wavesplatform/gowaves/pkg/proto" + "strconv" + "strings" +) + +var EpochKeyPrefix = "epoch_" +var blockMetaKeyPrefix = "block_0x" + +func removeOldEpochs(height uint64) { + +} + +// Helper function to read uint64 from bytes +func readInt64(data *bytes.Reader) int64 { + var num int64 + err := binary.Read(data, binary.BigEndian, &num) + if err != nil { + panic(fmt.Sprintf("Failed to read uint64: %v", err)) + } + return num +} + +// Decode base64 and extract blockHeight and height +func extractHeightFromBase64(metaBlockValueBytes []byte) (int64, int64, error) { + const base64Prefix = "base64:" + + metaBlockValue := string(metaBlockValueBytes) + // Strip the "base64:" prefix + if !strings.HasPrefix(metaBlockValue, base64Prefix) { + return 0, 0, fmt.Errorf("invalid base64 string") + } + + // Decode Base64 string + data, err := base64.StdEncoding.DecodeString(metaBlockValue[len(base64Prefix):]) + if err != nil { + return 0, 0, fmt.Errorf("failed to decode base64 string: %w", err) + } + + // Create a bytes reader for easier parsing + reader := bytes.NewReader(data) + + // Extract blockHeight and height + blockHeight := readInt64(reader) + height := readInt64(reader) + + return blockHeight, height, nil +} + +func filterDataEntries(beforeHeight uint64, dataEntries []proto.DataEntry) ([]proto.DataEntry, error) { + var filteredDataEntries []proto.DataEntry + + for _, entry := range dataEntries { + key := entry.GetKey() + + switch { + // Filter "epoch_" prefixed keys + case strings.HasPrefix(key, EpochKeyPrefix): + // Extract the numeric part after "epoch_" + epochStr := key[len(EpochKeyPrefix):] + + // Convert the epoch number to uint64 + epochNumber, err := strconv.ParseUint(epochStr, 10, 64) + if err != nil { + return nil, err + } + + // Compare epoch number with beforeHeight + if epochNumber > beforeHeight { + // Add to filtered list if epochNumber is greater + filteredDataEntries = append(filteredDataEntries, entry) + } + + // Filter block_0x binary entries + case strings.HasPrefix(key, blockMetaKeyPrefix): + // Extract blockHeight and height from base64 + binaryEntry, ok := entry.(*proto.BinaryDataEntry) + if !ok { + return nil, errors.New("failed to convert block meta key to binary data entry") + } + _, epoch, err := extractHeightFromBase64(binaryEntry.Value) + if err != nil { + return nil, err + } + + // Compare height with beforeHeight + if epoch > int64(beforeHeight) { + // Add to filtered list if height is less than beforeHeight + filteredDataEntries = append(filteredDataEntries, entry) + } + + // Default case to handle non-epoch and non-base64 entries + default: + filteredDataEntries = append(filteredDataEntries, entry) + } + } + + //epoch_number, i.e. epoch_03198129 + // + + return filteredDataEntries, nil +} + +//block_0xhash, i.e. block_0xee7e9ae625c8be417f239337d82ed5e577458dec8d305a35746777fd17297a03 + +//func mkBlockMetaEntry( +// blockHashHex: String, blockHeight: Int, blockParentHex: String, blockGenerator: Address, chainId: Int, +// elToClTransfersRootHashHex: String, lastClToElTransferIndex: Int +//) = { +//let blockMetaBytes = blockHeight.toBytes() + height.toBytes() + blockParentHex.fromBase16String() + blockGenerator.bytes + +//chainId.toBytes() + elToClTransfersRootHashHex.fromBase16String() + lastClToElTransferIndex.toBytes() +// +//BinaryEntry(blockMetaK + blockHashHex, blockMetaBytes) +//} From 6338578ecd1103f3fe7ab7ed50c6e59bf6d1ffb5 Mon Sep 17 00:00:00 2001 From: esuwu Date: Thu, 3 Oct 2024 02:16:26 -0500 Subject: [PATCH 22/50] Fixed filtering --- pkg/blockchaininfo/filter.go | 49 ++++++++++++++++++---------- pkg/blockchaininfo/nats_publisher.go | 8 ++++- pkg/blockchaininfo/types.go | 23 +++++++------ 3 files changed, 52 insertions(+), 28 deletions(-) diff --git a/pkg/blockchaininfo/filter.go b/pkg/blockchaininfo/filter.go index 225a2d5da..27be100be 100644 --- a/pkg/blockchaininfo/filter.go +++ b/pkg/blockchaininfo/filter.go @@ -2,7 +2,6 @@ package blockchaininfo import ( "bytes" - "encoding/base64" "encoding/binary" "errors" "fmt" @@ -12,7 +11,8 @@ import ( ) var EpochKeyPrefix = "epoch_" -var blockMetaKeyPrefix = "block_0x" +var blockMeta0xKeyPrefix = "block_0x" +var blockMetaKeyPrefix = "blockMeta" func removeOldEpochs(height uint64) { @@ -29,23 +29,23 @@ func readInt64(data *bytes.Reader) int64 { } // Decode base64 and extract blockHeight and height -func extractHeightFromBase64(metaBlockValueBytes []byte) (int64, int64, error) { - const base64Prefix = "base64:" +func extractEpochFromBlockMeta(metaBlockValueBytes []byte) (int64, int64, error) { + //const base64Prefix = "base64:" - metaBlockValue := string(metaBlockValueBytes) + //metaBlockValue := string(metaBlockValueBytes) // Strip the "base64:" prefix - if !strings.HasPrefix(metaBlockValue, base64Prefix) { - return 0, 0, fmt.Errorf("invalid base64 string") - } + //if !strings.HasPrefix(metaBlockValue, base64Prefix) { + // return 0, 0, fmt.Errorf("invalid base64 string") + //} // Decode Base64 string - data, err := base64.StdEncoding.DecodeString(metaBlockValue[len(base64Prefix):]) - if err != nil { - return 0, 0, fmt.Errorf("failed to decode base64 string: %w", err) - } + //data, err := base64.StdEncoding.DecodeString(metaBlockValue[len(base64Prefix):]) + //if err != nil { + // return 0, 0, fmt.Errorf("failed to decode base64 string: %w", err) + //} // Create a bytes reader for easier parsing - reader := bytes.NewReader(data) + reader := bytes.NewReader(metaBlockValueBytes) // Extract blockHeight and height blockHeight := readInt64(reader) @@ -79,13 +79,31 @@ func filterDataEntries(beforeHeight uint64, dataEntries []proto.DataEntry) ([]pr } // Filter block_0x binary entries + case strings.HasPrefix(key, blockMeta0xKeyPrefix): + // Extract blockHeight and height from base64 + binaryEntry, ok := entry.(*proto.BinaryDataEntry) + if !ok { + return nil, errors.New("failed to convert block meta key to binary data entry") + } + _, epoch, err := extractEpochFromBlockMeta(binaryEntry.Value) + if err != nil { + return nil, err + } + + // Compare height with beforeHeight + if epoch > int64(beforeHeight) { + // Add to filtered list if height is less than beforeHeight + filteredDataEntries = append(filteredDataEntries, entry) + } + + // Filter blockMeta binary entries case strings.HasPrefix(key, blockMetaKeyPrefix): // Extract blockHeight and height from base64 binaryEntry, ok := entry.(*proto.BinaryDataEntry) if !ok { return nil, errors.New("failed to convert block meta key to binary data entry") } - _, epoch, err := extractHeightFromBase64(binaryEntry.Value) + _, epoch, err := extractEpochFromBlockMeta(binaryEntry.Value) if err != nil { return nil, err } @@ -102,9 +120,6 @@ func filterDataEntries(beforeHeight uint64, dataEntries []proto.DataEntry) ([]pr } } - //epoch_number, i.e. epoch_03198129 - // - return filteredDataEntries, nil } diff --git a/pkg/blockchaininfo/nats_publisher.go b/pkg/blockchaininfo/nats_publisher.go index db6263928..f2833a634 100644 --- a/pkg/blockchaininfo/nats_publisher.go +++ b/pkg/blockchaininfo/nats_publisher.go @@ -10,7 +10,7 @@ import ( "github.com/wavesplatform/gowaves/pkg/proto" ) -const StoreBlocksLimit = 2000 +const StoreBlocksLimit = 200 const PortDefault = 4222 const HostDefault = "127.0.0.1" const ConnectionsTimeoutDefault = 5 * server.AUTH_TIMEOUT @@ -162,6 +162,12 @@ func handleBlockchainUpdates(updates BUpdatesInfo, ok bool, bu.currentState = &updates if bu.previousState == nil { // publish initial updates + + filteredDataEntries, err := filterDataEntries(*updates.BlockUpdatesInfo.Height-bu.Limit, *updates.ContractUpdatesInfo.AllDataEntries) + if err != nil { + return + } + updates.ContractUpdatesInfo.AllDataEntries = &filteredDataEntries pblshErr := bu.publishUpdates(updates, nc, scheme) if pblshErr != nil { log.Printf("failed to publish updates, %v", pblshErr) diff --git a/pkg/blockchaininfo/types.go b/pkg/blockchaininfo/types.go index 6137ddc85..d4fbe035e 100644 --- a/pkg/blockchaininfo/types.go +++ b/pkg/blockchaininfo/types.go @@ -27,7 +27,7 @@ type BUpdatesInfo struct { // TODO wrap errors. -func compareBUpdatesInfo(current, previous BUpdatesInfo, scheme proto.Scheme) (bool, BUpdatesInfo, error) { +func compareBUpdatesInfo(current, previous BUpdatesInfo, scheme proto.Scheme, heightLimit uint64) (bool, BUpdatesInfo, error) { changes := BUpdatesInfo{ BlockUpdatesInfo: BlockUpdatesInfo{}, ContractUpdatesInfo: L2ContractDataEntries{}, @@ -57,8 +57,17 @@ func compareBUpdatesInfo(current, previous BUpdatesInfo, scheme proto.Scheme) (b changes.BlockUpdatesInfo.BlockHeader = current.BlockUpdatesInfo.BlockHeader } - equalEntries, dataEntryChanges, err := compareDataEntries(*current.ContractUpdatesInfo.AllDataEntries, - *previous.ContractUpdatesInfo.AllDataEntries) + previousFilteredDataEntries, err := filterDataEntries(*previous.BlockUpdatesInfo.Height-heightLimit, *previous.ContractUpdatesInfo.AllDataEntries) + if err != nil { + return false, BUpdatesInfo{}, err + } + currentFilteredDataEntries, err := filterDataEntries(*current.BlockUpdatesInfo.Height-heightLimit, *current.ContractUpdatesInfo.AllDataEntries) + if err != nil { + return false, BUpdatesInfo{}, err + } + + equalEntries, dataEntryChanges, err := compareDataEntries(currentFilteredDataEntries, + previousFilteredDataEntries) if err != nil { return false, BUpdatesInfo{}, err } @@ -87,12 +96,6 @@ func compareBlockHeader(a, b *proto.BlockHeader, scheme proto.Scheme) (bool, err return bytes.Equal(blockAbytes, blockBbytes), nil } -//func filterDataEntries(height uint64) { -// // epoch_number, i.e. epoch_03198129 -// -// // block_0xhash, i.e. block_0xee7e9ae625c8be417f239337d82ed5e577458dec8d305a35746777fd17297a03 -//} - func compareDataEntries(current, previous proto.DataEntries) (bool, []proto.DataEntry, error) { currentMap := make(map[string][]byte) // Data entries. previousMap := make(map[string][]byte) // Data entries. @@ -148,5 +151,5 @@ func compareDataEntries(current, previous proto.DataEntries) (bool, []proto.Data } func statesEqual(state BUpdatesExtensionState, scheme proto.Scheme) (bool, BUpdatesInfo, error) { - return compareBUpdatesInfo(*state.currentState, *state.previousState, scheme) + return compareBUpdatesInfo(*state.currentState, *state.previousState, scheme, state.Limit) } From 3d2bf749bef48fcbe4828e6c0aa7793ca972e744 Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 16 Oct 2024 03:56:00 -0500 Subject: [PATCH 23/50] Added tests --- cmd/blockchaininfo/nats_subscriber.go | 104 ++++++++----- .../{filter.go => blockchaininfo.go} | 12 -- pkg/blockchaininfo/blockchaininfo_test.go | 140 ++++++++++++++++++ pkg/blockchaininfo/types.go | 2 +- 4 files changed, 211 insertions(+), 47 deletions(-) rename pkg/blockchaininfo/{filter.go => blockchaininfo.go} (85%) create mode 100644 pkg/blockchaininfo/blockchaininfo_test.go diff --git a/cmd/blockchaininfo/nats_subscriber.go b/cmd/blockchaininfo/nats_subscriber.go index 24b3444d3..c393bf685 100644 --- a/cmd/blockchaininfo/nats_subscriber.go +++ b/cmd/blockchaininfo/nats_subscriber.go @@ -3,10 +3,14 @@ package main import ( "context" "encoding/json" + "flag" + "github.com/pkg/errors" + "go.uber.org/zap" "log" "os" "os/signal" "strconv" + "strings" "syscall" "github.com/nats-io/nats.go" @@ -65,57 +69,76 @@ func receiveBlockUpdates(msg *nats.Msg) { } func receiveContractUpdates(msg *nats.Msg, contractMsg []byte, scheme proto.Scheme, path string) []byte { - log.Printf("Received on %s:\n", msg.Subject) - if msg.Data[0] == blockchaininfo.NoPaging { + zap.S().Infof("Received on %s:\n", msg.Subject) + + switch msg.Data[0] { + case blockchaininfo.NoPaging: contractMsg = msg.Data[1:] contractUpdatesInfo := new(g.L2ContractDataEntries) - unmrshlErr := contractUpdatesInfo.UnmarshalVT(contractMsg) - if unmrshlErr != nil { - log.Printf("failed to unmarshal contract updates, %v", unmrshlErr) + if err := contractUpdatesInfo.UnmarshalVT(contractMsg); err != nil { + log.Printf("Failed to unmarshal contract updates: %v", err) return contractMsg } - err := printContractInfo(contractUpdatesInfo, scheme, path) - if err != nil { + if err := printContractInfo(contractUpdatesInfo, scheme, path); err != nil { + log.Printf("Failed to print contract info: %v", err) return contractMsg } contractMsg = nil - return contractMsg - } - if msg.Data[0] == blockchaininfo.StartPaging { + case blockchaininfo.StartPaging: contractMsg = append(contractMsg, msg.Data[1:]...) - } - if msg.Data[0] == blockchaininfo.EndPaging && contractMsg != nil { - contractMsg = append(contractMsg, msg.Data[1:]...) - contractUpdatesInfo := new(g.L2ContractDataEntries) - unmrshlErr := contractUpdatesInfo.UnmarshalVT(contractMsg) - if unmrshlErr != nil { - log.Printf("failed to unmarshal contract updates, %v", unmrshlErr) - return contractMsg - } - - go func() { - prntErr := printContractInfo(contractUpdatesInfo, scheme, path) - if prntErr != nil { - log.Printf("failed to print contract info updates") + case blockchaininfo.EndPaging: + if contractMsg != nil { + contractMsg = append(contractMsg, msg.Data[1:]...) + contractUpdatesInfo := new(g.L2ContractDataEntries) + if err := contractUpdatesInfo.UnmarshalVT(contractMsg); err != nil { + log.Printf("Failed to unmarshal contract updates: %v", err) + return contractMsg } - }() - contractMsg = nil + + go func() { + if err := printContractInfo(contractUpdatesInfo, scheme, path); err != nil { + log.Printf("Failed to print contract info updates: %v", err) + } + }() + contractMsg = nil + } } + return contractMsg } -const scheme = proto.TestNetScheme -const path = "/media/alex/My_Book/dolgavin/waves/subscriber/contract_data/" +//const scheme = proto.TestNetScheme +//const path = "/media/alex/ExtremePro/waves/subscription/" func main() { + var ( + blockchainType string + updatesPath string + natsURL string + ) + // Initialize the zap logger + l, err := zap.NewProduction() + if err != nil { + log.Fatalf("failed to initialize zap logger: %v", err) + } + defer l.Sync() + + flag.StringVar(&blockchainType, "blockchain-type", "testnet", "Blockchain scheme (e.g., stagenet, testnet, mainnet)") + flag.StringVar(&updatesPath, "updates-path", "", "File path to store contract updates") + flag.StringVar(&natsURL, "nats-url", nats.DefaultURL, "URL for the NATS server") + + scheme, err := schemeFromString(blockchainType) + if err != nil { + zap.S().Fatalf("Failed to parse the blockchain type: %v", err) + } ctx, done := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer done() // Connect to a NATS server - nc, err := nats.Connect(nats.DefaultURL) + nc, err := nats.Connect(natsURL) if err != nil { - log.Print(err) + zap.S().Fatalf("Failed to connect to nats server: %v", err) return } defer nc.Close() @@ -124,18 +147,31 @@ func main() { receiveBlockUpdates(msg) }) if err != nil { - log.Printf("failed to subscribe to block updates, %v", err) + zap.S().Fatalf("Failed to subscribe to block updates: %v", err) return } var contractMsg []byte _, err = nc.Subscribe(blockchaininfo.ContractUpdates, func(msg *nats.Msg) { - contractMsg = receiveContractUpdates(msg, contractMsg, scheme, path) + contractMsg = receiveContractUpdates(msg, contractMsg, scheme, updatesPath) }) if err != nil { - log.Printf("failed to subscribe to contract updates, %v", err) + zap.S().Fatalf("Failed to subscribe to contract updates: %v", err) return } <-ctx.Done() - log.Println("Terminations of nats subscriber") + zap.S().Info("NATS subscriber finished...") +} + +func schemeFromString(networkType string) (proto.Scheme, error) { + switch strings.ToLower(networkType) { + case "mainnet": + return proto.MainNetScheme, nil + case "testnet": + return proto.TestNetScheme, nil + case "stagenet": + return proto.StageNetScheme, nil + default: + return 0, errors.New("invalid blockchain type string") + } } diff --git a/pkg/blockchaininfo/filter.go b/pkg/blockchaininfo/blockchaininfo.go similarity index 85% rename from pkg/blockchaininfo/filter.go rename to pkg/blockchaininfo/blockchaininfo.go index 27be100be..888843082 100644 --- a/pkg/blockchaininfo/filter.go +++ b/pkg/blockchaininfo/blockchaininfo.go @@ -122,15 +122,3 @@ func filterDataEntries(beforeHeight uint64, dataEntries []proto.DataEntry) ([]pr return filteredDataEntries, nil } - -//block_0xhash, i.e. block_0xee7e9ae625c8be417f239337d82ed5e577458dec8d305a35746777fd17297a03 - -//func mkBlockMetaEntry( -// blockHashHex: String, blockHeight: Int, blockParentHex: String, blockGenerator: Address, chainId: Int, -// elToClTransfersRootHashHex: String, lastClToElTransferIndex: Int -//) = { -//let blockMetaBytes = blockHeight.toBytes() + height.toBytes() + blockParentHex.fromBase16String() + blockGenerator.bytes + -//chainId.toBytes() + elToClTransfersRootHashHex.fromBase16String() + lastClToElTransferIndex.toBytes() -// -//BinaryEntry(blockMetaK + blockHashHex, blockMetaBytes) -//} diff --git a/pkg/blockchaininfo/blockchaininfo_test.go b/pkg/blockchaininfo/blockchaininfo_test.go new file mode 100644 index 000000000..8c078693c --- /dev/null +++ b/pkg/blockchaininfo/blockchaininfo_test.go @@ -0,0 +1,140 @@ +package blockchaininfo + +import ( + "fmt" + "github.com/stretchr/testify/require" + "github.com/wavesplatform/gowaves/pkg/proto" + "testing" +) + +//func TestAddressFromPublicKey(t *testing.T) { +// tests := []struct { +// publicKey string +// scheme byte +// address string +// }{ +// {"5CnGfSjguYfzWzaRmbxzCbF5qRNGTXEvayytSANkqQ6A", MainNetScheme, "3PQ8bp1aoqHQo3icNqFv6VM36V1jzPeaG1v"}, +// {"BstqhtQjQN9X78i6mEpaNnf6cMsZZRDVHNv3CqguXbxq", MainNetScheme, "3PQvBCHPnxXprTNq1rwdcDuxt6VGKRTM9wT"}, +// {"FckK43s6tQ9BBW77hSKuyRnfnrKuf6B7sEuJzcgkSDVf", MainNetScheme, "3PETfqHg9HyL92nfiujN5fBW6Ac1TYiVAAc"}, +// {"5CnGfSjguYfzWzaRmbxzCbF5qRNGTXEvayytSANkqQ6A", TestNetScheme, "3NC7nrggwhk2AbRC7kzv92yDjbVyALeGzE5"}, +// {"BstqhtQjQN9X78i6mEpaNnf6cMsZZRDVHNv3CqguXbxq", TestNetScheme, "3NCuNExVvpzSE15QkngdemY9XCyVVGhHA9h"}, +// {"5CnGfSjguYfzWzaRmbxzCbF5qRNGTXEvayytSANkqQ6A", 'x', "3cgHWJbRKGEhi32DEe6ucVV24FfF7u2mxit"}, +// {"BstqhtQjQN9X78i6mEpaNnf6cMsZZRDVHNv3CqguXbxq", 'x', "3ch55gsEJPV7mSgRsfnd8E3wqs8mSqyTNCj"}, +// } +// +// +// +// for _, tc := range tests { +// if b, err := base58.Decode(tc.publicKey); assert.NoError(t, err) { +// var pk crypto.PublicKey +// copy(pk[:], b) +// if address, err := NewAddressFromPublicKey(tc.scheme, pk); assert.NoError(t, err) { +// assert.Equal(t, tc.address, address.String()) +// } +// } +// } +//} + +func testBlockUpdates() BlockUpdatesInfo { + var b BlockUpdatesInfo + + var ( + height uint64 = 100 + VRF = proto.B58Bytes{} + BlockID = proto.BlockID{} + BlockHeader = proto.BlockHeader{} + ) + + b.Height = &height + b.VRF = &VRF + b.BlockID = &BlockID + b.BlockHeader = &BlockHeader + + return b +} + +func TestChangesGeneration(t *testing.T) { + previousDataEntries := []proto.DataEntry{ + &proto.BinaryDataEntry{Key: "block_0x3a85dedc42db076c91cf61d72fa17c80777aeed70ba68dbc14d6829dd6e88614", Value: []byte("base64:AAAAAAAQYVwAAAAAADDSCpJJsd11jrOMW7AS/AHIMIDQXjqmFyhDuGt2RPNvmcCXAVTy/URmfMOj7GNweXnZpzidmxHfPBfcP5A=")}, // height 3199498 + &proto.BinaryDataEntry{Key: "block_0x3a9209ce524553a75fd0e9bde5c99ff254b1fb231916fc89755be957e51e5516", Value: []byte("base64:AAAAAAAQYywAAAAAADDSQBBubtiRmKwtaNFF1TrBhsfBu61fj3qiSrtyu1/kLLAlAVQp5GtuF7Hxji8CQ9SFOEZLLUv88nvIgg8=")}, // height 3199552 + &proto.BinaryDataEntry{Key: "block_0x3b0181d3f66d9f0ddd8e1e8567b836a01f652b4cb873aa7b7c46fc8bd1e4eeee", Value: []byte("base64:AAAAAAAQZEUAAAAAADDSZeUUyashoWjUKurzA/wVU5prm68CambvjIo1ESLoLuAaAVRaS4vOsPl9cxvg7aeRj7RFZQzdpmvV/+A=")}, // height 3199589 + } + var previousHeight uint64 = 3199552 + + currentDataEntries := []proto.DataEntry{ + &proto.BinaryDataEntry{Key: "block_0x3b5ad5c176473be02cc3d19207204af87af03f6fd75c76916765745658f7e842", Value: []byte("base64:AAAAAAAQZKkAAAAAADDSb6xEaq4RsFQruGNeGdooPmtLBnlERR15qzc/mcKcQ461AVQp5GtuF7Hxji8CQ9SFOEZLLUv88nvIgg8=")}, // height 3199599 + &proto.BinaryDataEntry{Key: "block_0x3b72ee917fea7057fb88a357f619c22f6f8ddae03b701fab7c284953ecebbc8c", Value: []byte("base64:AAAAAAAQZQkAAAAAADDSe+2CGv9zgiR7s65XEBkYzIbv6jbxcR7Zi3ByUqsX0bkwAVTEkyC5glOJH8Upe49iT3+BUV5zRaDT2dM=")}, // height 3199611 + &proto.BinaryDataEntry{Key: "block_0x3b973acae11f248a524b463db7d198c7ddb47fd8aeda2f14699e639a0db19911", Value: []byte("base64:AAAAAAAQZf8AAAAAADDSolzqc5gjHWP/sCzqK7+HkAjybjGxq8SxL9ID8yEIKxrlAVRN71D/MD4dykS8vqW7cXqCh5QOclg6DEU=")}, // height 3199650 + } + var currentHeight uint64 = 3199611 + + previousBlockInfo := BUpdatesInfo{ + BlockUpdatesInfo: testBlockUpdates(), + ContractUpdatesInfo: L2ContractDataEntries{ + AllDataEntries: &previousDataEntries, + Height: &previousHeight, + }, + } + + currentBlockInfo := BUpdatesInfo{ + BlockUpdatesInfo: testBlockUpdates(), + ContractUpdatesInfo: L2ContractDataEntries{ + AllDataEntries: ¤tDataEntries, + Height: ¤tHeight, + }, + } + + equal, changes, err := compareBUpdatesInfo(currentBlockInfo, previousBlockInfo, proto.TestNetScheme, StoreBlocksLimit) + if err != nil { + return + } + require.False(t, equal) + + fmt.Println(changes.BlockUpdatesInfo) + +} + +func TestChangesGenerationSecond(t *testing.T) { + previousDataEntries := []proto.DataEntry{ + &proto.BinaryDataEntry{Key: "block_0x3a85dedc42db076c91cf61d72fa17c80777aeed70ba68dbc14d6829dd6e88614", Value: []byte("base64:AAAAAAAQYVwAAAAAADDSCpJJsd11jrOMW7AS/AHIMIDQXjqmFyhDuGt2RPNvmcCXAVTy/URmfMOj7GNweXnZpzidmxHfPBfcP5A=")}, // height 3199498 + &proto.BinaryDataEntry{Key: "block_0x3a9209ce524553a75fd0e9bde5c99ff254b1fb231916fc89755be957e51e5516", Value: []byte("base64:AAAAAAAQYywAAAAAADDSQBBubtiRmKwtaNFF1TrBhsfBu61fj3qiSrtyu1/kLLAlAVQp5GtuF7Hxji8CQ9SFOEZLLUv88nvIgg8=")}, // height 3199552 + &proto.BinaryDataEntry{Key: "block_0x3b0181d3f66d9f0ddd8e1e8567b836a01f652b4cb873aa7b7c46fc8bd1e4eeee", Value: []byte("base64:AAAAAAAQZEUAAAAAADDSZeUUyashoWjUKurzA/wVU5prm68CambvjIo1ESLoLuAaAVRaS4vOsPl9cxvg7aeRj7RFZQzdpmvV/+A=")}, // height 3199589 + } + var previousHeight uint64 = 3199552 + + currentDataEntries := []proto.DataEntry{ + &proto.BinaryDataEntry{Key: "block_0x3a85dedc42db076c91cf61d72fa17c80777aeed70ba68dbc14d6829dd6e88614", Value: []byte("base64:AAAAAAAQYVwAAAAAADDSCpJJsd11jrOMW7AS/AHIMIDQXjqmFyhDuGt2RPNvmcCXAVTy/URmfMOj7GNweXnZpzidmxHfPBfcP5A=")}, // height 3199498 + &proto.BinaryDataEntry{Key: "block_0x3a9209ce524553a75fd0e9bde5c99ff254b1fb231916fc89755be957e51e5516", Value: []byte("base64:AAAAAAAQYywAAAAAADDSQBBubtiRmKwtaNFF1TrBhsfBu61fj3qiSrtyu1/kLLAlAVQp5GtuF7Hxji8CQ9SFOEZLLUv88nvIgg8=")}, // height 3199552 + &proto.BinaryDataEntry{Key: "block_0x3b0181d3f66d9f0ddd8e1e8567b836a01f652b4cb873aa7b7c46fc8bd1e4eeee", Value: []byte("base64:AAAAAAAQZEUAAAAAADDSZeUUyashoWjUKurzA/wVU5prm68CambvjIo1ESLoLuAaAVRaS4vOsPl9cxvg7aeRj7RFZQzdpmvV/+A=")}, // height 3199589 + + &proto.BinaryDataEntry{Key: "block_0x3b5ad5c176473be02cc3d19207204af87af03f6fd75c76916765745658f7e842", Value: []byte("base64:AAAAAAAQZKkAAAAAADDSb6xEaq4RsFQruGNeGdooPmtLBnlERR15qzc/mcKcQ461AVQp5GtuF7Hxji8CQ9SFOEZLLUv88nvIgg8=")}, // height 3199599 + &proto.BinaryDataEntry{Key: "block_0x3b72ee917fea7057fb88a357f619c22f6f8ddae03b701fab7c284953ecebbc8c", Value: []byte("base64:AAAAAAAQZQkAAAAAADDSe+2CGv9zgiR7s65XEBkYzIbv6jbxcR7Zi3ByUqsX0bkwAVTEkyC5glOJH8Upe49iT3+BUV5zRaDT2dM=")}, // height 3199611 + &proto.BinaryDataEntry{Key: "block_0x3b973acae11f248a524b463db7d198c7ddb47fd8aeda2f14699e639a0db19911", Value: []byte("base64:AAAAAAAQZf8AAAAAADDSolzqc5gjHWP/sCzqK7+HkAjybjGxq8SxL9ID8yEIKxrlAVRN71D/MD4dykS8vqW7cXqCh5QOclg6DEU=")}, // height 3199650 + } + var currentHeight uint64 = 3199611 + + previousBlockInfo := BUpdatesInfo{ + BlockUpdatesInfo: testBlockUpdates(), + ContractUpdatesInfo: L2ContractDataEntries{ + AllDataEntries: &previousDataEntries, + Height: &previousHeight, + }, + } + + currentBlockInfo := BUpdatesInfo{ + BlockUpdatesInfo: testBlockUpdates(), + ContractUpdatesInfo: L2ContractDataEntries{ + AllDataEntries: ¤tDataEntries, + Height: ¤tHeight, + }, + } + + equal, changes, err := compareBUpdatesInfo(currentBlockInfo, previousBlockInfo, proto.TestNetScheme, StoreBlocksLimit) + if err != nil { + return + } + require.False(t, equal) + + fmt.Println(changes.BlockUpdatesInfo) + +} diff --git a/pkg/blockchaininfo/types.go b/pkg/blockchaininfo/types.go index d4fbe035e..1991aa535 100644 --- a/pkg/blockchaininfo/types.go +++ b/pkg/blockchaininfo/types.go @@ -34,7 +34,7 @@ func compareBUpdatesInfo(current, previous BUpdatesInfo, scheme proto.Scheme, he } equal := true - + // todo REMOVE POINTERS if current.BlockUpdatesInfo.Height != previous.BlockUpdatesInfo.Height { equal = false changes.BlockUpdatesInfo.Height = current.BlockUpdatesInfo.Height From 9fe8ed907dd54c76c9e693398d445c0a2557822f Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 16 Oct 2024 04:03:46 -0500 Subject: [PATCH 24/50] Added tests and parameters for nats subscriber --- cmd/blockchaininfo/nats_subscriber.go | 7 ++++++- pkg/blockchaininfo/blockchaininfo.go | 4 ---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cmd/blockchaininfo/nats_subscriber.go b/cmd/blockchaininfo/nats_subscriber.go index c393bf685..2f22d4c2d 100644 --- a/cmd/blockchaininfo/nats_subscriber.go +++ b/cmd/blockchaininfo/nats_subscriber.go @@ -123,7 +123,12 @@ func main() { if err != nil { log.Fatalf("failed to initialize zap logger: %v", err) } - defer l.Sync() + defer func(l *zap.Logger) { + err := l.Sync() + if err != nil { + log.Fatalf("failed to sync zap logger %v", err) + } + }(l) flag.StringVar(&blockchainType, "blockchain-type", "testnet", "Blockchain scheme (e.g., stagenet, testnet, mainnet)") flag.StringVar(&updatesPath, "updates-path", "", "File path to store contract updates") diff --git a/pkg/blockchaininfo/blockchaininfo.go b/pkg/blockchaininfo/blockchaininfo.go index 888843082..ca381b754 100644 --- a/pkg/blockchaininfo/blockchaininfo.go +++ b/pkg/blockchaininfo/blockchaininfo.go @@ -14,10 +14,6 @@ var EpochKeyPrefix = "epoch_" var blockMeta0xKeyPrefix = "block_0x" var blockMetaKeyPrefix = "blockMeta" -func removeOldEpochs(height uint64) { - -} - // Helper function to read uint64 from bytes func readInt64(data *bytes.Reader) int64 { var num int64 From e057d2a07c4a33e21f78d5f55b87c2639d0f171b Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 23 Oct 2024 22:38:25 -0500 Subject: [PATCH 25/50] Fixed tests and linter errors --- cmd/blockchaininfo/nats_subscriber.go | 14 +- cmd/node/node.go | 2 +- pkg/blockchaininfo/blockchaininfo.go | 79 ++---- pkg/blockchaininfo/blockchaininfo_test.go | 140 ---------- .../blockchaininfo_test.go | 255 ++++++++++++++++++ pkg/blockchaininfo/nats_publisher.go | 5 +- pkg/blockchaininfo/proto_converters.go | 32 +-- pkg/blockchaininfo/topics.go | 2 - pkg/blockchaininfo/types.go | 33 +-- pkg/state/appender.go | 12 +- pkg/state/invoke_applier_test.go | 3 +- 11 files changed, 322 insertions(+), 255 deletions(-) delete mode 100644 pkg/blockchaininfo/blockchaininfo_test.go create mode 100644 pkg/blockchaininfo/blockchaininfo_test/blockchaininfo_test.go diff --git a/cmd/blockchaininfo/nats_subscriber.go b/cmd/blockchaininfo/nats_subscriber.go index 2f22d4c2d..106f5e34a 100644 --- a/cmd/blockchaininfo/nats_subscriber.go +++ b/cmd/blockchaininfo/nats_subscriber.go @@ -4,8 +4,6 @@ import ( "context" "encoding/json" "flag" - "github.com/pkg/errors" - "go.uber.org/zap" "log" "os" "os/signal" @@ -13,7 +11,10 @@ import ( "strings" "syscall" + "go.uber.org/zap" + "github.com/nats-io/nats.go" + "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/blockchaininfo" g "github.com/wavesplatform/gowaves/pkg/grpc/l2/blockchain_info" "github.com/wavesplatform/gowaves/pkg/proto" @@ -109,9 +110,6 @@ func receiveContractUpdates(msg *nats.Msg, contractMsg []byte, scheme proto.Sche return contractMsg } -//const scheme = proto.TestNetScheme -//const path = "/media/alex/ExtremePro/waves/subscription/" - func main() { var ( blockchainType string @@ -124,9 +122,9 @@ func main() { log.Fatalf("failed to initialize zap logger: %v", err) } defer func(l *zap.Logger) { - err := l.Sync() - if err != nil { - log.Fatalf("failed to sync zap logger %v", err) + syncErr := l.Sync() + if syncErr != nil { + log.Fatalf("failed to sync zap logger %v", syncErr) } }(l) diff --git a/cmd/node/node.go b/cmd/node/node.go index 024094dc1..ff7695df0 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -396,7 +396,7 @@ func main() { bUpdatesExtensionState := blockchaininfo.NewBUpdatesExtensionState(blockchaininfo.StoreBlocksLimit, cfg.AddressSchemeCharacter) - l2address, cnvrtErr := proto.NewAddressFromString("3MsqKJ6o1ABE37676cHHBxJRs6huYTt72ch") + l2address, cnvrtErr := proto.NewAddressFromString("3Msx4Aq69zWUKy4d1wyKnQ4ofzEDAfv5Ngf") if cnvrtErr != nil { zap.S().Errorf("Failed to initialize L2 contract address") return diff --git a/pkg/blockchaininfo/blockchaininfo.go b/pkg/blockchaininfo/blockchaininfo.go index ca381b754..9614c1e54 100644 --- a/pkg/blockchaininfo/blockchaininfo.go +++ b/pkg/blockchaininfo/blockchaininfo.go @@ -5,16 +5,16 @@ import ( "encoding/binary" "errors" "fmt" - "github.com/wavesplatform/gowaves/pkg/proto" "strconv" "strings" + + "github.com/wavesplatform/gowaves/pkg/proto" ) -var EpochKeyPrefix = "epoch_" -var blockMeta0xKeyPrefix = "block_0x" -var blockMetaKeyPrefix = "blockMeta" +const EpochKeyPrefix = "epoch_" +const blockMeta0xKeyPrefix = "block_0x" -// Helper function to read uint64 from bytes +// Helper function to read uint64 from bytes. func readInt64(data *bytes.Reader) int64 { var num int64 err := binary.Read(data, binary.BigEndian, &num) @@ -24,30 +24,16 @@ func readInt64(data *bytes.Reader) int64 { return num } -// Decode base64 and extract blockHeight and height -func extractEpochFromBlockMeta(metaBlockValueBytes []byte) (int64, int64, error) { - //const base64Prefix = "base64:" - - //metaBlockValue := string(metaBlockValueBytes) - // Strip the "base64:" prefix - //if !strings.HasPrefix(metaBlockValue, base64Prefix) { - // return 0, 0, fmt.Errorf("invalid base64 string") - //} - - // Decode Base64 string - //data, err := base64.StdEncoding.DecodeString(metaBlockValue[len(base64Prefix):]) - //if err != nil { - // return 0, 0, fmt.Errorf("failed to decode base64 string: %w", err) - //} - - // Create a bytes reader for easier parsing +// Decode base64 and extract blockHeight and height. +func extractEpochFromBlockMeta(metaBlockValueBytes []byte) int64 { + // Create a bytes reader for easier parsing. reader := bytes.NewReader(metaBlockValueBytes) - // Extract blockHeight and height - blockHeight := readInt64(reader) - height := readInt64(reader) + // Extract blockHeight and epoch. + readInt64(reader) + epoch := readInt64(reader) - return blockHeight, height, nil + return epoch } func filterDataEntries(beforeHeight uint64, dataEntries []proto.DataEntry) ([]proto.DataEntry, error) { @@ -57,60 +43,39 @@ func filterDataEntries(beforeHeight uint64, dataEntries []proto.DataEntry) ([]pr key := entry.GetKey() switch { - // Filter "epoch_" prefixed keys + // Filter "epoch_" prefixed keys. case strings.HasPrefix(key, EpochKeyPrefix): // Extract the numeric part after "epoch_" epochStr := key[len(EpochKeyPrefix):] - // Convert the epoch number to uint64 + // Convert the epoch number to uint64. epochNumber, err := strconv.ParseUint(epochStr, 10, 64) if err != nil { return nil, err } - // Compare epoch number with beforeHeight + // Compare epoch number with beforeHeight. if epochNumber > beforeHeight { - // Add to filtered list if epochNumber is greater + // Add to filtered list if epochNumber is greater. filteredDataEntries = append(filteredDataEntries, entry) } - // Filter block_0x binary entries + // Filter block_0x binary entries. case strings.HasPrefix(key, blockMeta0xKeyPrefix): - // Extract blockHeight and height from base64 + // Extract blockHeight and height from base64. binaryEntry, ok := entry.(*proto.BinaryDataEntry) if !ok { return nil, errors.New("failed to convert block meta key to binary data entry") } - _, epoch, err := extractEpochFromBlockMeta(binaryEntry.Value) - if err != nil { - return nil, err - } - - // Compare height with beforeHeight - if epoch > int64(beforeHeight) { - // Add to filtered list if height is less than beforeHeight - filteredDataEntries = append(filteredDataEntries, entry) - } - - // Filter blockMeta binary entries - case strings.HasPrefix(key, blockMetaKeyPrefix): - // Extract blockHeight and height from base64 - binaryEntry, ok := entry.(*proto.BinaryDataEntry) - if !ok { - return nil, errors.New("failed to convert block meta key to binary data entry") - } - _, epoch, err := extractEpochFromBlockMeta(binaryEntry.Value) - if err != nil { - return nil, err - } + epoch := extractEpochFromBlockMeta(binaryEntry.Value) - // Compare height with beforeHeight + // Compare height with beforeHeight. if epoch > int64(beforeHeight) { - // Add to filtered list if height is less than beforeHeight + // Add to filtered list if height is less than beforeHeight. filteredDataEntries = append(filteredDataEntries, entry) } - // Default case to handle non-epoch and non-base64 entries + // Default case to handle non-epoch and non-base64 entries. default: filteredDataEntries = append(filteredDataEntries, entry) } diff --git a/pkg/blockchaininfo/blockchaininfo_test.go b/pkg/blockchaininfo/blockchaininfo_test.go deleted file mode 100644 index 8c078693c..000000000 --- a/pkg/blockchaininfo/blockchaininfo_test.go +++ /dev/null @@ -1,140 +0,0 @@ -package blockchaininfo - -import ( - "fmt" - "github.com/stretchr/testify/require" - "github.com/wavesplatform/gowaves/pkg/proto" - "testing" -) - -//func TestAddressFromPublicKey(t *testing.T) { -// tests := []struct { -// publicKey string -// scheme byte -// address string -// }{ -// {"5CnGfSjguYfzWzaRmbxzCbF5qRNGTXEvayytSANkqQ6A", MainNetScheme, "3PQ8bp1aoqHQo3icNqFv6VM36V1jzPeaG1v"}, -// {"BstqhtQjQN9X78i6mEpaNnf6cMsZZRDVHNv3CqguXbxq", MainNetScheme, "3PQvBCHPnxXprTNq1rwdcDuxt6VGKRTM9wT"}, -// {"FckK43s6tQ9BBW77hSKuyRnfnrKuf6B7sEuJzcgkSDVf", MainNetScheme, "3PETfqHg9HyL92nfiujN5fBW6Ac1TYiVAAc"}, -// {"5CnGfSjguYfzWzaRmbxzCbF5qRNGTXEvayytSANkqQ6A", TestNetScheme, "3NC7nrggwhk2AbRC7kzv92yDjbVyALeGzE5"}, -// {"BstqhtQjQN9X78i6mEpaNnf6cMsZZRDVHNv3CqguXbxq", TestNetScheme, "3NCuNExVvpzSE15QkngdemY9XCyVVGhHA9h"}, -// {"5CnGfSjguYfzWzaRmbxzCbF5qRNGTXEvayytSANkqQ6A", 'x', "3cgHWJbRKGEhi32DEe6ucVV24FfF7u2mxit"}, -// {"BstqhtQjQN9X78i6mEpaNnf6cMsZZRDVHNv3CqguXbxq", 'x', "3ch55gsEJPV7mSgRsfnd8E3wqs8mSqyTNCj"}, -// } -// -// -// -// for _, tc := range tests { -// if b, err := base58.Decode(tc.publicKey); assert.NoError(t, err) { -// var pk crypto.PublicKey -// copy(pk[:], b) -// if address, err := NewAddressFromPublicKey(tc.scheme, pk); assert.NoError(t, err) { -// assert.Equal(t, tc.address, address.String()) -// } -// } -// } -//} - -func testBlockUpdates() BlockUpdatesInfo { - var b BlockUpdatesInfo - - var ( - height uint64 = 100 - VRF = proto.B58Bytes{} - BlockID = proto.BlockID{} - BlockHeader = proto.BlockHeader{} - ) - - b.Height = &height - b.VRF = &VRF - b.BlockID = &BlockID - b.BlockHeader = &BlockHeader - - return b -} - -func TestChangesGeneration(t *testing.T) { - previousDataEntries := []proto.DataEntry{ - &proto.BinaryDataEntry{Key: "block_0x3a85dedc42db076c91cf61d72fa17c80777aeed70ba68dbc14d6829dd6e88614", Value: []byte("base64:AAAAAAAQYVwAAAAAADDSCpJJsd11jrOMW7AS/AHIMIDQXjqmFyhDuGt2RPNvmcCXAVTy/URmfMOj7GNweXnZpzidmxHfPBfcP5A=")}, // height 3199498 - &proto.BinaryDataEntry{Key: "block_0x3a9209ce524553a75fd0e9bde5c99ff254b1fb231916fc89755be957e51e5516", Value: []byte("base64:AAAAAAAQYywAAAAAADDSQBBubtiRmKwtaNFF1TrBhsfBu61fj3qiSrtyu1/kLLAlAVQp5GtuF7Hxji8CQ9SFOEZLLUv88nvIgg8=")}, // height 3199552 - &proto.BinaryDataEntry{Key: "block_0x3b0181d3f66d9f0ddd8e1e8567b836a01f652b4cb873aa7b7c46fc8bd1e4eeee", Value: []byte("base64:AAAAAAAQZEUAAAAAADDSZeUUyashoWjUKurzA/wVU5prm68CambvjIo1ESLoLuAaAVRaS4vOsPl9cxvg7aeRj7RFZQzdpmvV/+A=")}, // height 3199589 - } - var previousHeight uint64 = 3199552 - - currentDataEntries := []proto.DataEntry{ - &proto.BinaryDataEntry{Key: "block_0x3b5ad5c176473be02cc3d19207204af87af03f6fd75c76916765745658f7e842", Value: []byte("base64:AAAAAAAQZKkAAAAAADDSb6xEaq4RsFQruGNeGdooPmtLBnlERR15qzc/mcKcQ461AVQp5GtuF7Hxji8CQ9SFOEZLLUv88nvIgg8=")}, // height 3199599 - &proto.BinaryDataEntry{Key: "block_0x3b72ee917fea7057fb88a357f619c22f6f8ddae03b701fab7c284953ecebbc8c", Value: []byte("base64:AAAAAAAQZQkAAAAAADDSe+2CGv9zgiR7s65XEBkYzIbv6jbxcR7Zi3ByUqsX0bkwAVTEkyC5glOJH8Upe49iT3+BUV5zRaDT2dM=")}, // height 3199611 - &proto.BinaryDataEntry{Key: "block_0x3b973acae11f248a524b463db7d198c7ddb47fd8aeda2f14699e639a0db19911", Value: []byte("base64:AAAAAAAQZf8AAAAAADDSolzqc5gjHWP/sCzqK7+HkAjybjGxq8SxL9ID8yEIKxrlAVRN71D/MD4dykS8vqW7cXqCh5QOclg6DEU=")}, // height 3199650 - } - var currentHeight uint64 = 3199611 - - previousBlockInfo := BUpdatesInfo{ - BlockUpdatesInfo: testBlockUpdates(), - ContractUpdatesInfo: L2ContractDataEntries{ - AllDataEntries: &previousDataEntries, - Height: &previousHeight, - }, - } - - currentBlockInfo := BUpdatesInfo{ - BlockUpdatesInfo: testBlockUpdates(), - ContractUpdatesInfo: L2ContractDataEntries{ - AllDataEntries: ¤tDataEntries, - Height: ¤tHeight, - }, - } - - equal, changes, err := compareBUpdatesInfo(currentBlockInfo, previousBlockInfo, proto.TestNetScheme, StoreBlocksLimit) - if err != nil { - return - } - require.False(t, equal) - - fmt.Println(changes.BlockUpdatesInfo) - -} - -func TestChangesGenerationSecond(t *testing.T) { - previousDataEntries := []proto.DataEntry{ - &proto.BinaryDataEntry{Key: "block_0x3a85dedc42db076c91cf61d72fa17c80777aeed70ba68dbc14d6829dd6e88614", Value: []byte("base64:AAAAAAAQYVwAAAAAADDSCpJJsd11jrOMW7AS/AHIMIDQXjqmFyhDuGt2RPNvmcCXAVTy/URmfMOj7GNweXnZpzidmxHfPBfcP5A=")}, // height 3199498 - &proto.BinaryDataEntry{Key: "block_0x3a9209ce524553a75fd0e9bde5c99ff254b1fb231916fc89755be957e51e5516", Value: []byte("base64:AAAAAAAQYywAAAAAADDSQBBubtiRmKwtaNFF1TrBhsfBu61fj3qiSrtyu1/kLLAlAVQp5GtuF7Hxji8CQ9SFOEZLLUv88nvIgg8=")}, // height 3199552 - &proto.BinaryDataEntry{Key: "block_0x3b0181d3f66d9f0ddd8e1e8567b836a01f652b4cb873aa7b7c46fc8bd1e4eeee", Value: []byte("base64:AAAAAAAQZEUAAAAAADDSZeUUyashoWjUKurzA/wVU5prm68CambvjIo1ESLoLuAaAVRaS4vOsPl9cxvg7aeRj7RFZQzdpmvV/+A=")}, // height 3199589 - } - var previousHeight uint64 = 3199552 - - currentDataEntries := []proto.DataEntry{ - &proto.BinaryDataEntry{Key: "block_0x3a85dedc42db076c91cf61d72fa17c80777aeed70ba68dbc14d6829dd6e88614", Value: []byte("base64:AAAAAAAQYVwAAAAAADDSCpJJsd11jrOMW7AS/AHIMIDQXjqmFyhDuGt2RPNvmcCXAVTy/URmfMOj7GNweXnZpzidmxHfPBfcP5A=")}, // height 3199498 - &proto.BinaryDataEntry{Key: "block_0x3a9209ce524553a75fd0e9bde5c99ff254b1fb231916fc89755be957e51e5516", Value: []byte("base64:AAAAAAAQYywAAAAAADDSQBBubtiRmKwtaNFF1TrBhsfBu61fj3qiSrtyu1/kLLAlAVQp5GtuF7Hxji8CQ9SFOEZLLUv88nvIgg8=")}, // height 3199552 - &proto.BinaryDataEntry{Key: "block_0x3b0181d3f66d9f0ddd8e1e8567b836a01f652b4cb873aa7b7c46fc8bd1e4eeee", Value: []byte("base64:AAAAAAAQZEUAAAAAADDSZeUUyashoWjUKurzA/wVU5prm68CambvjIo1ESLoLuAaAVRaS4vOsPl9cxvg7aeRj7RFZQzdpmvV/+A=")}, // height 3199589 - - &proto.BinaryDataEntry{Key: "block_0x3b5ad5c176473be02cc3d19207204af87af03f6fd75c76916765745658f7e842", Value: []byte("base64:AAAAAAAQZKkAAAAAADDSb6xEaq4RsFQruGNeGdooPmtLBnlERR15qzc/mcKcQ461AVQp5GtuF7Hxji8CQ9SFOEZLLUv88nvIgg8=")}, // height 3199599 - &proto.BinaryDataEntry{Key: "block_0x3b72ee917fea7057fb88a357f619c22f6f8ddae03b701fab7c284953ecebbc8c", Value: []byte("base64:AAAAAAAQZQkAAAAAADDSe+2CGv9zgiR7s65XEBkYzIbv6jbxcR7Zi3ByUqsX0bkwAVTEkyC5glOJH8Upe49iT3+BUV5zRaDT2dM=")}, // height 3199611 - &proto.BinaryDataEntry{Key: "block_0x3b973acae11f248a524b463db7d198c7ddb47fd8aeda2f14699e639a0db19911", Value: []byte("base64:AAAAAAAQZf8AAAAAADDSolzqc5gjHWP/sCzqK7+HkAjybjGxq8SxL9ID8yEIKxrlAVRN71D/MD4dykS8vqW7cXqCh5QOclg6DEU=")}, // height 3199650 - } - var currentHeight uint64 = 3199611 - - previousBlockInfo := BUpdatesInfo{ - BlockUpdatesInfo: testBlockUpdates(), - ContractUpdatesInfo: L2ContractDataEntries{ - AllDataEntries: &previousDataEntries, - Height: &previousHeight, - }, - } - - currentBlockInfo := BUpdatesInfo{ - BlockUpdatesInfo: testBlockUpdates(), - ContractUpdatesInfo: L2ContractDataEntries{ - AllDataEntries: ¤tDataEntries, - Height: ¤tHeight, - }, - } - - equal, changes, err := compareBUpdatesInfo(currentBlockInfo, previousBlockInfo, proto.TestNetScheme, StoreBlocksLimit) - if err != nil { - return - } - require.False(t, equal) - - fmt.Println(changes.BlockUpdatesInfo) - -} diff --git a/pkg/blockchaininfo/blockchaininfo_test/blockchaininfo_test.go b/pkg/blockchaininfo/blockchaininfo_test/blockchaininfo_test.go new file mode 100644 index 000000000..77f7f1233 --- /dev/null +++ b/pkg/blockchaininfo/blockchaininfo_test/blockchaininfo_test.go @@ -0,0 +1,255 @@ +package blockchaininfo_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + "github.com/wavesplatform/gowaves/pkg/blockchaininfo" + "github.com/wavesplatform/gowaves/pkg/proto" +) + +// some random test data. +func testBlockUpdates() blockchaininfo.BlockUpdatesInfo { + var b blockchaininfo.BlockUpdatesInfo + + var ( + height uint64 = 100 + vrf = proto.B58Bytes{} + blockID = proto.BlockID{} + blockHeader = proto.BlockHeader{} + ) + + b.Height = height + b.VRF = vrf + b.BlockID = blockID + b.BlockHeader = blockHeader + + return b +} + +func containsDataEntry(changes []proto.DataEntry, key string, dataType string) bool { + for _, entry := range changes { + // Check if the key matches + if entry.GetKey() == key { + // Use a type switch to check the type + switch entry.(type) { + case *proto.BinaryDataEntry: + if dataType == "binary" { + return true + } + case *proto.DeleteDataEntry: + if dataType == "delete" { + return true + } + default: + } + } + } + return false +} + +// This tests check whether the changes generation will show the new records and will remove the old ones. +// Previous state contains 3 records, but the current state doesn't contain them and has 3 new records. +// The change result must be - 3 new records, and 3 old records for deletion. + +func TestChangesGenerationNewEntries(t *testing.T) { + previousFirstKey := "block_0x3a85dedc42db076c91cf61d72fa17c80777aeed70ba68dbc14d6829dd6e88614" + previousSecondKey := "block_0x3a9209ce524553a75fd0e9bde5c99ff254b1fb231916fc89755be957e51e5516" + previousThirdKey := "block_0x3b0181d3f66d9f0ddd8e1e8567b836a01f652b4cb873aa7b7c46fc8bd1e4eeee" + + previousDataEntries := []proto.DataEntry{ + &proto.BinaryDataEntry{Key: previousFirstKey, + Value: []byte("base64:AAAAAAAQYVwAAAAAADDSCpJJsd11jrOMW7AS/AHIMIDQ" + + "XjqmFyhDuGt2RPNvmcCXAVTy/URmfMOj7GNweXnZpzidmxHfPBfcP5A=")}, // height 3199498. + &proto.BinaryDataEntry{Key: previousSecondKey, + Value: []byte("base64:AAAAAAAQYywAAAAAADDSQBBubtiRmKwtaNFF1TrBhsfBu" + + "61fj3qiSrtyu1/kLLAlAVQp5GtuF7Hxji8CQ9SFOEZLLUv88nvIgg8=")}, // height 3199552. + &proto.BinaryDataEntry{Key: previousThirdKey, + Value: []byte("base64:AAAAAAAQZEUAAAAAADDSZeUUyashoWjUKurzA/wVU5prm" + + "68CambvjIo1ESLoLuAaAVRaS4vOsPl9cxvg7aeRj7RFZQzdpmvV/+A=")}, // height 3199589. + } + var previousHeight uint64 = 3199552 + + currentFirstKey := "block_0x3b5ad5c176473be02cc3d19207204af87af03f6fd75c76916765745658f7e842" + currentSecondKey := "block_0x3b72ee917fea7057fb88a357f619c22f6f8ddae03b701fab7c284953ecebbc8c" + currentThirdKey := "block_0x3b973acae11f248a524b463db7d198c7ddb47fd8aeda2f14699e639a0db19911" + + currentDataEntries := []proto.DataEntry{ + &proto.BinaryDataEntry{Key: currentFirstKey, + Value: []byte("base64:AAAAAAAQZKkAAAAAADDSb6xEaq4RsFQruG" + + "NeGdooPmtLBnlERR15qzc/mcKcQ461AVQp5GtuF7Hxji8CQ9SFOEZLLUv88nvIgg8=")}, // height 3199599. + &proto.BinaryDataEntry{Key: currentSecondKey, + Value: []byte("base64:AAAAAAAQZQkAAAAAADDSe+2CGv9zgiR7s" + + "65XEBkYzIbv6jbxcR7Zi3ByUqsX0bkwAVTEkyC5glOJH8Upe49iT3+BUV5zRaDT2dM=")}, // height 3199611. + &proto.BinaryDataEntry{Key: currentThirdKey, + Value: []byte("base64:AAAAAAAQZf8AAAAAADDSolzqc5gjHWP/s" + + "CzqK7+HkAjybjGxq8SxL9ID8yEIKxrlAVRN71D/MD4dykS8vqW7cXqCh5QOclg6DEU=")}, // height 3199650. + } + var currentHeight uint64 = 3199611 + + previousBlockInfo := blockchaininfo.BUpdatesInfo{ + BlockUpdatesInfo: testBlockUpdates(), + ContractUpdatesInfo: blockchaininfo.L2ContractDataEntries{ + AllDataEntries: previousDataEntries, + Height: previousHeight, + }, + } + + currentBlockInfo := blockchaininfo.BUpdatesInfo{ + BlockUpdatesInfo: testBlockUpdates(), + ContractUpdatesInfo: blockchaininfo.L2ContractDataEntries{ + AllDataEntries: currentDataEntries, + Height: currentHeight, + }, + } + + equal, changes, err := blockchaininfo.CompareBUpdatesInfo(currentBlockInfo, previousBlockInfo, + proto.TestNetScheme, blockchaininfo.StoreBlocksLimit) + if err != nil { + return + } + require.False(t, equal) + require.True(t, containsDataEntry(changes.ContractUpdatesInfo.AllDataEntries, currentFirstKey, "binary")) + require.True(t, containsDataEntry(changes.ContractUpdatesInfo.AllDataEntries, currentSecondKey, "binary")) + require.True(t, containsDataEntry(changes.ContractUpdatesInfo.AllDataEntries, currentThirdKey, "binary")) + + require.True(t, containsDataEntry(changes.ContractUpdatesInfo.AllDataEntries, previousFirstKey, "delete")) + require.True(t, containsDataEntry(changes.ContractUpdatesInfo.AllDataEntries, previousSecondKey, "delete")) + require.True(t, containsDataEntry(changes.ContractUpdatesInfo.AllDataEntries, previousThirdKey, "delete")) +} + +// This tests check whether the changes generation will only show the new records and will not remove the old ones. +// Previous state contains 3 records, the current state contains both the previous new records and 3 new ones. +// The change result must be - 3 new records. +func TestChangesGenerationContainsPrevious(t *testing.T) { + previousFirstKey := "block_0x3a85dedc42db076c91cf61d72fa17c80777aeed70ba68dbc14d6829dd6e88614" + previousSecondKey := "block_0x3a9209ce524553a75fd0e9bde5c99ff254b1fb231916fc89755be957e51e5516" + previousThirdKey := "block_0x3b0181d3f66d9f0ddd8e1e8567b836a01f652b4cb873aa7b7c46fc8bd1e4eeee" + + previousDataEntries := []proto.DataEntry{ + &proto.BinaryDataEntry{Key: previousFirstKey, + Value: []byte("base64:AAAAAAAQYVwAAAAAADDSCpJJsd11jrOMW7AS/AHIMIDQXj" + + "qmFyhDuGt2RPNvmcCXAVTy/URmfMOj7GNweXnZpzidmxHfPBfcP5A=")}, // height 3199498. + &proto.BinaryDataEntry{Key: previousSecondKey, + Value: []byte("base64:AAAAAAAQYywAAAAAADDSQBBubtiRmKwtaNFF1TrBhsfBu61" + + "fj3qiSrtyu1/kLLAlAVQp5GtuF7Hxji8CQ9SFOEZLLUv88nvIgg8=")}, // height 3199552. + &proto.BinaryDataEntry{Key: previousThirdKey, + Value: []byte("base64:AAAAAAAQZEUAAAAAADDSZeUUyashoWjUKurzA/wVU5prm68Ca" + + "mbvjIo1ESLoLuAaAVRaS4vOsPl9cxvg7aeRj7RFZQzdpmvV/+A=")}, // height 3199589. + } + var previousHeight uint64 = 3199552 + + currentFirstKey := "block_0x3b5ad5c176473be02cc3d19207204af87af03f6fd75c76916765745658f7e842" + currentSecondKey := "block_0x3b72ee917fea7057fb88a357f619c22f6f8ddae03b701fab7c284953ecebbc8c" + currentThirdKey := "block_0x3b973acae11f248a524b463db7d198c7ddb47fd8aeda2f14699e639a0db19911" + + currentDataEntries := []proto.DataEntry{ + &proto.BinaryDataEntry{Key: previousFirstKey, + Value: []byte("base64:AAAAAAAQYVwAAAAAADDSCpJJsd11jrOMW7AS/A" + + "HIMIDQXjqmFyhDuGt2RPNvmcCXAVTy/URmfMOj7GNweXnZpzidmxHfPBfcP5A=")}, // height 3199498. + &proto.BinaryDataEntry{Key: previousSecondKey, + Value: []byte("base64:AAAAAAAQYywAAAAAADDSQBBubtiRmKwtaNFF1T" + + "rBhsfBu61fj3qiSrtyu1/kLLAlAVQp5GtuF7Hxji8CQ9SFOEZLLUv88nvIgg8=")}, // height 3199552. + &proto.BinaryDataEntry{Key: previousThirdKey, + Value: []byte("base64:AAAAAAAQZEUAAAAAADDSZeUUyashoWjUKurzA/wV" + + "U5prm68CambvjIo1ESLoLuAaAVRaS4vOsPl9cxvg7aeRj7RFZQzdpmvV/+A=")}, // height 3199589. + + &proto.BinaryDataEntry{Key: currentFirstKey, + Value: []byte("base64:AAAAAAAQZKkAAAAAADDSb6xEaq4RsFQruGNeGdoo" + + "PmtLBnlERR15qzc/mcKcQ461AVQp5GtuF7Hxji8CQ9SFOEZLLUv88nvIgg8=")}, // height 3199599. + &proto.BinaryDataEntry{Key: currentSecondKey, + Value: []byte("base64:AAAAAAAQZQkAAAAAADDSe+2CGv9zgiR7s65XEBkYz" + + "Ibv6jbxcR7Zi3ByUqsX0bkwAVTEkyC5glOJH8Upe49iT3+BUV5zRaDT2dM=")}, // height 3199611. + &proto.BinaryDataEntry{Key: currentThirdKey, + Value: []byte("base64:AAAAAAAQZf8AAAAAADDSolzqc5gjHWP/sCzqK7+Hk" + + "AjybjGxq8SxL9ID8yEIKxrlAVRN71D/MD4dykS8vqW7cXqCh5QOclg6DEU=")}, // height 3199650. + } + var currentHeight uint64 = 3199611 + + previousBlockInfo := blockchaininfo.BUpdatesInfo{ + BlockUpdatesInfo: testBlockUpdates(), + ContractUpdatesInfo: blockchaininfo.L2ContractDataEntries{ + AllDataEntries: previousDataEntries, + Height: previousHeight, + }, + } + + currentBlockInfo := blockchaininfo.BUpdatesInfo{ + BlockUpdatesInfo: testBlockUpdates(), + ContractUpdatesInfo: blockchaininfo.L2ContractDataEntries{ + AllDataEntries: currentDataEntries, + Height: currentHeight, + }, + } + + equal, changes, err := blockchaininfo.CompareBUpdatesInfo(currentBlockInfo, previousBlockInfo, + proto.TestNetScheme, blockchaininfo.StoreBlocksLimit) + if err != nil { + return + } + require.False(t, equal) + + require.True(t, containsDataEntry(changes.ContractUpdatesInfo.AllDataEntries, currentFirstKey, "binary")) + require.True(t, containsDataEntry(changes.ContractUpdatesInfo.AllDataEntries, currentSecondKey, "binary")) + require.True(t, containsDataEntry(changes.ContractUpdatesInfo.AllDataEntries, currentThirdKey, "binary")) +} + +// This tests check whether the changes generation will not show anything, because there are no changes. +// Previous state contains 3 records, the current state contains the same records. +// The change result must be - 0 records. +func TestNoChangesGeneration(t *testing.T) { + previousFirstKey := "block_0x3a85dedc42db076c91cf61d72fa17c80777aeed70ba68dbc14d6829dd6e88614" + previousSecondKey := "block_0x3a9209ce524553a75fd0e9bde5c99ff254b1fb231916fc89755be957e51e5516" + previousThirdKey := "block_0x3b0181d3f66d9f0ddd8e1e8567b836a01f652b4cb873aa7b7c46fc8bd1e4eeee" + + previousDataEntries := []proto.DataEntry{ + &proto.BinaryDataEntry{Key: previousFirstKey, + Value: []byte("base64:AAAAAAAQYVwAAAAAADDSCpJJsd11jrO" + + "MW7AS/AHIMIDQXjqmFyhDuGt2RPNvmcCXAVTy/URmfMOj7GNweXnZpzidmxHfPBfcP5A=")}, // height 3199498. + &proto.BinaryDataEntry{Key: previousSecondKey, + Value: []byte("base64:AAAAAAAQYywAAAAAADDSQBBubtiRmKwt" + + "aNFF1TrBhsfBu61fj3qiSrtyu1/kLLAlAVQp5GtuF7Hxji8CQ9SFOEZLLUv88nvIgg8=")}, // height 3199552. + &proto.BinaryDataEntry{Key: previousThirdKey, + Value: []byte("base64:AAAAAAAQZEUAAAAAADDSZeUUyashoWjU" + + "KurzA/wVU5prm68CambvjIo1ESLoLuAaAVRaS4vOsPl9cxvg7aeRj7RFZQzdpmvV/+A=")}, // height 3199589. + } + var previousHeight uint64 = 3199552 + + currentDataEntries := []proto.DataEntry{ + &proto.BinaryDataEntry{Key: previousFirstKey, + Value: []byte("base64:AAAAAAAQYVwAAAAAADDSCpJJsd11jrO" + + "MW7AS/AHIMIDQXjqmFyhDuGt2RPNvmcCXAVTy/URmfMOj7GNweXnZpzidmxHfPBfcP5A=")}, // height 3199498. + &proto.BinaryDataEntry{Key: previousSecondKey, + Value: []byte("base64:AAAAAAAQYywAAAAAADDSQBBubtiRmKwta" + + "NFF1TrBhsfBu61fj3qiSrtyu1/kLLAlAVQp5GtuF7Hxji8CQ9SFOEZLLUv88nvIgg8=")}, // height 3199552. + &proto.BinaryDataEntry{Key: previousThirdKey, + Value: []byte("base64:AAAAAAAQZEUAAAAAADDSZeUUyashoWjU" + + "KurzA/wVU5prm68CambvjIo1ESLoLuAaAVRaS4vOsPl9cxvg7aeRj7RFZQzdpmvV/+A=")}, // height 3199589. + } + var currentHeight uint64 = 3199611 + + previousBlockInfo := blockchaininfo.BUpdatesInfo{ + BlockUpdatesInfo: testBlockUpdates(), + ContractUpdatesInfo: blockchaininfo.L2ContractDataEntries{ + AllDataEntries: previousDataEntries, + Height: previousHeight, + }, + } + + currentBlockInfo := blockchaininfo.BUpdatesInfo{ + BlockUpdatesInfo: testBlockUpdates(), + ContractUpdatesInfo: blockchaininfo.L2ContractDataEntries{ + AllDataEntries: currentDataEntries, + Height: currentHeight, + }, + } + + equal, changes, err := blockchaininfo.CompareBUpdatesInfo(currentBlockInfo, previousBlockInfo, + proto.TestNetScheme, blockchaininfo.StoreBlocksLimit) + if err != nil { + return + } + require.True(t, equal) + + require.True(t, len(changes.ContractUpdatesInfo.AllDataEntries) == 0) +} diff --git a/pkg/blockchaininfo/nats_publisher.go b/pkg/blockchaininfo/nats_publisher.go index f2833a634..84956eac4 100644 --- a/pkg/blockchaininfo/nats_publisher.go +++ b/pkg/blockchaininfo/nats_publisher.go @@ -163,11 +163,12 @@ func handleBlockchainUpdates(updates BUpdatesInfo, ok bool, if bu.previousState == nil { // publish initial updates - filteredDataEntries, err := filterDataEntries(*updates.BlockUpdatesInfo.Height-bu.Limit, *updates.ContractUpdatesInfo.AllDataEntries) + filteredDataEntries, err := filterDataEntries(updates.BlockUpdatesInfo.Height-bu.Limit, + updates.ContractUpdatesInfo.AllDataEntries) if err != nil { return } - updates.ContractUpdatesInfo.AllDataEntries = &filteredDataEntries + updates.ContractUpdatesInfo.AllDataEntries = filteredDataEntries pblshErr := bu.publishUpdates(updates, nc, scheme) if pblshErr != nil { log.Printf("failed to publish updates, %v", pblshErr) diff --git a/pkg/blockchaininfo/proto_converters.go b/pkg/blockchaininfo/proto_converters.go index 4b1d3bc97..b43266780 100644 --- a/pkg/blockchaininfo/proto_converters.go +++ b/pkg/blockchaininfo/proto_converters.go @@ -8,30 +8,18 @@ import ( func BUpdatesInfoToProto(blockInfo BUpdatesInfo, scheme proto.Scheme) (*g.BlockInfo, error) { var ( - height uint64 - vrf []byte - blockID []byte blockHeader *waves.Block_Header err error ) - if blockInfo.BlockUpdatesInfo.Height != nil { - height = *blockInfo.BlockUpdatesInfo.Height - } - if blockInfo.BlockUpdatesInfo.VRF != nil { - vrf = *blockInfo.BlockUpdatesInfo.VRF - } - if blockInfo.BlockUpdatesInfo.BlockID != nil { - blockID = blockInfo.BlockUpdatesInfo.BlockID.Bytes() - } blockHeader, err = blockInfo.BlockUpdatesInfo.BlockHeader.HeaderToProtobufHeader(scheme) if err != nil { return nil, err } return &g.BlockInfo{ - Height: height, - VRF: vrf, - BlockID: blockID, + Height: blockInfo.BlockUpdatesInfo.Height, + VRF: blockInfo.BlockUpdatesInfo.VRF, + BlockID: blockInfo.BlockUpdatesInfo.BlockID.Bytes(), BlockHeader: blockHeader, }, nil } @@ -47,22 +35,22 @@ func BUpdatesInfoFromProto(blockInfoProto *g.BlockInfo) (BlockUpdatesInfo, error } vrf := proto.B58Bytes(blockInfoProto.VRF) return BlockUpdatesInfo{ - Height: &blockInfoProto.Height, - VRF: &vrf, - BlockID: &blockID, - BlockHeader: blockHeader, + Height: blockInfoProto.Height, + VRF: vrf, + BlockID: blockID, + BlockHeader: *blockHeader, }, nil } func L2ContractDataEntriesToProto(contractData L2ContractDataEntries) *g.L2ContractDataEntries { var protobufDataEntries []*waves.DataEntry - for _, entry := range *contractData.AllDataEntries { + for _, entry := range contractData.AllDataEntries { entryProto := entry.ToProtobuf() protobufDataEntries = append(protobufDataEntries, entryProto) } return &g.L2ContractDataEntries{ DataEntries: protobufDataEntries, - Height: *contractData.Height, + Height: contractData.Height, } } @@ -78,5 +66,5 @@ func L2ContractDataEntriesFromProto(protoDataEntries *g.L2ContractDataEntries, dataEntries = append(dataEntries, entry) } - return L2ContractDataEntries{AllDataEntries: &dataEntries, Height: &protoDataEntries.Height}, nil + return L2ContractDataEntries{AllDataEntries: dataEntries, Height: protoDataEntries.Height}, nil } diff --git a/pkg/blockchaininfo/topics.go b/pkg/blockchaininfo/topics.go index 0fdb08b32..51bb99b01 100644 --- a/pkg/blockchaininfo/topics.go +++ b/pkg/blockchaininfo/topics.go @@ -6,5 +6,3 @@ const ( microblockUpdates = "microblock_topic" ContractUpdates = "contract_topic" ) - -// var Topics = []string{BlockUpdates, microblockUpdates, ContractUpdates} diff --git a/pkg/blockchaininfo/types.go b/pkg/blockchaininfo/types.go index 1991aa535..1568a6990 100644 --- a/pkg/blockchaininfo/types.go +++ b/pkg/blockchaininfo/types.go @@ -8,16 +8,16 @@ import ( // BlockUpdatesInfo Block updates. type BlockUpdatesInfo struct { - Height *uint64 `json:"height"` - VRF *proto.B58Bytes `json:"vrf"` - BlockID *proto.BlockID `json:"block_id"` - BlockHeader *proto.BlockHeader `json:"block_header"` + Height uint64 `json:"height"` + VRF proto.B58Bytes `json:"vrf"` + BlockID proto.BlockID `json:"block_id"` + BlockHeader proto.BlockHeader `json:"block_header"` } // L2ContractDataEntries L2 contract data entries. type L2ContractDataEntries struct { - AllDataEntries *[]proto.DataEntry `json:"all_data_entries"` - Height *uint64 `json:"height"` + AllDataEntries []proto.DataEntry `json:"all_data_entries"` + Height uint64 `json:"height"` } type BUpdatesInfo struct { @@ -27,7 +27,8 @@ type BUpdatesInfo struct { // TODO wrap errors. -func compareBUpdatesInfo(current, previous BUpdatesInfo, scheme proto.Scheme, heightLimit uint64) (bool, BUpdatesInfo, error) { +func CompareBUpdatesInfo(current, previous BUpdatesInfo, + scheme proto.Scheme, heightLimit uint64) (bool, BUpdatesInfo, error) { changes := BUpdatesInfo{ BlockUpdatesInfo: BlockUpdatesInfo{}, ContractUpdatesInfo: L2ContractDataEntries{}, @@ -39,7 +40,7 @@ func compareBUpdatesInfo(current, previous BUpdatesInfo, scheme proto.Scheme, he equal = false changes.BlockUpdatesInfo.Height = current.BlockUpdatesInfo.Height } - if !bytes.Equal(*current.BlockUpdatesInfo.VRF, *previous.BlockUpdatesInfo.VRF) { + if !bytes.Equal(current.BlockUpdatesInfo.VRF, previous.BlockUpdatesInfo.VRF) { equal = false changes.BlockUpdatesInfo.VRF = current.BlockUpdatesInfo.VRF } @@ -57,11 +58,13 @@ func compareBUpdatesInfo(current, previous BUpdatesInfo, scheme proto.Scheme, he changes.BlockUpdatesInfo.BlockHeader = current.BlockUpdatesInfo.BlockHeader } - previousFilteredDataEntries, err := filterDataEntries(*previous.BlockUpdatesInfo.Height-heightLimit, *previous.ContractUpdatesInfo.AllDataEntries) + previousFilteredDataEntries, err := filterDataEntries(previous.BlockUpdatesInfo.Height-heightLimit, + previous.ContractUpdatesInfo.AllDataEntries) if err != nil { return false, BUpdatesInfo{}, err } - currentFilteredDataEntries, err := filterDataEntries(*current.BlockUpdatesInfo.Height-heightLimit, *current.ContractUpdatesInfo.AllDataEntries) + currentFilteredDataEntries, err := filterDataEntries(current.BlockUpdatesInfo.Height-heightLimit, + current.ContractUpdatesInfo.AllDataEntries) if err != nil { return false, BUpdatesInfo{}, err } @@ -73,16 +76,14 @@ func compareBUpdatesInfo(current, previous BUpdatesInfo, scheme proto.Scheme, he } if !equalEntries { equal = false - changes.ContractUpdatesInfo.AllDataEntries = &dataEntryChanges + changes.ContractUpdatesInfo.AllDataEntries = dataEntryChanges changes.ContractUpdatesInfo.Height = current.BlockUpdatesInfo.Height } + return equal, changes, nil } -func compareBlockHeader(a, b *proto.BlockHeader, scheme proto.Scheme) (bool, error) { - if a == nil || b == nil { - return a == b, nil // both nil or one of them is nil - } +func compareBlockHeader(a, b proto.BlockHeader, scheme proto.Scheme) (bool, error) { blockAbytes, err := a.MarshalHeader(scheme) if err != nil { return false, err @@ -151,5 +152,5 @@ func compareDataEntries(current, previous proto.DataEntries) (bool, []proto.Data } func statesEqual(state BUpdatesExtensionState, scheme proto.Scheme) (bool, BUpdatesInfo, error) { - return compareBUpdatesInfo(*state.currentState, *state.previousState, scheme, state.Limit) + return CompareBUpdatesInfo(*state.currentState, *state.previousState, scheme, state.Limit) } diff --git a/pkg/state/appender.go b/pkg/state/appender.go index ec7992d9e..a47e3155d 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -885,14 +885,14 @@ func (a *txAppender) updateBlockchainUpdateInfo(blockInfo *proto.BlockInfo, bloc blockID := blockHeader.BlockID() bUpdatesInfo := blockchaininfo.BUpdatesInfo{ BlockUpdatesInfo: blockchaininfo.BlockUpdatesInfo{ - Height: &blockInfo.Height, - VRF: &blockInfo.VRF, - BlockID: &blockID, - BlockHeader: blockHeader, + Height: blockInfo.Height, + VRF: blockInfo.VRF, + BlockID: blockID, + BlockHeader: *blockHeader, }, ContractUpdatesInfo: blockchaininfo.L2ContractDataEntries{ - AllDataEntries: &dataEntries, - Height: &blockInfo.Height, + AllDataEntries: dataEntries, + Height: blockInfo.Height, }, } a.bUpdatesExtension.BUpdatesChannel <- bUpdatesInfo diff --git a/pkg/state/invoke_applier_test.go b/pkg/state/invoke_applier_test.go index 63ce55c4a..2fd0c1e64 100644 --- a/pkg/state/invoke_applier_test.go +++ b/pkg/state/invoke_applier_test.go @@ -35,7 +35,8 @@ type invokeApplierTestObjects struct { } func createInvokeApplierTestObjects(t *testing.T) *invokeApplierTestObjects { - state, err := newStateManager(t.TempDir(), true, DefaultTestingStateParams(), settings.MustMainNetSettings(), false, nil) + state, err := newStateManager(t.TempDir(), true, DefaultTestingStateParams(), + settings.MustMainNetSettings(), false, nil) assert.NoError(t, err, "newStateManager() failed") to := &invokeApplierTestObjects{state} randGenesisBlockID := genRandBlockId(t) From 860b8308cb6af1324606087292e8adf9068a98c9 Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 23 Oct 2024 23:03:19 -0500 Subject: [PATCH 26/50] fixed gosec issues --- cmd/blockchaininfo/nats_subscriber.go | 2 +- pkg/blockchaininfo/blockchaininfo.go | 2 +- pkg/proto/block.go | 36 ++++++++++++++++++++++----- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/cmd/blockchaininfo/nats_subscriber.go b/cmd/blockchaininfo/nats_subscriber.go index 106f5e34a..639bf0f72 100644 --- a/cmd/blockchaininfo/nats_subscriber.go +++ b/cmd/blockchaininfo/nats_subscriber.go @@ -43,7 +43,7 @@ func printContractInfo(contractInfoProto *g.L2ContractDataEntries, scheme proto. log.Println("Error converting to pretty JSON:", err) return err } - heightStr := strconv.Itoa(int(contractInfoProto.Height)) + heightStr := strconv.FormatUint(contractInfoProto.Height, 10) // Write the pretty JSON to a file err = os.WriteFile(path+heightStr+".json", prettyJSON, 0600) if err != nil { diff --git a/pkg/blockchaininfo/blockchaininfo.go b/pkg/blockchaininfo/blockchaininfo.go index 9614c1e54..8de194bb9 100644 --- a/pkg/blockchaininfo/blockchaininfo.go +++ b/pkg/blockchaininfo/blockchaininfo.go @@ -70,7 +70,7 @@ func filterDataEntries(beforeHeight uint64, dataEntries []proto.DataEntry) ([]pr epoch := extractEpochFromBlockMeta(binaryEntry.Value) // Compare height with beforeHeight. - if epoch > int64(beforeHeight) { + if uint64(epoch) > beforeHeight { // Add to filtered list if height is less than beforeHeight. filteredDataEntries = append(filteredDataEntries, entry) } diff --git a/pkg/proto/block.go b/pkg/proto/block.go index 6c71c41c1..56425ad58 100644 --- a/pkg/proto/block.go +++ b/pkg/proto/block.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "io" + "math" "github.com/jinzhu/copier" "github.com/mr-tron/base58/base58" @@ -517,11 +518,18 @@ func ProtobufHeaderToBlockHeader(ph *g.Block_Header) (*BlockHeader, error) { if err != nil { return nil, err } + if ph.Timestamp < 0 { + return nil, errors.Errorf("invalid timestamp: negative value %d", ph.Timestamp) + } + features, err := uint32SliceToInt16(ph.FeatureVotes) + if err != nil { + return nil, errors.Errorf("failed to convert uint32 slice of feature votes to int16, %v", err) + } blockHeader := &BlockHeader{ Version: BlockVersion(ph.Version), Timestamp: uint64(ph.Timestamp), Parent: parentBlockID, - Features: uint32SliceToInt16(ph.FeatureVotes), + Features: features, RewardVote: ph.RewardVote, GeneratorPublicKey: generatorPK, TransactionsRoot: B58Bytes(ph.TransactionsRoot), @@ -531,12 +539,15 @@ func ProtobufHeaderToBlockHeader(ph *g.Block_Header) (*BlockHeader, error) { return blockHeader, nil } -func uint32SliceToInt16(s []uint32) []int16 { +func uint32SliceToInt16(s []uint32) ([]int16, error) { var res []int16 for _, v := range s { + if v > math.MaxInt16 { // Check for overflow + return nil, fmt.Errorf("value %d exceeds int16 range", v) + } res = append(res, int16(v)) } - return res + return res, nil } func FromProtobufChallengedHeader(pb *g.Block_Header_ChallengedHeader) (*ChallengedHeader, error) { @@ -555,12 +566,22 @@ func FromProtobufChallengedHeader(pb *g.Block_Header_ChallengedHeader) (*Challen if err != nil { return nil, err } + if pb.BaseTarget < 0 { + return nil, errors.Errorf("invalid basetarget: negative value %d", pb.BaseTarget) + } + if pb.Timestamp < 0 { + return nil, errors.Errorf("invalid timestamp: negative value %d", pb.Timestamp) + } + features, err := int16SliceFromUint32(pb.FeatureVotes) + if err != nil { + return nil, errors.Errorf("failed to convert int16 slice of feature votes to uint32, %v", err) + } return &ChallengedHeader{ NxtConsensus: NxtConsensus{ BaseTarget: uint64(pb.BaseTarget), GenSignature: pb.GenerationSignature, }, - Features: int16SliceFromUint32(pb.FeatureVotes), + Features: features, Timestamp: uint64(pb.Timestamp), GeneratorPublicKey: genPublicKey, RewardVote: pb.RewardVote, @@ -569,12 +590,15 @@ func FromProtobufChallengedHeader(pb *g.Block_Header_ChallengedHeader) (*Challen }, nil } -func int16SliceFromUint32(data []uint32) []int16 { +func int16SliceFromUint32(data []uint32) ([]int16, error) { result := make([]int16, len(data)) for i, v := range data { + if v > math.MaxInt16 { // Check for overflow + return nil, fmt.Errorf("value %d exceeds int16 range", v) + } result[i] = int16(v) } - return result + return result, nil } func AppendHeaderBytesToTransactions(headerBytes, transactions []byte) ([]byte, error) { From ec15106e9ccaf2f10694f4799860f5de6de72817 Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 23 Oct 2024 23:16:14 -0500 Subject: [PATCH 27/50] fixed one more gosec issue --- pkg/blockchaininfo/blockchaininfo.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/blockchaininfo/blockchaininfo.go b/pkg/blockchaininfo/blockchaininfo.go index 8de194bb9..e73128d11 100644 --- a/pkg/blockchaininfo/blockchaininfo.go +++ b/pkg/blockchaininfo/blockchaininfo.go @@ -69,6 +69,9 @@ func filterDataEntries(beforeHeight uint64, dataEntries []proto.DataEntry) ([]pr } epoch := extractEpochFromBlockMeta(binaryEntry.Value) + if epoch < 0 { + return nil, errors.New("epoch is less than 0") + } // Compare height with beforeHeight. if uint64(epoch) > beforeHeight { // Add to filtered list if height is less than beforeHeight. From 8f70624b619ae50140c4a6edb6bf2d041a673f2b Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Thu, 7 Nov 2024 01:48:33 +0300 Subject: [PATCH 28/50] Mod clean. --- go.mod | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 93d9c721a..afeed2fc4 100644 --- a/go.mod +++ b/go.mod @@ -85,8 +85,8 @@ require ( github.com/ingonyama-zk/iciclegnark v0.1.0 // indirect github.com/klauspost/compress v1.17.9 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/minio/highwayhash v1.0.2 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/minio/highwayhash v1.0.2 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/term v0.5.0 // indirect @@ -114,9 +114,9 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.29.0 // indirect - golang.org/x/time v0.5.0 // indirect golang.org/x/term v0.25.0 // indirect golang.org/x/text v0.19.0 // indirect + golang.org/x/time v0.5.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect From 02f82ef663711ee4e0baaa68bce392d8e46e3315 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Thu, 7 Nov 2024 02:16:34 +0300 Subject: [PATCH 29/50] Fix lint for 'runNode' function. --- cmd/node/node.go | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/cmd/node/node.go b/cmd/node/node.go index 073dfd7dd..0656c0946 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -402,22 +402,11 @@ func runNode(ctx context.Context, nc *config) (_ io.Closer, retErr error) { var bUpdatesExtension *state.BlockchainUpdatesExtension if nc.enableBlockchainUpdatesPlugin { - updatesChannel := make(chan blockchaininfo.BUpdatesInfo) - bUpdatesExtensionState := blockchaininfo.NewBUpdatesExtensionState(blockchaininfo.StoreBlocksLimit, - cfg.AddressSchemeCharacter) - - l2address, cnvrtErr := proto.NewAddressFromString("3Msx4Aq69zWUKy4d1wyKnQ4ofzEDAfv5Ngf") - if cnvrtErr != nil { - zap.S().Errorf("Failed to initialize L2 contract address") - return + var bUErr error + bUpdatesExtension, bUErr = runBlockchainUpdatesPlugin(ctx, cfg) + if bUErr != nil { + return nil, errors.Wrap(bUErr, "failed to run blockchain updates plugin") } - bUpdatesExtension = &state.BlockchainUpdatesExtension{ - EnableBlockchainUpdatesPlugin: true, - BUpdatesChannel: updatesChannel, - L2ContractAddress: l2address, - } - - go bUpdatesExtensionState.RunBlockchainUpdatesPublisher(ctx, updatesChannel, cfg.AddressSchemeCharacter) } // Send updatesChannel into BlockchainSettings. Write updates into this channel @@ -816,6 +805,32 @@ func runAPIs( return nil } +func runBlockchainUpdatesPlugin( + ctx context.Context, + cfg *settings.BlockchainSettings, +) (*state.BlockchainUpdatesExtension, error) { + const l2ContractAddr = "3Msx4Aq69zWUKy4d1wyKnQ4ofzEDAfv5Ngf" + + l2address, cnvrtErr := proto.NewAddressFromString(l2ContractAddr) + if cnvrtErr != nil { + return nil, errors.Wrapf(cnvrtErr, "failed to convert L2 contract address %q", l2ContractAddr) + } + + bUpdatesExtensionState := blockchaininfo.NewBUpdatesExtensionState( + blockchaininfo.StoreBlocksLimit, + cfg.AddressSchemeCharacter, + ) + + updatesChannel := make(chan blockchaininfo.BUpdatesInfo) + go bUpdatesExtensionState.RunBlockchainUpdatesPublisher(ctx, updatesChannel, cfg.AddressSchemeCharacter) + + return &state.BlockchainUpdatesExtension{ + EnableBlockchainUpdatesPlugin: true, + BUpdatesChannel: updatesChannel, + L2ContractAddress: l2address, + }, nil +} + func FromArgs(scheme proto.Scheme, c *config) func(s *settings.NodeSettings) error { return func(s *settings.NodeSettings) error { s.DeclaredAddr = c.declAddr From bb3bd64372a043649b05d5547411c8d7ca77afc7 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Thu, 7 Nov 2024 02:20:25 +0300 Subject: [PATCH 30/50] Fix gosec issues. --- pkg/proto/block.go | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/pkg/proto/block.go b/pkg/proto/block.go index 56425ad58..543ee773d 100644 --- a/pkg/proto/block.go +++ b/pkg/proto/block.go @@ -518,8 +518,9 @@ func ProtobufHeaderToBlockHeader(ph *g.Block_Header) (*BlockHeader, error) { if err != nil { return nil, err } - if ph.Timestamp < 0 { - return nil, errors.Errorf("invalid timestamp: negative value %d", ph.Timestamp) + ts := ph.Timestamp + if ts < 0 { + return nil, errors.Errorf("invalid timestamp: negative value %d", ts) } features, err := uint32SliceToInt16(ph.FeatureVotes) if err != nil { @@ -527,7 +528,7 @@ func ProtobufHeaderToBlockHeader(ph *g.Block_Header) (*BlockHeader, error) { } blockHeader := &BlockHeader{ Version: BlockVersion(ph.Version), - Timestamp: uint64(ph.Timestamp), + Timestamp: uint64(ts), Parent: parentBlockID, Features: features, RewardVote: ph.RewardVote, @@ -566,11 +567,13 @@ func FromProtobufChallengedHeader(pb *g.Block_Header_ChallengedHeader) (*Challen if err != nil { return nil, err } - if pb.BaseTarget < 0 { - return nil, errors.Errorf("invalid basetarget: negative value %d", pb.BaseTarget) + bt := pb.BaseTarget + if bt < 0 { + return nil, errors.Errorf("invalid basetarget: negative value %d", bt) } - if pb.Timestamp < 0 { - return nil, errors.Errorf("invalid timestamp: negative value %d", pb.Timestamp) + ts := pb.Timestamp + if ts < 0 { + return nil, errors.Errorf("invalid timestamp: negative value %d", ts) } features, err := int16SliceFromUint32(pb.FeatureVotes) if err != nil { @@ -578,11 +581,11 @@ func FromProtobufChallengedHeader(pb *g.Block_Header_ChallengedHeader) (*Challen } return &ChallengedHeader{ NxtConsensus: NxtConsensus{ - BaseTarget: uint64(pb.BaseTarget), + BaseTarget: uint64(bt), GenSignature: pb.GenerationSignature, }, Features: features, - Timestamp: uint64(pb.Timestamp), + Timestamp: uint64(ts), GeneratorPublicKey: genPublicKey, RewardVote: pb.RewardVote, StateHash: stateHash, From 47320cf120ea9efaa6ab636dbd430b8713fe4681 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Thu, 7 Nov 2024 04:26:26 +0300 Subject: [PATCH 31/50] Deleted stale go protobuf generated code. --- .../waves/bupdates/blockchain_updates.pb.go | 198 ------------------ 1 file changed, 198 deletions(-) delete mode 100644 github.com/wavesplatform/gowaves/pkg/grpc/generated/waves/bupdates/blockchain_updates.pb.go diff --git a/github.com/wavesplatform/gowaves/pkg/grpc/generated/waves/bupdates/blockchain_updates.pb.go b/github.com/wavesplatform/gowaves/pkg/grpc/generated/waves/bupdates/blockchain_updates.pb.go deleted file mode 100644 index fe60e44f1..000000000 --- a/github.com/wavesplatform/gowaves/pkg/grpc/generated/waves/bupdates/blockchain_updates.pb.go +++ /dev/null @@ -1,198 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.12.4 -// source: waves/bupdates/blockchain_updates.proto - -package bupdates - -import ( - waves "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type BUpdates struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Height uint64 `protobuf:"varint,1,opt,name=Height,proto3" json:"Height,omitempty"` - VRF []byte `protobuf:"bytes,2,opt,name=VRF,proto3" json:"VRF,omitempty"` - BlockID []byte `protobuf:"bytes,3,opt,name=BlockID,proto3" json:"BlockID,omitempty"` - BlockHeader *waves.Block_Header `protobuf:"bytes,4,opt,name=BlockHeader,proto3" json:"BlockHeader,omitempty"` - DataEntries []*waves.DataEntry `protobuf:"bytes,5,rep,name=DataEntries,proto3" json:"DataEntries,omitempty"` -} - -func (x *BUpdates) Reset() { - *x = BUpdates{} - if protoimpl.UnsafeEnabled { - mi := &file_waves_bupdates_blockchain_updates_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BUpdates) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BUpdates) ProtoMessage() {} - -func (x *BUpdates) ProtoReflect() protoreflect.Message { - mi := &file_waves_bupdates_blockchain_updates_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BUpdates.ProtoReflect.Descriptor instead. -func (*BUpdates) Descriptor() ([]byte, []int) { - return file_waves_bupdates_blockchain_updates_proto_rawDescGZIP(), []int{0} -} - -func (x *BUpdates) GetHeight() uint64 { - if x != nil { - return x.Height - } - return 0 -} - -func (x *BUpdates) GetVRF() []byte { - if x != nil { - return x.VRF - } - return nil -} - -func (x *BUpdates) GetBlockID() []byte { - if x != nil { - return x.BlockID - } - return nil -} - -func (x *BUpdates) GetBlockHeader() *waves.Block_Header { - if x != nil { - return x.BlockHeader - } - return nil -} - -func (x *BUpdates) GetDataEntries() []*waves.DataEntry { - if x != nil { - return x.DataEntries - } - return nil -} - -var File_waves_bupdates_blockchain_updates_proto protoreflect.FileDescriptor - -var file_waves_bupdates_blockchain_updates_proto_rawDesc = []byte{ - 0x0a, 0x27, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x62, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, - 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x75, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x77, 0x61, 0x76, 0x65, 0x73, - 0x1a, 0x17, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x11, 0x77, 0x61, 0x76, 0x65, 0x73, - 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb9, 0x01, 0x0a, - 0x08, 0x42, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x48, 0x65, 0x69, - 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x48, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x12, 0x10, 0x0a, 0x03, 0x56, 0x52, 0x46, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, - 0x56, 0x52, 0x46, 0x12, 0x18, 0x0a, 0x07, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x12, 0x35, 0x0a, - 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, - 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x77, 0x61, 0x76, 0x65, - 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x44, 0x61, 0x74, - 0x61, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x42, 0x68, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, - 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, - 0x2f, 0x67, 0x6f, 0x77, 0x61, 0x76, 0x65, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67, 0x72, 0x70, - 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x77, 0x61, 0x76, 0x65, - 0x73, 0x2f, 0x62, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0xaa, 0x02, 0x05, 0x57, 0x61, 0x76, - 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_waves_bupdates_blockchain_updates_proto_rawDescOnce sync.Once - file_waves_bupdates_blockchain_updates_proto_rawDescData = file_waves_bupdates_blockchain_updates_proto_rawDesc -) - -func file_waves_bupdates_blockchain_updates_proto_rawDescGZIP() []byte { - file_waves_bupdates_blockchain_updates_proto_rawDescOnce.Do(func() { - file_waves_bupdates_blockchain_updates_proto_rawDescData = protoimpl.X.CompressGZIP(file_waves_bupdates_blockchain_updates_proto_rawDescData) - }) - return file_waves_bupdates_blockchain_updates_proto_rawDescData -} - -var file_waves_bupdates_blockchain_updates_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_waves_bupdates_blockchain_updates_proto_goTypes = []interface{}{ - (*BUpdates)(nil), // 0: waves.BUpdates - (*waves.Block_Header)(nil), // 1: waves.Block.Header - (*waves.DataEntry)(nil), // 2: waves.DataEntry -} -var file_waves_bupdates_blockchain_updates_proto_depIdxs = []int32{ - 1, // 0: waves.BUpdates.BlockHeader:type_name -> waves.Block.Header - 2, // 1: waves.BUpdates.DataEntries:type_name -> waves.DataEntry - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name -} - -func init() { file_waves_bupdates_blockchain_updates_proto_init() } -func file_waves_bupdates_blockchain_updates_proto_init() { - if File_waves_bupdates_blockchain_updates_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_waves_bupdates_blockchain_updates_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BUpdates); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_waves_bupdates_blockchain_updates_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_waves_bupdates_blockchain_updates_proto_goTypes, - DependencyIndexes: file_waves_bupdates_blockchain_updates_proto_depIdxs, - MessageInfos: file_waves_bupdates_blockchain_updates_proto_msgTypes, - }.Build() - File_waves_bupdates_blockchain_updates_proto = out.File - file_waves_bupdates_blockchain_updates_proto_rawDesc = nil - file_waves_bupdates_blockchain_updates_proto_goTypes = nil - file_waves_bupdates_blockchain_updates_proto_depIdxs = nil -} From fb56f6bfa345524d48ec22f02d6470adbd5c0043 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Thu, 7 Nov 2024 04:31:55 +0300 Subject: [PATCH 32/50] Make some types and functions package private. --- pkg/proto/types.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pkg/proto/types.go b/pkg/proto/types.go index 7c52dbfae..b82ff90d8 100644 --- a/pkg/proto/types.go +++ b/pkg/proto/types.go @@ -3123,12 +3123,12 @@ func (e *DeleteDataEntry) UnmarshalJSON(value []byte) error { return nil } -// DataEntryType is the assistive structure used to get the type of DataEntry while unmarshal form JSON. -type DataEntryType struct { +// dataEntryType is the assistive structure used to get the type of DataEntry while unmarshal form JSON. +type dataEntryType struct { Type string `json:"type"` } -func GuessDataEntryType(dataEntryType DataEntryType) (DataEntry, error) { +func guessDataEntryType(dataEntryType dataEntryType) (DataEntry, error) { var r DataEntry switch dataEntryType.Type { case "integer": @@ -3151,11 +3151,11 @@ func GuessDataEntryType(dataEntryType DataEntryType) (DataEntry, error) { func NewDataEntryFromJSON(data []byte) (DataEntry, error) { wrapError := func(err error) error { return errors.Wrap(err, "failed to unmarshal DataEntry from JSON") } - var et DataEntryType + var et dataEntryType if err := json.Unmarshal(data, &et); err != nil { return nil, wrapError(err) } - entry, err := GuessDataEntryType(et) + entry, err := guessDataEntryType(et) if err != nil { return nil, wrapError(err) } @@ -3212,7 +3212,7 @@ func (e DataEntries) Valid(forbidEmptyKey, utf16KeyLen bool) error { func (e *DataEntries) UnmarshalJSON(data []byte) error { wrapError := func(err error) error { return errors.Wrap(err, "failed to unmarshal DataEntries from JSON") } - var ets []DataEntryType + var ets []dataEntryType err := json.Unmarshal(data, &ets) if err != nil { return wrapError(err) @@ -3220,7 +3220,7 @@ func (e *DataEntries) UnmarshalJSON(data []byte) error { entries := make([]DataEntry, len(ets)) for i, row := range ets { - et, guessErr := GuessDataEntryType(row) + et, guessErr := guessDataEntryType(row) if guessErr != nil { return wrapError(guessErr) } From 89ffaf25028dd8490029991219d7ae07321495ff Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Thu, 7 Nov 2024 04:39:33 +0300 Subject: [PATCH 33/50] Update 'go.mod' go version. --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index afeed2fc4..c015b76e3 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/wavesplatform/gowaves -go 1.22.0 +go 1.22 require ( filippo.io/edwards25519 v1.1.0 From 28086dca6c0feed323527f3faf42efba615d7091 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Thu, 7 Nov 2024 04:49:17 +0300 Subject: [PATCH 34/50] Change location of 'blockchaininfo_test.go'. --- .../{blockchaininfo_test => }/blockchaininfo_test.go | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pkg/blockchaininfo/{blockchaininfo_test => }/blockchaininfo_test.go (100%) diff --git a/pkg/blockchaininfo/blockchaininfo_test/blockchaininfo_test.go b/pkg/blockchaininfo/blockchaininfo_test.go similarity index 100% rename from pkg/blockchaininfo/blockchaininfo_test/blockchaininfo_test.go rename to pkg/blockchaininfo/blockchaininfo_test.go From 2f8c3c0973840d43d266aac05d671921836bf1e1 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Thu, 7 Nov 2024 06:48:54 +0300 Subject: [PATCH 35/50] Add new method 'PartialBlockHeader' for 'ProtobufConverter'. --- pkg/proto/protobuf_converters.go | 61 ++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/pkg/proto/protobuf_converters.go b/pkg/proto/protobuf_converters.go index d00f7ae8a..385abf746 100644 --- a/pkg/proto/protobuf_converters.go +++ b/pkg/proto/protobuf_converters.go @@ -1752,43 +1752,66 @@ func (c *ProtobufConverter) stateHash(stateHashBytes []byte) *crypto.Digest { return &sh } -func (c *ProtobufConverter) BlockHeader(block *g.Block) (BlockHeader, error) { - if block == nil { - return BlockHeader{}, errors.New("empty block") - } - if block.Header == nil { +// PartialBlockHeader converts protobuf block header to domain block header. +// Some fields can't be set in this conversion because the information is not available in the protobuf message. +// The following fields are not set: +// +// - BlockHeader.BlockSignature - the field is not set because it requires the whole block message; +// +// - BlockHeader.TransactionCount - the field is not set because it requires the whole block message; +// +// - BlockHeader.ID - the field is not set because it requires the scheme and filled block signature field. +func (c *ProtobufConverter) PartialBlockHeader(pbHeader *g.Block_Header) (BlockHeader, error) { + if pbHeader == nil { return BlockHeader{}, errors.New("empty block header") } - features := c.features(block.Header.FeatureVotes) - consensus := c.consensus(block.Header) - v := BlockVersion(c.byte(block.Header.Version)) + features := c.features(pbHeader.FeatureVotes) + consensus := c.consensus(pbHeader) + v := BlockVersion(c.byte(pbHeader.Version)) header := BlockHeader{ Version: v, - Timestamp: c.uint64(block.Header.Timestamp), - Parent: c.blockID(block.Header.Reference), + Timestamp: c.uint64(pbHeader.Timestamp), + Parent: c.blockID(pbHeader.Reference), FeaturesCount: len(features), Features: features, - RewardVote: block.Header.RewardVote, + RewardVote: pbHeader.RewardVote, ConsensusBlockLength: uint32(consensus.BinarySize()), NxtConsensus: consensus, - TransactionCount: len(block.Transactions), - GeneratorPublicKey: c.publicKey(block.Header.Generator), - BlockSignature: c.signature(block.Signature), - TransactionsRoot: block.Header.TransactionsRoot, - StateHash: c.stateHash(block.Header.StateHash), - ChallengedHeader: c.challengedHeader(block.Header.ChallengedHeader), + TransactionCount: 0, // not set, can't be set without g.Block structure + GeneratorPublicKey: c.publicKey(pbHeader.Generator), + BlockSignature: crypto.Signature{}, // not set, can't be set without g.Block structure + TransactionsRoot: pbHeader.TransactionsRoot, + StateHash: c.stateHash(pbHeader.StateHash), + ChallengedHeader: c.challengedHeader(pbHeader.ChallengedHeader), + ID: BlockID{}, // not set, can't be calculated without the scheme and the block signature } if c.err != nil { err := c.err c.reset() return BlockHeader{}, err } + return header, nil +} + +func (c *ProtobufConverter) BlockHeader(block *g.Block) (BlockHeader, error) { + if block == nil { + return BlockHeader{}, errors.New("empty block") + } + if block.Header == nil { + return BlockHeader{}, errors.New("empty block header") + } + header, err := c.PartialBlockHeader(block.Header) + if err != nil { + return BlockHeader{}, err + } + header.TransactionCount = len(block.Transactions) // set tx count from whole block message + header.BlockSignature = c.signature(block.Signature) // set block signature from whole block message scheme := c.byte(block.Header.ChainId) if scheme == 0 { scheme = c.FallbackChainID } - if err := header.GenerateBlockID(scheme); err != nil { - return BlockHeader{}, err + if gbErr := header.GenerateBlockID(scheme); gbErr != nil { // generate block ID after setting all fields + return BlockHeader{}, gbErr } return header, nil } From 5f1010c5eee966d3e0bf44de8d5452f9e8a96748 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Thu, 7 Nov 2024 06:49:41 +0300 Subject: [PATCH 36/50] Refactor 'BUpdatesInfoFromProto' function with unused functions removal. --- pkg/blockchaininfo/proto_converters.go | 15 +++- pkg/proto/block.go | 116 ------------------------- 2 files changed, 11 insertions(+), 120 deletions(-) diff --git a/pkg/blockchaininfo/proto_converters.go b/pkg/blockchaininfo/proto_converters.go index b43266780..058ddf20e 100644 --- a/pkg/blockchaininfo/proto_converters.go +++ b/pkg/blockchaininfo/proto_converters.go @@ -1,6 +1,8 @@ package blockchaininfo import ( + "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/grpc/generated/waves" g "github.com/wavesplatform/gowaves/pkg/grpc/l2/blockchain_info" "github.com/wavesplatform/gowaves/pkg/proto" @@ -25,20 +27,25 @@ func BUpdatesInfoToProto(blockInfo BUpdatesInfo, scheme proto.Scheme) (*g.BlockI } func BUpdatesInfoFromProto(blockInfoProto *g.BlockInfo) (BlockUpdatesInfo, error) { + if blockInfoProto == nil { + return BlockUpdatesInfo{}, errors.New("empty block info") + } blockID, err := proto.NewBlockIDFromBytes(blockInfoProto.BlockID) if err != nil { - return BlockUpdatesInfo{}, err + return BlockUpdatesInfo{}, errors.Wrap(err, "failed to convert block ID") } - blockHeader, err := proto.ProtobufHeaderToBlockHeader(blockInfoProto.BlockHeader) + var c proto.ProtobufConverter + blockHeader, err := c.PartialBlockHeader(blockInfoProto.BlockHeader) if err != nil { - return BlockUpdatesInfo{}, err + return BlockUpdatesInfo{}, errors.Wrap(err, "failed to convert block header") } + blockHeader.ID = blockID // Set block ID to the one from the protobuf. vrf := proto.B58Bytes(blockInfoProto.VRF) return BlockUpdatesInfo{ Height: blockInfoProto.Height, VRF: vrf, BlockID: blockID, - BlockHeader: *blockHeader, + BlockHeader: blockHeader, }, nil } diff --git a/pkg/proto/block.go b/pkg/proto/block.go index 543ee773d..9578e996e 100644 --- a/pkg/proto/block.go +++ b/pkg/proto/block.go @@ -4,9 +4,7 @@ import ( "bytes" "encoding/binary" "encoding/json" - "fmt" "io" - "math" "github.com/jinzhu/copier" "github.com/mr-tron/base58/base58" @@ -490,120 +488,6 @@ func (b *BlockHeader) UnmarshalHeaderFromBinary(data []byte, scheme Scheme) (err return nil } -func ProtobufHeaderToBlockHeader(ph *g.Block_Header) (*BlockHeader, error) { - if ph == nil { - return nil, errors.New("input protobuf header is nil") - } - var challengedHeader *ChallengedHeader - if ph.ChallengedHeader != nil { - ch, err := FromProtobufChallengedHeader(ph.ChallengedHeader) - if err != nil { - return nil, err - } - challengedHeader = ch - } - var stateHash *crypto.Digest - if len(ph.StateHash) > 0 { - sh, err := crypto.NewDigestFromBytes(ph.StateHash) - if err != nil { - return nil, err - } - stateHash = &sh - } - parentBlockID, err := NewBlockIDFromBytes(ph.Reference) - if err != nil { - return nil, err - } - generatorPK, err := crypto.NewPublicKeyFromBytes(ph.Generator) - if err != nil { - return nil, err - } - ts := ph.Timestamp - if ts < 0 { - return nil, errors.Errorf("invalid timestamp: negative value %d", ts) - } - features, err := uint32SliceToInt16(ph.FeatureVotes) - if err != nil { - return nil, errors.Errorf("failed to convert uint32 slice of feature votes to int16, %v", err) - } - blockHeader := &BlockHeader{ - Version: BlockVersion(ph.Version), - Timestamp: uint64(ts), - Parent: parentBlockID, - Features: features, - RewardVote: ph.RewardVote, - GeneratorPublicKey: generatorPK, - TransactionsRoot: B58Bytes(ph.TransactionsRoot), - StateHash: stateHash, - ChallengedHeader: challengedHeader, - } - return blockHeader, nil -} - -func uint32SliceToInt16(s []uint32) ([]int16, error) { - var res []int16 - for _, v := range s { - if v > math.MaxInt16 { // Check for overflow - return nil, fmt.Errorf("value %d exceeds int16 range", v) - } - res = append(res, int16(v)) - } - return res, nil -} - -func FromProtobufChallengedHeader(pb *g.Block_Header_ChallengedHeader) (*ChallengedHeader, error) { - if pb == nil { - return nil, fmt.Errorf("input protobuf object is nil") - } - headerSig, err := crypto.NewSignatureFromBytes(pb.HeaderSignature) - if err != nil { - return nil, err - } - genPublicKey, err := crypto.NewPublicKeyFromBytes(pb.Generator) - if err != nil { - return nil, err - } - stateHash, err := crypto.NewDigestFromBytes(pb.StateHash) - if err != nil { - return nil, err - } - bt := pb.BaseTarget - if bt < 0 { - return nil, errors.Errorf("invalid basetarget: negative value %d", bt) - } - ts := pb.Timestamp - if ts < 0 { - return nil, errors.Errorf("invalid timestamp: negative value %d", ts) - } - features, err := int16SliceFromUint32(pb.FeatureVotes) - if err != nil { - return nil, errors.Errorf("failed to convert int16 slice of feature votes to uint32, %v", err) - } - return &ChallengedHeader{ - NxtConsensus: NxtConsensus{ - BaseTarget: uint64(bt), - GenSignature: pb.GenerationSignature, - }, - Features: features, - Timestamp: uint64(ts), - GeneratorPublicKey: genPublicKey, - RewardVote: pb.RewardVote, - StateHash: stateHash, - BlockSignature: headerSig, - }, nil -} - -func int16SliceFromUint32(data []uint32) ([]int16, error) { - result := make([]int16, len(data)) - for i, v := range data { - if v > math.MaxInt16 { // Check for overflow - return nil, fmt.Errorf("value %d exceeds int16 range", v) - } - result[i] = int16(v) - } - return result, nil -} - func AppendHeaderBytesToTransactions(headerBytes, transactions []byte) ([]byte, error) { headerLen := len(headerBytes) if headerLen < 1 { From 7dc0748c1987793f265166e9519d43f480c83640 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Thu, 7 Nov 2024 07:13:57 +0300 Subject: [PATCH 37/50] Refactored a bit 'L2ContractDataEntriesFromProto'. --- pkg/blockchaininfo/proto_converters.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pkg/blockchaininfo/proto_converters.go b/pkg/blockchaininfo/proto_converters.go index 058ddf20e..728b84042 100644 --- a/pkg/blockchaininfo/proto_converters.go +++ b/pkg/blockchaininfo/proto_converters.go @@ -61,14 +61,19 @@ func L2ContractDataEntriesToProto(contractData L2ContractDataEntries) *g.L2Contr } } -func L2ContractDataEntriesFromProto(protoDataEntries *g.L2ContractDataEntries, - scheme proto.Scheme) (L2ContractDataEntries, error) { +func L2ContractDataEntriesFromProto( + protoDataEntries *g.L2ContractDataEntries, + scheme proto.Scheme, +) (L2ContractDataEntries, error) { + if protoDataEntries == nil { + return L2ContractDataEntries{}, errors.New("empty contract data") + } converter := proto.ProtobufConverter{FallbackChainID: scheme} - var dataEntries []proto.DataEntry + dataEntries := make([]proto.DataEntry, 0, len(protoDataEntries.DataEntries)) for _, protoEntry := range protoDataEntries.DataEntries { entry, err := converter.Entry(protoEntry) if err != nil { - return L2ContractDataEntries{}, err + return L2ContractDataEntries{}, errors.Wrap(err, "failed to convert data entry") } dataEntries = append(dataEntries, entry) } From 3f9bb83a9eba45e8599e88bd9565f6790e6f3d3a Mon Sep 17 00:00:00 2001 From: esuwu Date: Tue, 12 Nov 2024 00:04:18 -0600 Subject: [PATCH 38/50] Added a parse function --- cmd/blockchaininfo/nats_subscriber.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/blockchaininfo/nats_subscriber.go b/cmd/blockchaininfo/nats_subscriber.go index 639bf0f72..a5d13a70a 100644 --- a/cmd/blockchaininfo/nats_subscriber.go +++ b/cmd/blockchaininfo/nats_subscriber.go @@ -38,6 +38,7 @@ func printContractInfo(contractInfoProto *g.L2ContractDataEntries, scheme proto. if err != nil { return err } + // Delete data entries are not going to have "type" prettyJSON, err := json.MarshalIndent(contractInfo, "", " ") if err != nil { log.Println("Error converting to pretty JSON:", err) @@ -132,6 +133,8 @@ func main() { flag.StringVar(&updatesPath, "updates-path", "", "File path to store contract updates") flag.StringVar(&natsURL, "nats-url", nats.DefaultURL, "URL for the NATS server") + flag.Parse() + scheme, err := schemeFromString(blockchainType) if err != nil { zap.S().Fatalf("Failed to parse the blockchain type: %v", err) From cf23bdf9d31533d0a6e6e4ee9d0b8adc10e99b0c Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Mon, 18 Nov 2024 12:42:41 +0300 Subject: [PATCH 39/50] Set 'NoSigs' option for nats sever to true. --- pkg/blockchaininfo/nats_publisher.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/blockchaininfo/nats_publisher.go b/pkg/blockchaininfo/nats_publisher.go index 84956eac4..42e053915 100644 --- a/pkg/blockchaininfo/nats_publisher.go +++ b/pkg/blockchaininfo/nats_publisher.go @@ -7,6 +7,7 @@ import ( "github.com/nats-io/nats-server/v2/server" "github.com/nats-io/nats.go" + "github.com/wavesplatform/gowaves/pkg/proto" ) @@ -214,6 +215,7 @@ func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(ctx context.Cont MaxPayload: NatsMaxPayloadSize, Host: HostDefault, Port: PortDefault, + NoSigs: true, } s, err := server.NewServer(opts) if err != nil { From d7dcd5ea7af7b637fccd42cd5ca7b2c80f0c4479 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Mon, 18 Nov 2024 12:43:22 +0300 Subject: [PATCH 40/50] Fix 'runPublisher' in case when updates channel is closed. --- pkg/blockchaininfo/nats_publisher.go | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/pkg/blockchaininfo/nats_publisher.go b/pkg/blockchaininfo/nats_publisher.go index 42e053915..205703492 100644 --- a/pkg/blockchaininfo/nats_publisher.go +++ b/pkg/blockchaininfo/nats_publisher.go @@ -153,12 +153,7 @@ func (bu *BUpdatesExtensionState) publishUpdates(updates BUpdatesInfo, nc *nats. return nil } -func handleBlockchainUpdates(updates BUpdatesInfo, ok bool, - bu *BUpdatesExtensionState, scheme proto.Scheme, nc *nats.Conn) { - if !ok { - log.Printf("the updates channel for publisher was closed") - return - } +func handleBlockchainUpdate(updates BUpdatesInfo, bu *BUpdatesExtensionState, scheme proto.Scheme, nc *nats.Conn) { // update current state bu.currentState = &updates if bu.previousState == nil { @@ -197,16 +192,18 @@ func handleBlockchainUpdates(updates BUpdatesInfo, ok bool, func runPublisher(ctx context.Context, updatesChannel <-chan BUpdatesInfo, bu *BUpdatesExtensionState, scheme proto.Scheme, nc *nats.Conn) { - func(ctx context.Context, updatesChannel <-chan BUpdatesInfo) { - for { - select { - case updates, ok := <-updatesChannel: - handleBlockchainUpdates(updates, ok, bu, scheme, nc) - case <-ctx.Done(): + for { + select { + case updates, ok := <-updatesChannel: + if !ok { + log.Printf("the updates channel for publisher was closed") return } + handleBlockchainUpdate(updates, bu, scheme, nc) + case <-ctx.Done(): + return } - }(ctx, updatesChannel) + } } func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(ctx context.Context, From d13b940eff73683279d5220034cc7e844cc63dd7 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Mon, 18 Nov 2024 12:43:59 +0300 Subject: [PATCH 41/50] Add nats sever shutdown. --- cmd/node/node.go | 7 ++++++- pkg/blockchaininfo/nats_publisher.go | 15 +++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/cmd/node/node.go b/cmd/node/node.go index 0656c0946..cf885577e 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -822,7 +822,12 @@ func runBlockchainUpdatesPlugin( ) updatesChannel := make(chan blockchaininfo.BUpdatesInfo) - go bUpdatesExtensionState.RunBlockchainUpdatesPublisher(ctx, updatesChannel, cfg.AddressSchemeCharacter) + go func() { + err := bUpdatesExtensionState.RunBlockchainUpdatesPublisher(ctx, updatesChannel, cfg.AddressSchemeCharacter) + if err != nil { + zap.S().Fatalf("Failed to run blockchain updates publisher: %v", err) + } + }() return &state.BlockchainUpdatesExtension{ EnableBlockchainUpdatesPlugin: true, diff --git a/pkg/blockchaininfo/nats_publisher.go b/pkg/blockchaininfo/nats_publisher.go index 205703492..701dc6ce8 100644 --- a/pkg/blockchaininfo/nats_publisher.go +++ b/pkg/blockchaininfo/nats_publisher.go @@ -7,6 +7,7 @@ import ( "github.com/nats-io/nats-server/v2/server" "github.com/nats-io/nats.go" + "github.com/pkg/errors" "github.com/wavesplatform/gowaves/pkg/proto" ) @@ -207,7 +208,7 @@ func runPublisher(ctx context.Context, updatesChannel <-chan BUpdatesInfo, } func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(ctx context.Context, - updatesChannel <-chan BUpdatesInfo, scheme proto.Scheme) { + updatesChannel <-chan BUpdatesInfo, scheme proto.Scheme) error { opts := &server.Options{ MaxPayload: NatsMaxPayloadSize, Host: HostDefault, @@ -216,19 +217,25 @@ func (bu *BUpdatesExtensionState) RunBlockchainUpdatesPublisher(ctx context.Cont } s, err := server.NewServer(opts) if err != nil { - log.Fatalf("failed to create NATS server: %v", err) + return errors.Wrap(err, "failed to create NATS server") } go s.Start() + defer func() { + s.Shutdown() + s.WaitForShutdown() + }() if !s.ReadyForConnections(ConnectionsTimeoutDefault) { - log.Fatal("NATS Server not ready for connections") + return errors.New("NATS server is not ready for connections") } + log.Printf("NATS Server is running on port %d", PortDefault) nc, err := nats.Connect(nats.DefaultURL) if err != nil { - log.Fatal(err) + return errors.Wrap(err, "failed to connect to NATS server") } defer nc.Close() runPublisher(ctx, updatesChannel, bu, scheme, nc) + return nil } From 4dc94d59405405630ce3803e9301ab40c8d7c12d Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Mon, 18 Nov 2024 15:11:24 +0300 Subject: [PATCH 42/50] Fix deadlock and refactoring. --- cmd/node/node.go | 10 ++----- pkg/blockchaininfo/bupdates.go | 55 ++++++++++++++++++++++++++++++++++ pkg/state/api.go | 3 +- pkg/state/appender.go | 28 +++++++---------- pkg/state/state.go | 3 +- 5 files changed, 73 insertions(+), 26 deletions(-) create mode 100644 pkg/blockchaininfo/bupdates.go diff --git a/cmd/node/node.go b/cmd/node/node.go index cf885577e..336849704 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -400,7 +400,7 @@ func runNode(ctx context.Context, nc *config) (_ io.Closer, retErr error) { return nil, errors.Wrap(err, "failed to create state parameters") } - var bUpdatesExtension *state.BlockchainUpdatesExtension + var bUpdatesExtension *blockchaininfo.BlockchainUpdatesExtension if nc.enableBlockchainUpdatesPlugin { var bUErr error bUpdatesExtension, bUErr = runBlockchainUpdatesPlugin(ctx, cfg) @@ -808,7 +808,7 @@ func runAPIs( func runBlockchainUpdatesPlugin( ctx context.Context, cfg *settings.BlockchainSettings, -) (*state.BlockchainUpdatesExtension, error) { +) (*blockchaininfo.BlockchainUpdatesExtension, error) { const l2ContractAddr = "3Msx4Aq69zWUKy4d1wyKnQ4ofzEDAfv5Ngf" l2address, cnvrtErr := proto.NewAddressFromString(l2ContractAddr) @@ -829,11 +829,7 @@ func runBlockchainUpdatesPlugin( } }() - return &state.BlockchainUpdatesExtension{ - EnableBlockchainUpdatesPlugin: true, - BUpdatesChannel: updatesChannel, - L2ContractAddress: l2address, - }, nil + return blockchaininfo.NewBlockchainUpdatesExtension(ctx, l2address, updatesChannel), nil } func FromArgs(scheme proto.Scheme, c *config) func(s *settings.NodeSettings) error { diff --git a/pkg/blockchaininfo/bupdates.go b/pkg/blockchaininfo/bupdates.go new file mode 100644 index 000000000..56bfcaeb2 --- /dev/null +++ b/pkg/blockchaininfo/bupdates.go @@ -0,0 +1,55 @@ +package blockchaininfo + +import ( + "context" + + "github.com/wavesplatform/gowaves/pkg/proto" +) + +type BlockchainUpdatesExtension struct { + ctx context.Context + enableBlockchainUpdatesPlugin bool + l2ContractAddress proto.WavesAddress + bUpdatesChannel chan<- BUpdatesInfo +} + +func NewBlockchainUpdatesExtension( + ctx context.Context, + l2ContractAddress proto.WavesAddress, + bUpdatesChannel chan<- BUpdatesInfo, +) *BlockchainUpdatesExtension { + return &BlockchainUpdatesExtension{ + ctx: ctx, + enableBlockchainUpdatesPlugin: true, + l2ContractAddress: l2ContractAddress, + bUpdatesChannel: bUpdatesChannel, + } +} + +func (e *BlockchainUpdatesExtension) EnableBlockchainUpdatesPlugin() bool { + return e != nil && e.enableBlockchainUpdatesPlugin +} + +func (e *BlockchainUpdatesExtension) L2ContractAddress() proto.WavesAddress { + return e.l2ContractAddress +} + +func (e *BlockchainUpdatesExtension) WriteBUpdates(bUpdates BUpdatesInfo) { + if e.bUpdatesChannel == nil { + return + } + select { + case e.bUpdatesChannel <- bUpdates: + case <-e.ctx.Done(): + e.close() + return + } +} + +func (e *BlockchainUpdatesExtension) close() { + if e.bUpdatesChannel == nil { + return + } + close(e.bUpdatesChannel) + e.bUpdatesChannel = nil +} diff --git a/pkg/state/api.go b/pkg/state/api.go index fb20105a3..bd7f92086 100644 --- a/pkg/state/api.go +++ b/pkg/state/api.go @@ -6,6 +6,7 @@ import ( "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/blockchaininfo" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/keyvalue" "github.com/wavesplatform/gowaves/pkg/libs/ntptime" @@ -232,7 +233,7 @@ func NewState( params StateParams, settings *settings.BlockchainSettings, enableLightNode bool, - bUpdatesExtension *BlockchainUpdatesExtension, + bUpdatesExtension *blockchaininfo.BlockchainUpdatesExtension, ) (State, error) { s, err := newStateManager(dataDir, amend, params, settings, enableLightNode, bUpdatesExtension) if err != nil { diff --git a/pkg/state/appender.go b/pkg/state/appender.go index 127cb00ef..21268ca43 100644 --- a/pkg/state/appender.go +++ b/pkg/state/appender.go @@ -2,11 +2,13 @@ package state import ( "fmt" + "github.com/mr-tron/base58/base58" "github.com/pkg/errors" - "github.com/wavesplatform/gowaves/pkg/blockchaininfo" "go.uber.org/zap" + "github.com/wavesplatform/gowaves/pkg/blockchaininfo" + "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/errs" "github.com/wavesplatform/gowaves/pkg/proto" @@ -55,13 +57,7 @@ type txAppender struct { // appending transactions. buildApiData bool - bUpdatesExtension *BlockchainUpdatesExtension -} - -type BlockchainUpdatesExtension struct { - EnableBlockchainUpdatesPlugin bool - L2ContractAddress proto.WavesAddress - BUpdatesChannel chan<- blockchaininfo.BUpdatesInfo + bUpdatesExtension *blockchaininfo.BlockchainUpdatesExtension } func newTxAppender( @@ -72,7 +68,7 @@ func newTxAppender( stateDB *stateDB, atx *addressTransactions, snapshotApplier *blockSnapshotsApplier, - bUpdatesExtension *BlockchainUpdatesExtension, + bUpdatesExtension *blockchaininfo.BlockchainUpdatesExtension, ) (*txAppender, error) { buildAPIData, err := stateDB.stateStoresApiData() if err != nil { @@ -847,12 +843,10 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { // write updates into the updatesChannel here // TODO possibly run it in a goroutine? make sure goroutines run in order? - if a.bUpdatesExtension != nil { - if a.bUpdatesExtension.EnableBlockchainUpdatesPlugin { - updtErr := a.updateBlockchainUpdateInfo(blockInfo, params.block) - if updtErr != nil { - return updtErr - } + if a.bUpdatesExtension != nil && a.bUpdatesExtension.EnableBlockchainUpdatesPlugin() { + updtErr := a.updateBlockchainUpdateInfo(blockInfo, params.block) + if updtErr != nil { + return updtErr } } @@ -879,7 +873,7 @@ func (a *txAppender) appendBlock(params *appendBlockParams) error { func (a *txAppender) updateBlockchainUpdateInfo(blockInfo *proto.BlockInfo, blockHeader *proto.BlockHeader) error { // TODO improve this by using diffs instead grabbing all the records every time - dataEntries, err := a.ia.state.RetrieveEntries(proto.NewRecipientFromAddress(a.bUpdatesExtension.L2ContractAddress)) + dataEntries, err := a.ia.state.RetrieveEntries(proto.NewRecipientFromAddress(a.bUpdatesExtension.L2ContractAddress())) if err != nil && !errors.Is(err, proto.ErrNotFound) { return err } @@ -896,7 +890,7 @@ func (a *txAppender) updateBlockchainUpdateInfo(blockInfo *proto.BlockInfo, bloc Height: blockInfo.Height, }, } - a.bUpdatesExtension.BUpdatesChannel <- bUpdatesInfo + a.bUpdatesExtension.WriteBUpdates(bUpdatesInfo) return nil } diff --git a/pkg/state/state.go b/pkg/state/state.go index 64177afdb..57476d9ed 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -16,6 +16,7 @@ import ( "go.uber.org/atomic" "go.uber.org/zap" + "github.com/wavesplatform/gowaves/pkg/blockchaininfo" "github.com/wavesplatform/gowaves/pkg/consensus" "github.com/wavesplatform/gowaves/pkg/crypto" "github.com/wavesplatform/gowaves/pkg/errs" @@ -519,7 +520,7 @@ func newStateManager( params StateParams, settings *settings.BlockchainSettings, enableLightNode bool, - bUpdatesExtension *BlockchainUpdatesExtension, + bUpdatesExtension *blockchaininfo.BlockchainUpdatesExtension, ) (_ *stateManager, retErr error) { if err := validateSettings(settings); err != nil { return nil, err From 8fbe2b4f4f02acbc070aed1896fa355cc793db16 Mon Sep 17 00:00:00 2001 From: esuwu Date: Wed, 20 Nov 2024 02:53:00 -0600 Subject: [PATCH 43/50] Fixed err not found handling --- pkg/state/accounts_data_storage.go | 2 +- pkg/state/state.go | 2 +- pkg/state/transaction_handler.go | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pkg/state/accounts_data_storage.go b/pkg/state/accounts_data_storage.go index b4a7c8756..dcb2c894e 100644 --- a/pkg/state/accounts_data_storage.go +++ b/pkg/state/accounts_data_storage.go @@ -242,7 +242,7 @@ func (s *accountsDataStorage) entryBytes(addr proto.Address, entryKey string) ([ func (s *accountsDataStorage) retrieveEntries(addr proto.Address) ([]proto.DataEntry, error) { addrNum, err := s.addrToNum(addr) if err != nil { - return nil, proto.ErrNotFound + return nil, wrapErr(NotFoundError, err) } key := accountsDataStorKey{addrNum: addrNum} iter, err := s.hs.newTopEntryIteratorByPrefix(key.accountPrefix()) diff --git a/pkg/state/state.go b/pkg/state/state.go index 57476d9ed..a65273f7f 100644 --- a/pkg/state/state.go +++ b/pkg/state/state.go @@ -2364,7 +2364,7 @@ func (s *stateManager) RetrieveEntries(account proto.Recipient) ([]proto.DataEnt } entries, err := s.stor.accountsDataStor.retrieveEntries(addr) if err != nil { - if errors.Is(err, proto.ErrNotFound) { + if IsNotFound(err) { return nil, err } return nil, wrapErr(RetrievalError, err) diff --git a/pkg/state/transaction_handler.go b/pkg/state/transaction_handler.go index 0fc973769..103af3f89 100644 --- a/pkg/state/transaction_handler.go +++ b/pkg/state/transaction_handler.go @@ -265,8 +265,6 @@ func (h *transactionHandler) performTx( return txSnapshot{}, errors.Wrap(err, "failed to apply transaction snapshot") } - // write updates into the updatesChannel here - return snapshot, nil } From bb23dbccb88284b88a7034bc444fbb69eeaf1ca4 Mon Sep 17 00:00:00 2001 From: Aleksandr Dolgavin Date: Wed, 20 Nov 2024 08:27:49 -0600 Subject: [PATCH 44/50] Fixed a toolchain not found issue (#1545) --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 06d23b3de..5bbe3982e 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/wavesplatform/gowaves -go 1.22 +go 1.22.0 require ( filippo.io/edwards25519 v1.1.0 From b65c6d97d28ace6874e44e1d41caa4a4990ab9b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 12:44:21 +0400 Subject: [PATCH 45/50] Bump github.com/stretchr/testify from 1.9.0 to 1.10.0 (#1546) Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.9.0 to 1.10.0. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.9.0...v1.10.0) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5bbe3982e..bdb939bfc 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/starius/emsort v0.0.0-20191221202443-6f2fbdee4781 github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 github.com/stoewer/go-strcase v1.3.0 - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.10.0 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/throttled/throttled/v2 v2.12.0 github.com/tidwall/sjson v1.2.5 diff --git a/go.sum b/go.sum index 6c83a7ed6..ab2d281a9 100644 --- a/go.sum +++ b/go.sum @@ -296,8 +296,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8= From 68db8b321d024f8dd628f410b64ed78fa8044d53 Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Tue, 26 Nov 2024 10:52:41 +0300 Subject: [PATCH 46/50] Handle blockchain import errors properly (#1548) Return error instead of killing process with fatal log record. --- cmd/importer/importer.go | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/cmd/importer/importer.go b/cmd/importer/importer.go index 435748032..64145d3d4 100644 --- a/cmd/importer/importer.go +++ b/cmd/importer/importer.go @@ -178,6 +178,11 @@ func runImporter(c *cfg) error { return err } defer cpfClose() + defer func() { // Debug. + if mpfErr := configureMemProfile(c.memProfilePath); mpfErr != nil { + zap.S().Errorf("Failed to configure memory profile: %v", mpfErr) + } + }() // https://godoc.org/github.com/coocood/freecache#NewCache debug.SetGCPercent(20) @@ -213,15 +218,19 @@ func runImporter(c *cfg) error { } start := time.Now() + defer func() { + elapsed := time.Since(start) + zap.S().Infof("Import took %s", elapsed) + }() if impErr := importer.ApplyFromFile(ctx, params, st, uint64(c.nBlocks), height); impErr != nil { currentHeight, hErr := st.Height() if hErr != nil { zap.S().Fatalf("Failed to get current height: %v", hErr) } - handleError(impErr, currentHeight) + if resErr := handleError(impErr, currentHeight); resErr != nil { + return resErr + } } - elapsed := time.Since(start) - zap.S().Infof("Import took %s", elapsed) if len(c.balancesPath) != 0 { if balErr := importer.CheckBalances(st, c.balancesPath); balErr != nil { @@ -229,22 +238,19 @@ func runImporter(c *cfg) error { } } - // Debug. - if mpfErr := configureMemProfile(c.memProfilePath); mpfErr != nil { - return mpfErr - } - return nil } -func handleError(err error, height uint64) { +func handleError(err error, height uint64) error { switch { case errors.Is(err, context.Canceled): zap.S().Infof("Interrupted by user, height %d", height) + return nil case errors.Is(err, io.EOF): zap.S().Infof("End of blockchain file reached, height %d", height) + return nil default: - zap.S().Fatalf("Failed to apply blocks after height %d: %v", height, err) + return fmt.Errorf("failed to apply blocks after height %d: %w", height, err) } } From d66423a7cb63f80c1d53fd142093473191182ad0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Nov 2024 13:04:41 +0400 Subject: [PATCH 47/50] Bump github.com/elliotchance/orderedmap/v2 from 2.4.0 to 2.5.0 (#1549) Bumps [github.com/elliotchance/orderedmap/v2](https://github.com/elliotchance/orderedmap) from 2.4.0 to 2.5.0. - [Release notes](https://github.com/elliotchance/orderedmap/releases) - [Commits](https://github.com/elliotchance/orderedmap/compare/v2.4.0...v2.5.0) --- updated-dependencies: - dependency-name: github.com/elliotchance/orderedmap/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bdb939bfc..2bbf99dc4 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/consensys/gnark v0.11.0 github.com/consensys/gnark-crypto v0.14.0 github.com/coocood/freecache v1.2.4 - github.com/elliotchance/orderedmap/v2 v2.4.0 + github.com/elliotchance/orderedmap/v2 v2.5.0 github.com/ericlagergren/decimal v0.0.0-20210307182354-5f8425a47c58 github.com/fxamacker/cbor/v2 v2.7.0 github.com/go-chi/chi v4.1.2+incompatible diff --git a/go.sum b/go.sum index ab2d281a9..433a2913d 100644 --- a/go.sum +++ b/go.sum @@ -67,8 +67,8 @@ github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/elliotchance/orderedmap/v2 v2.4.0 h1:6tUmMwD9F998FNpwFxA5E6NQvSpk2PVw7RKsVq3+2Cw= -github.com/elliotchance/orderedmap/v2 v2.4.0/go.mod h1:85lZyVbpGaGvHvnKa7Qhx7zncAdBIBq6u56Hb1PRU5Q= +github.com/elliotchance/orderedmap/v2 v2.5.0 h1:WRPmWGChucaZ09eEd3UkU8XfVajv6ZZ6eg3+x0cLWPM= +github.com/elliotchance/orderedmap/v2 v2.5.0/go.mod h1:85lZyVbpGaGvHvnKa7Qhx7zncAdBIBq6u56Hb1PRU5Q= github.com/ericlagergren/decimal v0.0.0-20210307182354-5f8425a47c58 h1:+Ct3FisijQso/lJt1zGGl0eIcFCoM0dozj4tiPJamqw= github.com/ericlagergren/decimal v0.0.0-20210307182354-5f8425a47c58/go.mod h1:ZWP59etEywfyMG2lAqnoi3t8uoiZCiTmLtwt6iESIsQ= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= From c598d67aeb49cb0c5d3804b2d8def910e9a916d1 Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Thu, 28 Nov 2024 15:47:30 +0400 Subject: [PATCH 48/50] Check on leasing state added. (#1550) * Check on leasing state added. * Tests added. --------- Co-authored-by: Nikolay Eskov --- pkg/proto/actions_validator.go | 1 + pkg/state/invoke_applier.go | 6 ++ pkg/state/invoke_applier_test.go | 16 ++++- pkg/state/snapshot_generator_internal_test.go | 72 +++++++++++++++++++ 4 files changed, 92 insertions(+), 3 deletions(-) diff --git a/pkg/proto/actions_validator.go b/pkg/proto/actions_validator.go index 8056a9771..4383f6b1c 100644 --- a/pkg/proto/actions_validator.go +++ b/pkg/proto/actions_validator.go @@ -2,6 +2,7 @@ package proto import ( "github.com/pkg/errors" + "github.com/wavesplatform/gowaves/pkg/ride/ast" ) diff --git a/pkg/state/invoke_applier.go b/pkg/state/invoke_applier.go index c7acf0d2a..d8a2991a4 100644 --- a/pkg/state/invoke_applier.go +++ b/pkg/state/invoke_applier.go @@ -709,6 +709,12 @@ func (ia *invokeApplier) fallibleValidation(tx proto.Transaction, info *addlInvo if err != nil { return proto.DAppError, info.failedChanges, err } + if !li.isActive() { + return proto.DAppError, info.failedChanges, + errors.Errorf( + "failed to cancel leasing %q, leasing is already cancelled", a.LeaseID.String(), + ) + } if senderPK != li.SenderPK { return proto.DAppError, info.failedChanges, errors.Errorf( diff --git a/pkg/state/invoke_applier_test.go b/pkg/state/invoke_applier_test.go index 2fd0c1e64..7882eb856 100644 --- a/pkg/state/invoke_applier_test.go +++ b/pkg/state/invoke_applier_test.go @@ -149,9 +149,9 @@ func (to *invokeApplierTestObjects) activateFeature(t *testing.T, feature int16) to.state.reset() } -func (to *invokeApplierTestObjects) applyAndSaveInvoke(t *testing.T, tx *proto.InvokeScriptWithProofs, +func (to *invokeApplierTestObjects) applyAndSaveInvokeIfOk(t *testing.T, tx *proto.InvokeScriptWithProofs, info *fallibleValidationParams, - shouldCommitUncertain bool) (*invocationResult, *applicationResult) { + shouldCommitUncertain bool) (*invocationResult, *applicationResult, error) { // TODO: consider rewriting using txAppender. // This should simplify tests because we actually reimplement part of appendTx() here. if shouldCommitUncertain { @@ -162,13 +162,23 @@ func (to *invokeApplierTestObjects) applyAndSaveInvoke(t *testing.T, tx *proto.I } invocationRes, applicationRes, err := to.state.appender.ia.applyInvokeScript(tx, info) - require.NoError(t, err) + if err != nil { // if error occurred, we should not save diff and return immediately + return invocationRes, applicationRes, err + } err = to.state.appender.diffStor.saveTxDiff(applicationRes.changes.diff) assert.NoError(t, err) if applicationRes.status && shouldCommitUncertain { err = to.state.stor.commitUncertain(info.checkerInfo.blockID) assert.NoError(t, err) } + return invocationRes, applicationRes, nil +} + +func (to *invokeApplierTestObjects) applyAndSaveInvoke(t *testing.T, tx *proto.InvokeScriptWithProofs, + info *fallibleValidationParams, + shouldCommitUncertain bool) (*invocationResult, *applicationResult) { + invocationRes, applicationRes, err := to.applyAndSaveInvokeIfOk(t, tx, info, shouldCommitUncertain) + require.NoError(t, err) return invocationRes, applicationRes } diff --git a/pkg/state/snapshot_generator_internal_test.go b/pkg/state/snapshot_generator_internal_test.go index b674f5249..d80108a2e 100644 --- a/pkg/state/snapshot_generator_internal_test.go +++ b/pkg/state/snapshot_generator_internal_test.go @@ -1309,6 +1309,78 @@ func TestLeaseAndLeaseCancelInTheSameInvokeTx(t *testing.T) { assert.NoError(t, flushErr) } +func TestDoubleLeaseCancelApplicationFailure(t *testing.T) { + const ( + script = ` + {-# STDLIB_VERSION 5 #-} + {-# CONTENT_TYPE DAPP #-} + {-# SCRIPT_TYPE ACCOUNT #-} + + let addr = Address(base58'3PD8uesEwWoKu63ujwbJXeJdk7jygdimJST') + + @Callable(i) + func call() = { + let lease = Lease(addr, 1000000) + let leaseID = calculateLeaseId(lease) + [lease, LeaseCancel(leaseID), LeaseCancel(leaseID)] + }` + leaseAmount = 1000000 + leaseRecipientAddr = "3PD8uesEwWoKu63ujwbJXeJdk7jygdimJST" + ) + scriptBytes, errs := compiler.Compile(script, false, true) + require.NoError(t, errors.Join(errs...)) + + to := createInvokeApplierTestObjects(t) + info := to.fallibleValidationParams(t) + + dAppInfo := testGlobal.recipientInfo + to.setScript(t, testGlobal.recipientInfo.addr, dAppInfo.pk, scriptBytes) + + amount := uint64(1000) + startBalance := amount + 1 + + wavesBalSender := wavesValue{ + profile: balanceProfile{ + balance: startBalance + invokeFee, + }, + leaseChange: false, + balanceChange: false, + } + wavesBalMiner := wavesValue{ + profile: balanceProfile{ + balance: startBalance, + }, + leaseChange: false, + balanceChange: false, + } + err := to.state.stor.balances.setWavesBalance(testGlobal.senderInfo.addr.ID(), wavesBalSender, blockID0) + assert.NoError(t, err) + err = to.state.stor.balances.setWavesBalance(testGlobal.minerInfo.addr.ID(), wavesBalMiner, blockID0) + assert.NoError(t, err) + + snapshotApplierInfo := newBlockSnapshotsApplierInfo(info.checkerInfo, to.state.settings.AddressSchemeCharacter) + cleanup := to.state.appender.txHandler.sa.SetApplierInfo(snapshotApplierInfo) + defer cleanup() + + testData := invokeApplierTestData{ + payments: []proto.ScriptPayment{}, + fc: proto.NewFunctionCall("call", []proto.Argument{}), + info: info, + } + + tx := createInvokeScriptWithProofs(t, testData.payments, testData.fc, feeAsset, invokeFee) + assert.NoError(t, err, "failed to sign invoke script tx") + + lRcpAddr := proto.MustAddressFromString(leaseRecipientAddr) + lID := proto.GenerateLeaseScriptActionID(proto.NewRecipientFromAddress(lRcpAddr), leaseAmount, 0, *tx.ID) + + _, _, resErr := to.applyAndSaveInvokeIfOk(t, tx, testData.info, false) + assert.Errorf(t, resErr, "failed to cancel leasing \"%s\", leasing is already cancelled", lID.String()) + + flushErr := to.state.stor.flush() + assert.NoError(t, flushErr) +} + func remove(slice []proto.AtomicSnapshot, s int) []proto.AtomicSnapshot { return append(slice[:s], slice[s+1:]...) } From bd889f5fe8c5ca2aac979ff9e5242c6d5a51998c Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Mon, 2 Dec 2024 12:12:20 +0300 Subject: [PATCH 49/50] Prepare timers for go1.23. (#1552) --- pkg/api/app.go | 5 ++++- pkg/api/metamask/service.go | 5 ++++- pkg/libs/ntptime/ntptime.go | 5 ++++- pkg/node/fsm/tasks/tasks.go | 5 ++++- pkg/node/node.go | 10 ++++++++-- pkg/util/limit_listener/listen.go | 5 ++++- 6 files changed, 28 insertions(+), 7 deletions(-) diff --git a/pkg/api/app.go b/pkg/api/app.go index 8246c12ec..b5d06b772 100644 --- a/pkg/api/app.go +++ b/pkg/api/app.go @@ -111,7 +111,10 @@ func (a *App) TransactionsBroadcast(ctx context.Context, b []byte) (proto.Transa ) defer func() { if !delay.Stop() && !fired { - <-delay.C + select { + case <-delay.C: + default: + } } }() select { diff --git a/pkg/api/metamask/service.go b/pkg/api/metamask/service.go index 721de862d..d19cb85f8 100644 --- a/pkg/api/metamask/service.go +++ b/pkg/api/metamask/service.go @@ -395,7 +395,10 @@ func (s RPCService) Eth_SendRawTransaction(signedTxData string) (proto.EthereumH return proto.EthereumHash{}, errors.New("timeout waiting response from internal FSM") case err := <-respCh: if !timer.Stop() { - <-timer.C + select { + case <-timer.C: + default: + } } if err != nil { zap.S().Debugf("Eth_SendRawTransaction: error from internal FSM for ethereum tx (ethTxID=%q, to=%q, from=%q): %v", diff --git a/pkg/libs/ntptime/ntptime.go b/pkg/libs/ntptime/ntptime.go index 2e48b257a..07771ae94 100644 --- a/pkg/libs/ntptime/ntptime.go +++ b/pkg/libs/ntptime/ntptime.go @@ -70,7 +70,10 @@ func (a *ntpTimeImpl) Run(ctx context.Context, duration time.Duration) { select { case <-ctx.Done(): if !timer.Stop() { - <-timer.C + select { + case <-timer.C: + default: + } } return case <-timer.C: diff --git a/pkg/node/fsm/tasks/tasks.go b/pkg/node/fsm/tasks/tasks.go index 37b223c8a..f42e65194 100644 --- a/pkg/node/fsm/tasks/tasks.go +++ b/pkg/node/fsm/tasks/tasks.go @@ -233,7 +233,10 @@ func (a SnapshotTimeoutTask) Run(ctx context.Context, output chan AsyncTask) err t := time.NewTimer(a.timeout) defer func() { if !t.Stop() { - <-t.C + select { + case <-t.C: + default: + } } }() select { diff --git a/pkg/node/node.go b/pkg/node/node.go index f7dad4059..d4cf39bdd 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -222,7 +222,10 @@ func (a *Node) runInternalMetrics(ctx context.Context, ch chan peer.ProtoMessage select { case <-ctx.Done(): if !timer.Stop() { - <-timer.C + select { + case <-timer.C: + default: + } } return case <-timer.C: @@ -238,7 +241,10 @@ func (a *Node) runOutgoingConnections(ctx context.Context) { select { case <-ctx.Done(): if !timer.Stop() { - <-timer.C + select { + case <-timer.C: + default: + } } return case <-timer.C: diff --git a/pkg/util/limit_listener/listen.go b/pkg/util/limit_listener/listen.go index 2710b1b4f..5b8c05a44 100644 --- a/pkg/util/limit_listener/listen.go +++ b/pkg/util/limit_listener/listen.go @@ -90,7 +90,10 @@ func (l *limitListener) acquire() bool { timer := time.NewTimer(l.waitConnQuotaTimeout) stopTimer := func() { if !timer.Stop() { - <-timer.C + select { + case <-timer.C: + default: + } } } select { From c24cb574938f061b1d2cc05ae5e41a672fd3c6df Mon Sep 17 00:00:00 2001 From: Nikolay Eskov Date: Tue, 3 Dec 2024 13:10:01 +0300 Subject: [PATCH 50/50] Peer address parsing refactoring (#1551) * Refactor and fix 'NewPeerInfoFromString' Add check for IP address parsing failure. Improved 'TestNewPeerInfoFromString'. * Improve 'NewPeerInfoFromString' Add hostname IP resolving. * Simplified 'NewTCPAddrFromString' * Refactoring and bugfix of 'resolveHostToIPv4' - Now it returns ipV4 address exactly in ipV4 form. - Fixed bug with skipping address for chesk after ipV6 removal. - Fixed bug with duplication of ipV4 address when resolving 'localhost'. * Optimized a bit 'filterToIPV4'. * Create 'NewPeerInfosFromString' function. * Use 'NewPeerInfosFromString' for resolving 'host:port' records by '-peers' CLI parameter. * Fix 'TestNewPeerInfoFromString' test. --------- Co-authored-by: Alexey Kiselev --- cmd/node/node.go | 21 +++++--- pkg/proto/proto.go | 104 +++++++++++++++++++++++++++++++--------- pkg/proto/proto_test.go | 90 ++++++++++++++++++++++++++++++++-- 3 files changed, 182 insertions(+), 33 deletions(-) diff --git a/cmd/node/node.go b/cmd/node/node.go index 67042d399..3282b302d 100644 --- a/cmd/node/node.go +++ b/cmd/node/node.go @@ -657,14 +657,21 @@ func spawnPeersByAddresses(ctx context.Context, addressesByComma string, pm *pee } addresses := strings.Split(addressesByComma, ",") for _, addr := range addresses { - tcpAddr := proto.NewTCPAddrFromString(addr) - if tcpAddr.Empty() { - // That means that configuration parameter is invalid - return errors.Errorf("Failed to parse TCPAddr from string %q", tcpAddr.String()) + peerInfos, err := proto.NewPeerInfosFromString(addr) + if err != nil { + return errors.Wrapf(err, "failed to resolve TCP addresses from string %q", addr) } - if pErr := pm.AddAddress(ctx, tcpAddr); pErr != nil { - // That means that we have problems with peers storage - return errors.Wrapf(pErr, "failed to add address %q into known peers storage", tcpAddr.String()) + for _, pi := range peerInfos { + tcpAddr := proto.NewTCPAddr(pi.Addr, int(pi.Port)) + if tcpAddr.Empty() { + return errors.Errorf("failed to create TCP address from IP %q and port %d", + fmt.Stringer(pi.Addr), pi.Port, + ) + } + if pErr := pm.AddAddress(ctx, tcpAddr); pErr != nil { + // That means that we have problems with peers storage + return errors.Wrapf(pErr, "failed to add address %q into known peers storage", tcpAddr.String()) + } } } return nil diff --git a/pkg/proto/proto.go b/pkg/proto/proto.go index 8a917301f..8f039d9b0 100644 --- a/pkg/proto/proto.go +++ b/pkg/proto/proto.go @@ -6,6 +6,7 @@ import ( "encoding/binary" "fmt" "io" + "math/rand/v2" "net" "strconv" "strings" @@ -375,23 +376,14 @@ func (a TCPAddr) Equal(other TCPAddr) bool { return a.IP.Equal(other.IP) && a.Port == other.Port } +// NewTCPAddrFromString creates TCPAddr from string. +// Returns empty TCPAddr if string can't be parsed. func NewTCPAddrFromString(s string) TCPAddr { - host, port, err := net.SplitHostPort(s) + pi, err := NewPeerInfoFromString(s) if err != nil { - return TCPAddr{} + return TCPAddr{} // return empty TCPAddr in case of error } - ip := net.ParseIP(host) - if ip == nil { - ips, err := net.LookupIP(host) - if err == nil { - ip = ips[0] - } - } - p, err := strconv.ParseUint(port, 10, 16) - if err != nil { - return TCPAddr{} - } - return NewTCPAddr(ip, int(p)) + return NewTCPAddr(pi.Addr, int(pi.Port)) } func NewTcpAddrFromUint64(value uint64) TCPAddr { @@ -737,26 +729,94 @@ func (a *IpPort) String() string { return NewTCPAddr(a.Addr(), a.Port()).String() } +func filterToIPV4(ips []net.IP) []net.IP { + for i := 0; i < len(ips); i++ { + ipV4 := ips[i].To4() + if ipV4 == nil { // for now we support only IPv4 + iLast := len(ips) - 1 + ips[i], ips[iLast] = ips[iLast], nil // move last address to the current position, order is not important + ips = ips[:iLast] // remove last address + i-- // move back to check the previously last address + } else { + ips[i] = ipV4 // replace with exact IPv4 form (ipV4 can be in both forms: ipv4 and ipV4 in ipv6) + } + } + return ips +} + +func resolveHostToIPsv4(host string) ([]net.IP, error) { + if ip := net.ParseIP(host); ip != nil { // try to parse host as IP address + ipV4 := ip.To4() // try to convert to IPv4 + if ipV4 == nil { + return nil, errors.Errorf("non-IPv4 address %q", host) + } + return []net.IP{ipV4}, nil // host is already an IP address + } + ips, err := net.LookupIP(host) // try to resolve host + if err != nil { + return nil, errors.Wrapf(err, "failed to resolve host %q", host) + } + ips = filterToIPV4(ips) + if len(ips) == 0 { + return nil, errors.Errorf("no IPv4 addresses found for host %q", host) + } + return ips, nil +} + // PeerInfo represents the address of a single peer type PeerInfo struct { Addr net.IP Port uint16 } -func NewPeerInfoFromString(addr string) (PeerInfo, error) { - parts := strings.Split(addr, ":") - if len(parts) != 2 { - return PeerInfo{}, errors.Errorf("invalid addr %s", addr) +func ipsV4PortFromString(addr string) ([]net.IP, uint16, error) { + host, port, err := net.SplitHostPort(addr) + if err != nil { + return nil, 0, errors.Wrap(err, "failed to split host and port") + } + portNum, err := strconv.ParseUint(port, 10, 16) + if err != nil { + return nil, 0, errors.Errorf("invalid port %q", port) + } + if portNum == 0 { + return nil, 0, errors.Errorf("invalid port %q", port) + } + ips, err := resolveHostToIPsv4(host) + if err != nil { + return nil, 0, errors.Wrap(err, "failed to resolve host") + } + return ips, uint16(portNum), nil +} + +// NewPeerInfosFromString creates PeerInfo slice from string 'host:port'. +// It resolves host to IPv4 addresses and creates PeerInfo for each of them. +func NewPeerInfosFromString(addr string) ([]PeerInfo, error) { + ips, portNum, err := ipsV4PortFromString(addr) + if err != nil { + return nil, err } + res := make([]PeerInfo, 0, len(ips)) + for _, ip := range ips { + res = append(res, PeerInfo{ + Addr: ip, + Port: portNum, + }) + } + return res, nil +} - ip := net.ParseIP(parts[0]) - port, err := strconv.ParseUint(parts[1], 10, 16) +// NewPeerInfoFromString creates PeerInfo from string 'host:port'. +// It resolves host to IPv4 addresses and selects the random one using math/rand/v2. +func NewPeerInfoFromString(addr string) (PeerInfo, error) { + ips, portNum, err := ipsV4PortFromString(addr) if err != nil { - return PeerInfo{}, errors.Errorf("invalid port %s", parts[1]) + return PeerInfo{}, err } + n := rand.IntN(len(ips)) // #nosec: it's ok to use math/rand/v2 here + ip := ips[n] // Select random IPv4 from the list return PeerInfo{ Addr: ip, - Port: uint16(port), + Port: portNum, }, nil } diff --git a/pkg/proto/proto_test.go b/pkg/proto/proto_test.go index bdad8a522..b63d469aa 100644 --- a/pkg/proto/proto_test.go +++ b/pkg/proto/proto_test.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" "io" + "math" "net" "sort" "strings" @@ -14,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/wavesplatform/gowaves/pkg/crypto" ) @@ -277,10 +279,90 @@ func TestPeerInfoMarshalJSON(t *testing.T) { } func TestNewPeerInfoFromString(t *testing.T) { - rs, err := NewPeerInfoFromString("34.253.153.4:6868") - require.NoError(t, err) - assert.Equal(t, "34.253.153.4", rs.Addr.String()) - assert.EqualValues(t, 6868, rs.Port) + tests := []struct { + in string + out PeerInfo + err string + platformDependentErrMsg bool + }{ + {in: "34.253.153.4:6868", out: PeerInfo{net.IPv4(34, 253, 153, 4).To4(), 6868}, err: ""}, + { + in: "34.444.153.4:6868", + out: PeerInfo{}, + err: "failed to resolve host: failed to resolve host \"34.444.153.4\": lookup 34.444.153.4: no such host", + }, + { + in: "jfhasjdhfkmnn:6868", + out: PeerInfo{}, + err: "failed to resolve host: failed to resolve host \"jfhasjdhfkmnn\": ", + platformDependentErrMsg: true, + }, + { + in: "localhost:6868", + out: PeerInfo{net.IPv4(127, 0, 0, 1).To4(), 6868}, + err: "", + }, + { + in: "127.0.0.1:6868", + out: PeerInfo{net.IPv4(127, 0, 0, 1).To4(), 6868}, + err: "", + }, + { + in: fmt.Sprintf("34.44.153.4:%d", math.MaxUint16+1), + out: PeerInfo{}, + err: fmt.Sprintf("invalid port \"%d\"", math.MaxUint16+1), + }, + { + in: fmt.Sprintf("34.44.153.4:%d", -42), + out: PeerInfo{}, + err: fmt.Sprintf("invalid port \"%d\"", -42), + }, + {in: "34.44.153.4:bugaga", out: PeerInfo{}, err: "invalid port \"bugaga\""}, + {in: "34.44.153.4:0", out: PeerInfo{}, err: "invalid port \"0\""}, + {in: "34.44.153.4:", out: PeerInfo{}, err: "invalid port \"\""}, + { + in: "34.44.153.4", + out: PeerInfo{}, + err: "failed to split host and port: address 34.44.153.4: missing port in address", + }, + { + in: "34.44.153.4:42:", + out: PeerInfo{}, + err: "failed to split host and port: address 34.44.153.4:42:: too many colons in address", + }, + } + for i, tc := range tests { + t.Run(fmt.Sprintf("case_%d", i), func(t *testing.T) { + t.Run("NewPeerInfoFromString", func(t *testing.T) { + rs, err := NewPeerInfoFromString(tc.in) + if tc.err != "" { + if tc.platformDependentErrMsg { + assert.ErrorContains(t, err, tc.err) + } else { + assert.EqualError(t, err, tc.err) + } + } else { + require.NoError(t, err) + assert.Equal(t, tc.out, rs) + } + }) + t.Run("NewPeerInfosFromString", func(t *testing.T) { + rs, err := NewPeerInfosFromString(tc.in) + if tc.err != "" { + if tc.platformDependentErrMsg { + assert.ErrorContains(t, err, tc.err) + } else { + assert.EqualError(t, err, tc.err) + } + } else { + require.NoError(t, err) + assert.Len(t, rs, 1) + res := rs[0] + assert.Equal(t, tc.out, res) + } + }) + }) + } } func TestPeerInfoUnmarshalJSON(t *testing.T) {