Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Itest light node state hash #1512

Merged
merged 83 commits into from
Dec 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
c000f3c
Test fixture that starts one Go node added.
alexeykiselev Sep 30, 2024
c27d530
Genesis and key-block snapshot hashes generation added.
alexeykiselev Oct 3, 2024
54ba718
Added config options to configure preactivated featuers and absence p…
alexeykiselev Oct 3, 2024
350b071
Fix genesis block snapshot hash calculation.
alexeykiselev Oct 3, 2024
e797cac
Test refactoring.
alexeykiselev Oct 7, 2024
2daaf9d
Linter issues fixed.
alexeykiselev Oct 7, 2024
def62d4
Rename test suite.
alexeykiselev Oct 7, 2024
c10dfd0
Merge branch 'master' into itest-light-node-state-hash
alexeykiselev Oct 7, 2024
30bf02f
Merge branch 'master' into itest-light-node-state-hash
alexeykiselev Oct 8, 2024
dbec589
Merge branch 'master' into itest-light-node-state-hash
nickeskov Oct 18, 2024
77a4392
Merge branch 'master' into itest-light-node-state-hash
alexeykiselev Oct 21, 2024
fc8b25a
Better function naming.
alexeykiselev Oct 21, 2024
470cae5
TaskGroup goroutine manager added in pkg/execution package.
alexeykiselev Nov 14, 2024
561302a
Networking package with a new connection handler Session added.
alexeykiselev Nov 15, 2024
3d5e202
Logger interface removed from networking package. Standard slog packa…
alexeykiselev Nov 18, 2024
60d0178
WIP. Simple connection replaced with NetClient.
alexeykiselev Nov 25, 2024
eb14f66
Merge branch 'master' into new-network-connection
alexeykiselev Nov 25, 2024
948cc56
Fixed NetClient closing issue.
alexeykiselev Nov 25, 2024
67f4b85
Redundant log removed.
alexeykiselev Nov 25, 2024
d44fa7f
Move save int conversion to safecast lib.
alexeykiselev Nov 25, 2024
d139cb9
Merge branch 'master' into itest-light-node-state-hash
alexeykiselev Nov 27, 2024
19ef470
Accidentially added files removed.
alexeykiselev Nov 27, 2024
cc1f425
Merge branch 'master' into itest-light-node-state-hash
alexeykiselev Nov 27, 2024
65414fa
Merge branch 'master' into new-network-connection
alexeykiselev Nov 27, 2024
1b130f2
Merge branch 'new-network-connection' into itest-light-node-state-hash
alexeykiselev Nov 27, 2024
512a441
Fixed handshake issue for the single node test suite.
alexeykiselev Nov 27, 2024
643c9c4
Merge branch 'master' into itest-light-node-state-hash
alexeykiselev Nov 28, 2024
7bab250
Merge branch 'master' into new-network-connection
nickeskov Nov 28, 2024
df01e60
Fix data race error in 'networking_test' package
nickeskov Nov 28, 2024
0f3cd81
Refactofing of test containers shutdown. Explicit test containers rem…
alexeykiselev Nov 29, 2024
2af500b
Paralles start and shutdown of test nodes implemented.
alexeykiselev Nov 29, 2024
4f8b6b7
Add parallelizm to some Docker functions.
alexeykiselev Dec 3, 2024
9705342
Merge branch 'master' into new-network-connection
nickeskov Dec 3, 2024
5e753de
Merge branch 'new-network-connection' into itest-light-node-state-hash
alexeykiselev Dec 4, 2024
855acc9
Merge branch 'master' into itest-light-node-state-hash
alexeykiselev Dec 5, 2024
bd86c93
Support native itest container building for Gowaves node.
alexeykiselev Dec 6, 2024
d7217de
Merge branch 'master' into itest-light-node-state-hash
alexeykiselev Dec 6, 2024
41147b0
Fix linter issues.
alexeykiselev Dec 6, 2024
70a8c34
Merge branch 'master' into new-network-connection
alexeykiselev Dec 6, 2024
00a9ebe
Replace atomic.Uint32 with atomic.Bool and use CompareAndSwap there i…
alexeykiselev Dec 10, 2024
63a0305
Assertions added.
alexeykiselev Dec 10, 2024
5219227
Simplified closing and close logic in NetClient.
alexeykiselev Dec 11, 2024
9b63c35
Merge branch 'new-network-connection' into itest-light-node-state-hash
alexeykiselev Dec 11, 2024
ff41cf7
Prepare for new timer in Go 1.23
alexeykiselev Dec 11, 2024
e2f697f
Move constant into function were it used.
alexeykiselev Dec 12, 2024
edd942a
Merge branch 'master' into new-network-connection
alexeykiselev Dec 12, 2024
f832683
Better way to prevent from running multiple receiveLoops.
alexeykiselev Dec 13, 2024
c2ad101
Better data emptyness checks.
alexeykiselev Dec 13, 2024
3aa8a85
Better read error handling.
alexeykiselev Dec 13, 2024
c08bace
Use constructor.
alexeykiselev Dec 13, 2024
abced7f
Wrap heavy logging into log level checks.
alexeykiselev Dec 14, 2024
64bf7d9
Merge branch 'master' into new-network-connection
alexeykiselev Dec 14, 2024
294cf66
Merge branch 'master' into new-network-connection
alexeykiselev Dec 14, 2024
57b9ffb
Session configuration accepts slog handler to set up logging.
alexeykiselev Dec 16, 2024
fdd44ef
Merge branch 'new-network-connection' into itest-light-node-state-hash
alexeykiselev Dec 16, 2024
14420bc
Close error channel on sending data successfully.
alexeykiselev Dec 16, 2024
412377f
Better error handling while reading.
alexeykiselev Dec 16, 2024
52a893e
Fine error assertions.
alexeykiselev Dec 16, 2024
77633f3
Fix blinking test.
alexeykiselev Dec 16, 2024
125adb7
Merge branch 'new-network-connection' into itest-light-node-state-hash
alexeykiselev Dec 16, 2024
8747fc4
Merge branch 'master' into new-network-connection
alexeykiselev Dec 18, 2024
2f7bcc5
Merge branch 'new-network-connection' into itest-light-node-state-hash
alexeykiselev Dec 18, 2024
df77a57
Better configuration handling.
alexeykiselev Dec 19, 2024
dc78383
Merge branch 'master' into new-network-connection
alexeykiselev Dec 19, 2024
7b3fffb
Fixed blinking test TestCloseParentContext. Wait group added to wait …
alexeykiselev Dec 19, 2024
d2e2646
Better test workflow. Better wait group naming.
alexeykiselev Dec 19, 2024
3d8f38d
Merge branch 'master' into new-network-connection
alexeykiselev Dec 20, 2024
9599840
Fix deadlock in test by introducing wait group instead of sleep.
alexeykiselev Dec 20, 2024
275701e
Merge branch 'new-network-connection' into itest-light-node-state-hash
alexeykiselev Dec 20, 2024
044cab1
Function to disable IPv6 in itest docker containers added.
alexeykiselev Dec 24, 2024
b5d5173
Merge branch 'master' into new-network-connection
alexeykiselev Dec 24, 2024
0f4b79b
Merge branch 'new-network-connection' into itest-light-node-state-hash
alexeykiselev Dec 24, 2024
16a32cb
Merge branch 'master' into new-network-connection
alexeykiselev Dec 26, 2024
227698f
Merge branch 'new-network-connection' into itest-light-node-state-hash
alexeykiselev Dec 26, 2024
7a27d43
Functions to subscribe and wait for network messages of specifed type…
alexeykiselev Dec 26, 2024
897c3ff
Better error messages.
alexeykiselev Dec 27, 2024
63ade4e
Internal sendPacket reimplemented using io.Reader. Data restoration f…
alexeykiselev Dec 27, 2024
7a5d641
Merge branch 'new-network-connection' into itest-light-node-state-hash
alexeykiselev Dec 27, 2024
aa2bff0
Handler implementation updated.
alexeykiselev Dec 27, 2024
78579ca
Itest network client handler updated.
alexeykiselev Dec 27, 2024
d2b67d5
Merge branch 'new-network-connection' into itest-light-node-state-hash
alexeykiselev Dec 27, 2024
ca36923
Fix multiple containers removal issue.
alexeykiselev Dec 27, 2024
d5998c3
Merge branch 'master' into itest-light-node-state-hash
alexeykiselev Dec 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions Dockerfile.gowaves-it
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ COPY cmd cmd
COPY pkg pkg

ARG WITH_RACE_SUFFIX=""
RUN make build-node-linux-amd64${WITH_RACE_SUFFIX}
RUN make build-node-native${WITH_RACE_SUFFIX}

FROM alpine:3.21.0
ENV TZ=Etc/UTC \
APP_USER=gowaves

RUN apk add --no-cache bind-tools
RUN apk add --no-cache bind-tools curl

RUN addgroup -S $APP_USER \
&& adduser -S $APP_USER -G $APP_USER
Expand All @@ -34,7 +34,9 @@ ENV CONFIG_PATH=/home/gowaves/config/gowaves-it.json \

USER $APP_USER

COPY --from=builder /app/build/bin/linux-amd64/node /app/node
COPY --from=builder /app/build/bin/native/node /app/node

HEALTHCHECK CMD curl -f http://localhost:6869/node/status || exit 1

STOPSIGNAL SIGINT

Expand Down Expand Up @@ -64,3 +66,5 @@ CMD /app/node \
-microblock-interval 2s \
-blacklist-residence-time 0 \
-rate-limiter-opts="rps=100&burst=100" \
-min-peers-mining=2 \
-disable-miner=$DISABLE_MINER \
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ dist-blockcmp: release-blockcmp

build-node-native:
@go build -o build/bin/native/node -ldflags="-X 'github.com/wavesplatform/gowaves/pkg/versioning.Version=$(VERSION)'" ./cmd/node
build-node-native-with-race:
@go build -race -o build/bin/native/node -ldflags="-X 'github.com/wavesplatform/gowaves/pkg/versioning.Version=$(VERSION)'" ./cmd/node
build-node-linux-amd64:
@CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o build/bin/linux-amd64/node -ldflags="-X 'github.com/wavesplatform/gowaves/pkg/versioning.Version=$(VERSION)'" ./cmd/node
build-node-linux-amd64-with-race:
Expand Down
132 changes: 128 additions & 4 deletions itests/clients/net_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ import (
"bytes"
"context"
"encoding/base64"
"errors"
"fmt"
"io"
"log/slog"
"math/big"
"net"
"reflect"
"sync"
"sync/atomic"
"testing"
Expand All @@ -33,6 +37,7 @@ type NetClient struct {
impl Implementation
n *networking.Network
c *networking.Config
h *handler
s *networking.Session

closing atomic.Bool
Expand All @@ -45,7 +50,17 @@ func NewNetClient(
n := networking.NewNetwork()
p := newProtocol(t, nil)
h := newHandler(t, peers)
log := slogt.New(t)

f := slogt.Factory(func(w io.Writer) slog.Handler {
opts := &slog.HandlerOptions{
AddSource: true,
Level: slog.LevelInfo,
}
return slog.NewTextHandler(w, opts)
})
log := slogt.New(t, f)

slog.SetLogLoggerLevel(slog.LevelError)
conf := networking.NewConfig(p, h).
WithSlogHandler(log.Handler()).
WithWriteTimeout(networkTimeout).
Expand All @@ -58,7 +73,7 @@ func NewNetClient(
s, err := n.NewSession(ctx, conn, conf)
require.NoError(t, err, "failed to establish new session to %s node", impl.String())

cli := &NetClient{ctx: ctx, t: t, impl: impl, n: n, c: conf, s: s}
cli := &NetClient{ctx: ctx, t: t, impl: impl, n: n, c: conf, h: h, s: s}
h.client = cli // Set client reference in handler.
return cli
}
Expand Down Expand Up @@ -93,9 +108,85 @@ func (c *NetClient) Close() {
}
err := c.s.Close()
require.NoError(c.t, err, "failed to close session to %s node at %q", c.impl.String(), c.s.RemoteAddr())
c.h.close()
})
}

// SubscribeForMessages adds specified types to the message waiting queue.
// Once the awaited message received the corresponding type is removed from the queue.
func (c *NetClient) SubscribeForMessages(messageType ...reflect.Type) error {
for _, mt := range messageType {
if err := c.h.waitFor(mt); err != nil {
return err
}
}
return nil
}

// AwaitMessage waits for a message from the node for the specified timeout.
func (c *NetClient) AwaitMessage(messageType reflect.Type, timeout time.Duration) (proto.Message, error) {
nickeskov marked this conversation as resolved.
Show resolved Hide resolved
select {
case <-c.ctx.Done():
return nil, c.ctx.Err()
case <-time.After(timeout):
return nil, fmt.Errorf("timeout waiting for message of type %q", messageType.String())
case msg := <-c.h.receiveChan():
if reflect.TypeOf(msg) != messageType {
return nil, fmt.Errorf("unexpected message type %q, expecting %q",
reflect.TypeOf(msg).String(), messageType.String())
}
return msg, nil
}
}

// AwaitGetBlockMessage waits for a GetBlockMessage from the node for the specified timeout and
// returns the requested block ID.
func (c *NetClient) AwaitGetBlockMessage(timeout time.Duration) (proto.BlockID, error) {
msg, err := c.AwaitMessage(reflect.TypeOf(&proto.GetBlockMessage{}), timeout)
if err != nil {
return proto.BlockID{}, err
}
getBlockMessage, ok := msg.(*proto.GetBlockMessage)
if !ok {
return proto.BlockID{}, fmt.Errorf("failed to cast message of type %q to GetBlockMessage",
reflect.TypeOf(msg).String())
}
return getBlockMessage.BlockID, nil
}

// AwaitScoreMessage waits for a ScoreMessage from the node for the specified timeout and returns the received score.
func (c *NetClient) AwaitScoreMessage(timeout time.Duration) (*big.Int, error) {
msg, err := c.AwaitMessage(reflect.TypeOf(&proto.ScoreMessage{}), timeout)
if err != nil {
return nil, err
}
scoreMessage, ok := msg.(*proto.ScoreMessage)
if !ok {
return nil, fmt.Errorf("failed to cast message of type %q to ScoreMessage", reflect.TypeOf(msg).String())
}
score := new(big.Int).SetBytes(scoreMessage.Score)
return score, nil
}

// AwaitMicroblockRequest waits for a MicroBlockRequestMessage from the node for the specified timeout and
// returns the received block ID.
func (c *NetClient) AwaitMicroblockRequest(timeout time.Duration) (proto.BlockID, error) {
msg, err := c.AwaitMessage(reflect.TypeOf(&proto.MicroBlockRequestMessage{}), timeout)
if err != nil {
return proto.BlockID{}, err
}
mbr, ok := msg.(*proto.MicroBlockRequestMessage)
if !ok {
return proto.BlockID{}, fmt.Errorf("failed to cast message of type %q to MicroBlockRequestMessage",
reflect.TypeOf(msg).String())
}
r, err := proto.NewBlockIDFromBytes(mbr.TotalBlockSig)
if err != nil {
return proto.BlockID{}, err
}
return r, nil
}

func (c *NetClient) reconnect() {
c.t.Logf("Reconnecting to %q", c.s.RemoteAddr().String())
conn, err := net.Dial("tcp", c.s.RemoteAddr().String())
Expand Down Expand Up @@ -174,10 +265,13 @@ type handler struct {
peers []proto.PeerInfo
t testing.TB
client *NetClient
queue []reflect.Type
ch chan proto.Message
}

func newHandler(t testing.TB, peers []proto.PeerInfo) *handler {
return &handler{t: t, peers: peers}
ch := make(chan proto.Message, 1)
return &handler{t: t, peers: peers, ch: ch}
}

func (h *handler) OnReceive(s *networking.Session, r io.Reader) {
Expand All @@ -195,14 +289,22 @@ func (h *handler) OnReceive(s *networking.Session, r io.Reader) {
}
switch msg.(type) { // Only reply with peers on GetPeersMessage.
case *proto.GetPeersMessage:
h.t.Logf("Received GetPeersMessage from %q", s.RemoteAddr())
rpl := &proto.PeersMessage{Peers: h.peers}
if _, sErr := rpl.WriteTo(s); sErr != nil {
h.t.Logf("Failed to send peers message: %v", sErr)
h.t.FailNow()
return
}
default:
if len(h.queue) == 0 { // No messages to wait for.
return
}
et := h.queue[0]
if reflect.TypeOf(msg) == et {
h.t.Logf("Received expected message of type %q", reflect.TypeOf(msg).String())
h.queue = h.queue[1:] // Pop the expected type.
h.ch <- msg
nickeskov marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

Expand All @@ -216,3 +318,25 @@ func (h *handler) OnClose(s *networking.Session) {
h.client.reconnect()
}
}

func (h *handler) waitFor(messageType reflect.Type) error {
if messageType == nil {
return errors.New("nil message type")
}
if messageType == reflect.TypeOf(proto.GetPeersMessage{}) {
return errors.New("cannot wait for GetPeersMessage")
}
h.queue = append(h.queue, messageType)
return nil
}

func (h *handler) receiveChan() <-chan proto.Message {
return h.ch
}
nickeskov marked this conversation as resolved.
Show resolved Hide resolved

func (h *handler) close() {
if h.ch != nil {
close(h.ch)
h.ch = nil
}
}
10 changes: 5 additions & 5 deletions itests/clients/node_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ func NewNodesClients(ctx context.Context, t *testing.T, goPorts, scalaPorts *d.P
}

func (c *NodesClients) SendStartMessage(t *testing.T) {
c.GoClient.HTTPClient.PrintMsg(t, "------------- Start test: "+t.Name()+" -------------")
c.ScalaClient.HTTPClient.PrintMsg(t, "------------- Start test: "+t.Name()+" -------------")
c.GoClient.SendStartMessage(t)
c.ScalaClient.SendStartMessage(t)
}

func (c *NodesClients) SendEndMessage(t *testing.T) {
c.GoClient.HTTPClient.PrintMsg(t, "------------- End test: "+t.Name()+" -------------")
c.ScalaClient.HTTPClient.PrintMsg(t, "------------- End test: "+t.Name()+" -------------")
c.GoClient.SendEndMessage(t)
c.ScalaClient.SendEndMessage(t)
}

func (c *NodesClients) StateHashCmp(t *testing.T, height uint64) (*proto.StateHash, *proto.StateHash, bool) {
Expand Down Expand Up @@ -242,7 +242,7 @@ func (c *NodesClients) SynchronizedWavesBalances(
ctx, cancel := context.WithTimeout(context.Background(), synchronizedBalancesTimeout)
defer cancel()

t.Logf("Initial balacnces request")
t.Logf("Initial balances request")
sbs, err := c.requestAvailableBalancesForAddresses(ctx, addresses)
if err != nil {
t.Logf("Errors while requesting balances: %v", err)
Expand Down
17 changes: 17 additions & 0 deletions itests/clients/universal_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,20 @@ func NewNodeUniversalClient(
Connection: NewNetClient(ctx, t, impl, netPort, peers),
}
}

func (c *NodeUniversalClient) SendStartMessage(t *testing.T) {
c.HTTPClient.PrintMsg(t, "------------- Start test: "+t.Name()+" -------------")
}

func (c *NodeUniversalClient) SendEndMessage(t *testing.T) {
c.HTTPClient.PrintMsg(t, "------------- End test: "+t.Name()+" -------------")
}

func (c *NodeUniversalClient) Handshake() {
c.Connection.SendHandshake()
}

func (c *NodeUniversalClient) Close(t testing.TB) {
c.GRPCClient.Close(t)
c.Connection.Close()
}
88 changes: 15 additions & 73 deletions itests/config/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,21 +61,19 @@ func (ra *RewardAddresses) AddressesAfter21() []proto.WavesAddress {
return []proto.WavesAddress{}
}

// BlockchainOption is a function type that allows to set additional parameters to BlockchainConfig.
type BlockchainOption func(*BlockchainConfig) error

// BlockchainConfig is a struct that contains settings for blockchain.
// This configuration is used both for building Scala and Go configuration files.
// Also, it's used to produce a Docker container run configurations for both nodes.
type BlockchainConfig struct {
accounts []AccountInfo
supported []int16
desiredReward uint64

Settings *settings.BlockchainSettings
Features []FeatureInfo
RewardAddresses RewardAddresses
EnableScalaMining bool
accounts []AccountInfo
supported []int16
desiredReward uint64
disableGoMining bool
disableScalaMining bool

Settings *settings.BlockchainSettings
Features []FeatureInfo
RewardAddresses RewardAddresses
}

func NewBlockchainConfig(options ...BlockchainOption) (*BlockchainConfig, error) {
Expand Down Expand Up @@ -174,71 +172,15 @@ func (c *BlockchainConfig) TestConfig() TestConfig {
}
}

// WithFeatureSettingFromFile is a BlockchainOption that allows to set feature settings from configuration file.
// Feature settings configuration file is a JSON file with the structure of `featureSettings`.
func WithFeatureSettingFromFile(path ...string) BlockchainOption {
return func(cfg *BlockchainConfig) error {
fs, err := NewFeatureSettingsFromFile(path...)
if err != nil {
return errors.Wrap(err, "failed to modify features settings")
}
cfg.supported = fs.SupportedFeatures
if ftErr := cfg.UpdatePreactivatedFeatures(fs.PreactivatedFeatures); ftErr != nil {
return errors.Wrap(ftErr, "failed to modify preactivated features")
}
return nil
}
}

// WithPaymentsSettingFromFile is a BlockchainOption that allows to set payment settings from configuration file.
// Payment settings configuration file is a JSON file with the structure of `paymentSettings`.
func WithPaymentsSettingFromFile(path ...string) BlockchainOption {
return func(cfg *BlockchainConfig) error {
fs, err := NewPaymentSettingsFromFile(path...)
if err != nil {
return errors.Wrap(err, "failed to modify payments settings")
}
cfg.Settings.PaymentsFixAfterHeight = fs.PaymentsFixAfterHeight
cfg.Settings.InternalInvokePaymentsValidationAfterHeight = fs.InternalInvokePaymentsValidationAfterHeight
cfg.Settings.InternalInvokeCorrectFailRejectBehaviourAfterHeight =
fs.InternalInvokeCorrectFailRejectBehaviourAfterHeight
cfg.Settings.InvokeNoZeroPaymentsAfterHeight = fs.InvokeNoZeroPaymentsAfterHeight
return nil
}
}

// WithRewardSettingFromFile is a BlockchainOption that allows to set reward settings from configuration file.
// Reward settings configuration file is a JSON file with the structure of `rewardSettings`.
func WithRewardSettingFromFile(path ...string) BlockchainOption {
return func(cfg *BlockchainConfig) error {
rs, err := NewRewardSettingsFromFile(path...)
if err != nil {
return errors.Wrap(err, "failed to modify reward settings")
}
cfg.Settings.InitialBlockReward = rs.InitialBlockReward
cfg.Settings.BlockRewardIncrement = rs.BlockRewardIncrement
cfg.Settings.BlockRewardVotingPeriod = rs.BlockRewardVotingPeriod
cfg.Settings.BlockRewardTermAfter20 = rs.BlockRewardTermAfter20
cfg.Settings.BlockRewardTerm = rs.BlockRewardTerm
cfg.Settings.MinXTNBuyBackPeriod = rs.MinXTNBuyBackPeriod

ras, err := NewRewardAddresses(rs.DaoAddress, rs.XtnBuybackAddress)
if err != nil {
return errors.Wrap(err, "failed to modify reward settings")
}
cfg.RewardAddresses = ras
cfg.Settings.RewardAddresses = ras.Addresses()
cfg.Settings.RewardAddressesAfter21 = ras.AddressesAfter21()
cfg.desiredReward = rs.DesiredBlockReward
return nil
}
func (c *BlockchainConfig) DisableGoMiningString() string {
return strconv.FormatBool(c.disableGoMining)
}

func WithScalaMining() BlockchainOption {
return func(cfg *BlockchainConfig) error {
cfg.EnableScalaMining = true
return nil
func (c *BlockchainConfig) EnableScalaMiningString() string {
if c.disableScalaMining {
return "no"
}
return "yes"
}

func safeNow() uint64 {
Expand Down
Loading
Loading