diff --git a/cmd/cmd.go b/cmd/cmd.go index a1862e748..e5dbc5916 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -401,7 +401,11 @@ func StartNode(workingDir string, passwordFetcher func(*wallet.Wallet) (string, } validatorAddrs := make([]string, conf.Node.NumValidators) for i := 0; i < conf.Node.NumValidators; i++ { - validatorAddrs[i] = addrLabels[i].Address + valAddr, _ := crypto.AddressFromString(addrLabels[i].Address) + if !valAddr.IsValidatorAddress() { + return nil, nil, fmt.Errorf("invalid validator address: %s", addrLabels[i].Address) + } + validatorAddrs[i] = valAddr.String() } valKeys := make([]*bls.ValidatorKey, conf.Node.NumValidators) password, ok := passwordFetcher(walletInstance) @@ -417,19 +421,26 @@ func StartNode(workingDir string, passwordFetcher func(*wallet.Wallet) (string, } // Create reward addresses - rewardAddrs := make([]crypto.Address, conf.Node.NumValidators) + rewardAddrs := make([]crypto.Address, 0, conf.Node.NumValidators) if len(conf.Node.RewardAddresses) != 0 { - for i, addrStr := range conf.Node.RewardAddresses { - rewardAddrs[i], _ = crypto.AddressFromString(addrStr) + for _, addrStr := range conf.Node.RewardAddresses { + addr, _ := crypto.AddressFromString(addrStr) + rewardAddrs = append(rewardAddrs, addr) } } else { - if len(addrLabels) < 2*conf.Node.NumValidators { - return nil, nil, fmt.Errorf("not enough addresses in wallet") - } - for i := 0; i < conf.Node.NumValidators; i++ { - rewardAddrs[i], _ = crypto.AddressFromString(addrLabels[conf.Node.NumValidators+i].Address) + for i := conf.Node.NumValidators; i < len(addrLabels); i++ { + addr, _ := crypto.AddressFromString(addrLabels[i].Address) + if addr.IsAccountAddress() { + rewardAddrs = append(rewardAddrs, addr) + if len(rewardAddrs) == conf.Node.NumValidators { + break + } + } } } + if len(rewardAddrs) != conf.Node.NumValidators { + return nil, nil, fmt.Errorf("not enough addresses in wallet") + } nodeInstance, err := node.NewNode(gen, conf, valKeys, rewardAddrs) if err != nil { diff --git a/config/config.go b/config/config.go index b561cf483..3d8bc9ddf 100644 --- a/config/config.go +++ b/config/config.go @@ -55,15 +55,20 @@ func (conf *NodeConfig) BasicCheck() error { return errors.Errorf(errors.ErrInvalidConfig, "number of validators must be between 1 and 32") } - if len(conf.RewardAddresses) != conf.NumValidators { + if len(conf.RewardAddresses) > 0 && + len(conf.RewardAddresses) != conf.NumValidators { return errors.Errorf(errors.ErrInvalidConfig, "reward addresses should be %v", conf.NumValidators) } - for _, addr := range conf.RewardAddresses { - _, err := crypto.AddressFromString(addr) + for _, addrStr := range conf.RewardAddresses { + addr, err := crypto.AddressFromString(addrStr) if err != nil { return errors.Errorf(errors.ErrInvalidConfig, "invalid reward address: %v", err.Error()) } + + if !addr.IsAccountAddress() { + return errors.Errorf(errors.ErrInvalidConfig, "reward address is not an account address: %s", addrStr) + } } return nil } @@ -118,8 +123,8 @@ func SaveTestnetConfig(path string, numValidators int) error { conf.Network.Bootstrap.MaxThreshold = 8 conf.Network.EnableRelay = true conf.Network.RelayAddrs = []string{ - "/ip4/139.162.153.10/udp/4002/quic/p2p/12D3KooWNR79jqHVVNhNVrqnDbxbJJze4VjbEsBjZhz6mkvinHAN", "/ip4/139.162.153.10/tcp/4002/p2p/12D3KooWNR79jqHVVNhNVrqnDbxbJJze4VjbEsBjZhz6mkvinHAN", + "/ip4/139.162.153.10/udp/4002/quic/p2p/12D3KooWNR79jqHVVNhNVrqnDbxbJJze4VjbEsBjZhz6mkvinHAN", "/ip6/2a01:7e01::f03c:93ff:fed2:84c5/tcp/4002/p2p/12D3KooWNR79jqHVVNhNVrqnDbxbJJze4VjbEsBjZhz6mkvinHAN", "/ip6/2a01:7e01::f03c:93ff:fed2:84c5/udp/4002/quic/p2p/12D3KooWNR79jqHVVNhNVrqnDbxbJJze4VjbEsBjZhz6mkvinHAN", "/ip4/94.101.184.118/tcp/4002/p2p/12D3KooWCRHn8vjrKNBEQcut8uVCYX5q77RKidPaE6iMK31qEVHb", @@ -131,7 +136,7 @@ func SaveTestnetConfig(path string, numValidators int) error { conf.GRPC.Gateway.Listen = "[::]:8080" conf.HTTP.Enable = false conf.HTTP.Listen = "[::]:80" - conf.Nanomsg.Enable = true + conf.Nanomsg.Enable = false conf.Nanomsg.Listen = "tcp://127.0.0.1:40799" return util.WriteFile(path, conf.toTOML()) @@ -187,6 +192,9 @@ func LoadFromFile(file string, strict bool) (*Config, error) { // BasicCheck performs basic checks on the configuration. func (conf *Config) BasicCheck() error { + if err := conf.Node.BasicCheck(); err != nil { + return err + } if err := conf.Store.BasicCheck(); err != nil { return err } diff --git a/config/config_test.go b/config/config_test.go index 564c39ed3..fabbce552 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -111,6 +111,16 @@ func TestNodeConfigBasicCheck(t *testing.T) { assert.Error(t, conf.BasicCheck()) }) + t.Run("validator address as reward address", func(t *testing.T) { + conf := DefaultNodeConfig() + conf.NumValidators = 1 + conf.RewardAddresses = []string{ + ts.RandValAddress().String(), + } + + assert.Error(t, conf.BasicCheck()) + }) + t.Run("ok", func(t *testing.T) { conf := DefaultNodeConfig() conf.NumValidators = 2 @@ -121,4 +131,12 @@ func TestNodeConfigBasicCheck(t *testing.T) { assert.NoError(t, conf.BasicCheck()) }) + + t.Run("no reward addresses inside config, Ok", func(t *testing.T) { + conf := DefaultNodeConfig() + conf.NumValidators = 2 + conf.RewardAddresses = []string{} + + assert.NoError(t, conf.BasicCheck()) + }) } diff --git a/sync/firewall/firewall.go b/sync/firewall/firewall.go index b57e1e28e..d5441cf96 100644 --- a/sync/firewall/firewall.go +++ b/sync/firewall/firewall.go @@ -48,7 +48,8 @@ func (f *Firewall) OpenGossipBundle(data []byte, source peer.ID, from peer.ID) * bdl, err := f.openBundle(bytes.NewReader(data), source) if err != nil { - f.logger.Warn("firewall: unable to open a gossip bundle", "error", err) + f.logger.Warn("firewall: unable to open a gossip bundle", + "error", err, "bundle", bdl) f.closeConnection(from) return nil } @@ -62,7 +63,8 @@ func (f *Firewall) OpenGossipBundle(data []byte, source peer.ID, from peer.ID) * func (f *Firewall) OpenStreamBundle(r io.Reader, from peer.ID) *bundle.Bundle { bdl, err := f.openBundle(r, from) if err != nil { - f.logger.Warn("firewall: unable to open a stream bundle", "error", err) + f.logger.Warn("firewall: unable to open a stream bundle", + "error", err, "bundle", bdl) f.closeConnection(from) return nil } @@ -91,7 +93,7 @@ func (f *Firewall) openBundle(r io.Reader, source peer.ID) (*bundle.Bundle, erro if err := f.checkBundle(bdl, source); err != nil { f.peerSet.IncreaseInvalidBundlesCounter(source) - return nil, err + return bdl, err } return bdl, nil diff --git a/sync/firewall/firewall_test.go b/sync/firewall/firewall_test.go index 47f15f2da..556eb3a98 100644 --- a/sync/firewall/firewall_test.go +++ b/sync/firewall/firewall_test.go @@ -112,6 +112,16 @@ func TestGossipMessage(t *testing.T) { assert.True(t, td.network.IsClosed(td.badPeerID)) }) + t.Run("Message is nil => should close the connection", func(t *testing.T) { + td := setup(t) + + assert.False(t, td.network.IsClosed(td.badPeerID)) + assert.False(t, td.network.IsClosed(td.unknownPeerID)) + assert.Nil(t, td.firewall.OpenGossipBundle(nil, td.badPeerID, td.unknownPeerID)) + assert.True(t, td.network.IsClosed(td.badPeerID)) + assert.True(t, td.network.IsClosed(td.unknownPeerID)) + }) + t.Run("Message source: bad, from: unknown => should close the connection", func(t *testing.T) { td := setup(t) @@ -151,6 +161,14 @@ func TestGossipMessage(t *testing.T) { } func TestStreamMessage(t *testing.T) { + t.Run("Message is nil => should close the connection", func(t *testing.T) { + td := setup(t) + + assert.False(t, td.network.IsClosed(td.badPeerID)) + assert.Nil(t, td.firewall.OpenStreamBundle(bytes.NewReader(nil), td.badPeerID)) + assert.True(t, td.network.IsClosed(td.badPeerID)) + }) + t.Run("Message source: bad => should close the connection", func(t *testing.T) { td := setup(t) diff --git a/sync/handler_blocks_request.go b/sync/handler_blocks_request.go index a4a5fc75c..47ee6f298 100644 --- a/sync/handler_blocks_request.go +++ b/sync/handler_blocks_request.go @@ -95,8 +95,9 @@ func (handler *blocksRequestHandler) PrepareBundle(m message.Message) *bundle.Bu func (handler *blocksRequestHandler) respond(msg *message.BlocksResponseMessage, to peer.ID) error { if msg.ResponseCode == message.ResponseCodeRejected { - handler.logger.Warn("rejecting block request message", "message", msg, + handler.logger.Error("rejecting block request message", "message", msg, "to", to.ShortString(), "reason", msg.Reason) + handler.network.CloseConnection(to) } else { handler.logger.Info("responding block request message", "message", msg, "to", to.ShortString()) diff --git a/types/block/block_test.go b/types/block/block_test.go index e6de1b60c..30105abf4 100644 --- a/types/block/block_test.go +++ b/types/block/block_test.go @@ -45,23 +45,24 @@ func TestBasicCheck(t *testing.T) { err := b.BasicCheck() assert.ErrorIs(t, err, block.BasicCheckError{ - Reason: "invalid certificate: certificate basic check failed: height is not positive: 0", + Reason: "invalid certificate: height is not positive: 0", }) }) - //TODO fix me later - //t.Run("Invalid transaction", func(t *testing.T) { - // b0 := ts.GenerateTestBlock() - // trxs0 := b0.Transactions() - // invalidValKey := ts.RandValKey() - // invalidValKey.Sign(trxs0[0].SignBytes()) - // b := block.NewBlock(b0.Header(), b0.PrevCertificate(), trxs0) - // - // err := b.BasicCheck() - // assert.ErrorIs(t, err, block.BasicCheckError{ - // Reason: "invalid transaction: transaction basic check failed: invalid address: invalid address", - // }) - //}) + t.Run("Invalid transaction", func(t *testing.T) { + b0 := ts.GenerateTestBlock() + trxs0 := b0.Transactions() + invalidValKey := ts.RandValKey() + invSig := invalidValKey.Sign(trxs0[0].SignBytes()) + trxs0[0].SetSignature(invSig) + + b := block.NewBlock(b0.Header(), b0.PrevCertificate(), trxs0) + + err := b.BasicCheck() + assert.ErrorIs(t, err, block.BasicCheckError{ + Reason: "invalid transaction: invalid signature", + }) + }) t.Run("Invalid state root hash", func(t *testing.T) { d := ts.DecodingHex( diff --git a/types/block/errors.go b/types/block/errors.go index cbe42f7bd..afbf0c5bf 100644 --- a/types/block/errors.go +++ b/types/block/errors.go @@ -6,5 +6,5 @@ type BasicCheckError struct { } func (e BasicCheckError) Error() string { - return "block basic check failed: " + e.Reason + return e.Reason } diff --git a/types/certificate/errors.go b/types/certificate/errors.go index c5a08b563..1453511ac 100644 --- a/types/certificate/errors.go +++ b/types/certificate/errors.go @@ -13,7 +13,7 @@ type BasicCheckError struct { } func (e BasicCheckError) Error() string { - return "certificate basic check failed: " + e.Reason + return e.Reason } // UnexpectedHeightError is returned when the height of the certificate diff --git a/types/tx/errors.go b/types/tx/errors.go index 154d64870..c5e195efb 100644 --- a/types/tx/errors.go +++ b/types/tx/errors.go @@ -8,7 +8,7 @@ type BasicCheckError struct { } func (e BasicCheckError) Error() string { - return "transaction basic check failed: " + e.Reason + return e.Reason } // InvalidPayloadTypeError is returned when the payload type is not valid. diff --git a/types/tx/payload/bond.go b/types/tx/payload/bond.go index f0fa01e47..fdf745714 100644 --- a/types/tx/payload/bond.go +++ b/types/tx/payload/bond.go @@ -31,13 +31,13 @@ func (p *BondPayload) Value() int64 { func (p *BondPayload) BasicCheck() error { if !p.From.IsAccountAddress() { return BasicCheckError{ - Reason: "sender is not an account address", + Reason: "sender is not an account address: " + p.From.ShortString(), } } if !p.To.IsValidatorAddress() { return BasicCheckError{ - Reason: "receiver is not a validator address", + Reason: "receiver is not a validator address: " + p.To.ShortString(), } } diff --git a/types/tx/payload/bond_test.go b/types/tx/payload/bond_test.go index 804672425..661bcbacf 100644 --- a/types/tx/payload/bond_test.go +++ b/types/tx/payload/bond_test.go @@ -93,7 +93,7 @@ func TestBondDecoding(t *testing.T) { value: 0x200000, readErr: nil, basicErr: BasicCheckError{ - Reason: "sender is not an account address", + Reason: "sender is not an account address: pc1pqgpsgpgx", }, }, { @@ -110,7 +110,7 @@ func TestBondDecoding(t *testing.T) { value: 0x200000, readErr: nil, basicErr: BasicCheckError{ - Reason: "receiver is not a validator address", + Reason: "receiver is not a validator address: pc1zzgf3g9gk", }, }, { diff --git a/types/tx/payload/errors.go b/types/tx/payload/errors.go index 4ed31abe7..92a5b3be8 100644 --- a/types/tx/payload/errors.go +++ b/types/tx/payload/errors.go @@ -11,5 +11,5 @@ type BasicCheckError struct { } func (e BasicCheckError) Error() string { - return "payload basic check failed: " + e.Reason + return e.Reason } diff --git a/types/tx/payload/sortition.go b/types/tx/payload/sortition.go index e4500030c..a89093aa3 100644 --- a/types/tx/payload/sortition.go +++ b/types/tx/payload/sortition.go @@ -29,7 +29,7 @@ func (p *SortitionPayload) Value() int64 { func (p *SortitionPayload) BasicCheck() error { if !p.Validator.IsValidatorAddress() { return BasicCheckError{ - Reason: "address is not a validator address", + Reason: "address is not a validator address: " + p.Validator.ShortString(), } } diff --git a/types/tx/payload/sortition_test.go b/types/tx/payload/sortition_test.go index 39ec4f33b..f1c161d94 100644 --- a/types/tx/payload/sortition_test.go +++ b/types/tx/payload/sortition_test.go @@ -84,7 +84,7 @@ func TestSortitionDecoding(t *testing.T) { value: 0, readErr: nil, basicErr: BasicCheckError{ - Reason: "address is not a validator address", + Reason: "address is not a validator address: pc1zqgpsgpgx", }, }, } diff --git a/types/tx/payload/transfer.go b/types/tx/payload/transfer.go index eb1c82742..7a8726094 100644 --- a/types/tx/payload/transfer.go +++ b/types/tx/payload/transfer.go @@ -29,12 +29,12 @@ func (p *TransferPayload) Value() int64 { func (p *TransferPayload) BasicCheck() error { if !p.From.IsAccountAddress() { return BasicCheckError{ - Reason: "sender is not an account address", + Reason: "sender is not an account address: " + p.From.ShortString(), } } if !p.To.IsAccountAddress() { return BasicCheckError{ - Reason: "receiver is not an account address", + Reason: "receiver is not an account address: " + p.To.ShortString(), } } return nil diff --git a/types/tx/payload/transfer_test.go b/types/tx/payload/transfer_test.go index b6919fa00..ccc325bd8 100644 --- a/types/tx/payload/transfer_test.go +++ b/types/tx/payload/transfer_test.go @@ -73,7 +73,7 @@ func TestTransferDecoding(t *testing.T) { value: 0x200000, readErr: nil, basicErr: BasicCheckError{ - Reason: "sender is not an account address", + Reason: "sender is not an account address: pc1pqgpsgpgx", }, }, { @@ -89,7 +89,7 @@ func TestTransferDecoding(t *testing.T) { value: 0x200000, readErr: nil, basicErr: BasicCheckError{ - Reason: "receiver is not an account address", + Reason: "receiver is not an account address: pc1pzgf3g9gk", }, }, { diff --git a/types/tx/payload/withdraw.go b/types/tx/payload/withdraw.go index 1d3a77e68..9b652551e 100644 --- a/types/tx/payload/withdraw.go +++ b/types/tx/payload/withdraw.go @@ -30,12 +30,12 @@ func (p *WithdrawPayload) Value() int64 { func (p *WithdrawPayload) BasicCheck() error { if !p.From.IsValidatorAddress() { return BasicCheckError{ - Reason: "sender is not a validator address", + Reason: "sender is not a validator address: " + p.From.ShortString(), } } if !p.To.IsAccountAddress() { return BasicCheckError{ - Reason: "receiver is not an account address", + Reason: "receiver is not an account address: " + p.To.ShortString(), } } diff --git a/types/tx/tx.go b/types/tx/tx.go index 75c0999a6..29e7add76 100644 --- a/types/tx/tx.go +++ b/types/tx/tx.go @@ -189,7 +189,7 @@ func (tx *Tx) checkSignature() error { bs := tx.SignBytes() if err := tx.PublicKey().Verify(bs, tx.Signature()); err != nil { return BasicCheckError{ - Reason: fmt.Sprintf("invalid signature: %s", tx.Signature().String()), + Reason: "invalid signature", } } } diff --git a/types/tx/tx_test.go b/types/tx/tx_test.go index 1c2388708..7f6bebb53 100644 --- a/types/tx/tx_test.go +++ b/types/tx/tx_test.go @@ -119,7 +119,7 @@ func TestBasicCheck(t *testing.T) { err := trx.BasicCheck() assert.ErrorIs(t, err, tx.BasicCheckError{ - Reason: "invalid payload: payload basic check failed: receiver is not an account address", + Reason: "invalid payload: receiver is not an account address: " + invAddr.ShortString(), }) }) @@ -290,7 +290,7 @@ func TestInvalidSignature(t *testing.T) { err := trx.BasicCheck() assert.ErrorIs(t, err, tx.BasicCheckError{ - Reason: "invalid signature: " + trx.Signature().String(), + Reason: "invalid signature", }) }) @@ -314,7 +314,7 @@ func TestInvalidSignature(t *testing.T) { err := trx.BasicCheck() assert.ErrorIs(t, err, tx.BasicCheckError{ - Reason: "invalid signature: " + trx.Signature().String(), + Reason: "invalid signature", }) }) @@ -324,8 +324,7 @@ func TestInvalidSignature(t *testing.T) { err := trx.BasicCheck() assert.ErrorIs(t, err, tx.BasicCheckError{ - Reason: "invalid signature: " + - "c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + Reason: "invalid signature", }) }) diff --git a/types/vote/errors.go b/types/vote/errors.go index e05f26d7c..5930e19d9 100644 --- a/types/vote/errors.go +++ b/types/vote/errors.go @@ -12,7 +12,7 @@ type BasicCheckError struct { } func (e BasicCheckError) Error() string { - return "transaction basic check failed: " + e.Reason + return e.Reason } // InvalidSignerError is returned when the vote signer does not match with the diff --git a/util/logger/logger.go b/util/logger/logger.go index abe99f966..39a9983d9 100644 --- a/util/logger/logger.go +++ b/util/logger/logger.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "os" + "reflect" "github.com/pactus-project/pactus/util" "github.com/rs/zerolog" @@ -82,9 +83,14 @@ func addFields(event *zerolog.Event, keyvals ...interface{}) *zerolog.Event { key = "!INVALID-KEY!" } /// - switch v := keyvals[i+1].(type) { + value := keyvals[i+1] + switch v := value.(type) { case fmt.Stringer: - event.Stringer(key, v) + if isNil(v) { + event.Any(key, v) + } else { + event.Stringer(key, v) + } case error: event.AnErr(key, v) case []byte: @@ -203,3 +209,14 @@ func Fatal(msg string, keyvals ...interface{}) { func Panic(msg string, keyvals ...interface{}) { addFields(log.Panic(), keyvals...).Msg(msg) } + +func isNil(i interface{}) bool { + if i == nil { + return true + } + switch reflect.TypeOf(i).Kind() { + case reflect.Ptr: + return reflect.ValueOf(i).IsNil() + } + return false +} diff --git a/util/logger/logger_test.go b/util/logger/logger_test.go index 6986a03ae..97c078469 100644 --- a/util/logger/logger_test.go +++ b/util/logger/logger_test.go @@ -35,11 +35,11 @@ func TestObjLogger(t *testing.T) { var buf bytes.Buffer l.logger = l.logger.Output(&buf) - l.Trace("a") - l.Debug("b") - l.Info("c") - l.Warn("d") - l.Error("e") + l.Trace("msg") + l.Debug("msg") + l.Info("msg") + l.Warn("msg") + l.Error("msg") out := buf.String() @@ -60,16 +60,19 @@ func TestLogger(t *testing.T) { var buf bytes.Buffer log.Logger = log.Output(&buf) - Trace("a") - Info("b", nil) - Info("b", "a", nil) - Info("c", "b", []byte{1, 2, 3}) - Warn("d", "x") - Error("e", "y", Foo{}) + Trace("msg", "trace", "trace") + Debug("msg", "trace", "trace") + Info("msg", nil) + Info("msg", "a", nil) + Info("msg", "b", []byte{1, 2, 3}) + Warn("msg", "x") + Error("msg", "y", Foo{}) out := buf.String() fmt.Println(out) + assert.NotContains(t, out, "trace") + assert.NotContains(t, out, "debug") assert.Contains(t, out, "foo") assert.Contains(t, out, "010203") assert.Contains(t, out, "!INVALID-KEY!") @@ -81,3 +84,25 @@ func TestLogger(t *testing.T) { assert.Contains(t, out, "warn") assert.Contains(t, out, "error") } + +func TestNilValue(t *testing.T) { + var buf bytes.Buffer + log.Logger = log.Output(&buf) + + foo := new(Foo) + if true { + // to avoid some linting errors + foo = nil + } + + Info("msg", "null", nil) + Info("msg", "error", error(nil)) + Info("msg", "stringer", foo) + + out := buf.String() + + fmt.Println(out) + assert.Contains(t, out, "null") + assert.Contains(t, out, "error") + assert.Contains(t, out, "stringer") +} diff --git a/wallet/errors.go b/wallet/errors.go index 420a5560c..9036a41c4 100644 --- a/wallet/errors.go +++ b/wallet/errors.go @@ -27,12 +27,12 @@ func (e CRCNotMatchError) Error() string { return fmt.Sprintf("crc not matched, expected: %d, got: %d", e.Expected, e.Got) } -// WalletExitsError describes an error in which a wallet exists in the +// ExitsError describes an error in which a wallet exists in the // given path. -type WalletExitsError struct { //nolint +type ExitsError struct { Path string } -func (e WalletExitsError) Error() string { +func (e ExitsError) Error() string { return fmt.Sprintf("a wallet exists at: %s", e.Path) } diff --git a/wallet/wallet.go b/wallet/wallet.go index bef4db561..68df0bd4b 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -68,7 +68,7 @@ func Open(path string, offline bool) (*Wallet, error) { func Create(path, mnemonic, password string, chain genesis.ChainType) (*Wallet, error) { path = util.MakeAbs(path) if util.PathExists(path) { - return nil, WalletExitsError{ + return nil, ExitsError{ Path: path, } } @@ -141,6 +141,12 @@ func (w *Wallet) tryToConnect(addr string) error { return err } + // Check if client is responding + _, err = client.getBlockchainInfo() + if err != nil { + return err + } + w.client = client return nil } diff --git a/wallet/wallet_test.go b/wallet/wallet_test.go index 1e17a912d..60551163d 100644 --- a/wallet/wallet_test.go +++ b/wallet/wallet_test.go @@ -138,7 +138,7 @@ func TestRecoverWallet(t *testing.T) { assert.NoError(t, td.wallet.Save()) _, err := Create(td.wallet.path, mnemonic, password, 0) - assert.ErrorIs(t, err, WalletExitsError{ + assert.ErrorIs(t, err, ExitsError{ Path: td.wallet.path, }) }) diff --git a/www/http/account.go b/www/http/account.go index 441cbe0b6..077504062 100644 --- a/www/http/account.go +++ b/www/http/account.go @@ -19,6 +19,7 @@ func (s *Server) GetAccountHandler(w http.ResponseWriter, r *http.Request) { acc := res.Account tm := newTableMaker() + tm.addRowAccAddress("Address", acc.Address) tm.addRowInt("Number", int(acc.Number)) tm.addRowAmount("Balance", acc.Balance) tm.addRowBytes("Hash", acc.Hash) diff --git a/www/http/blockchain.go b/www/http/blockchain.go index 81774a878..7423d3316 100644 --- a/www/http/blockchain.go +++ b/www/http/blockchain.go @@ -21,14 +21,15 @@ func (s *Server) BlockchainHandler(w http.ResponseWriter, _ *http.Request) { } tm := newTableMaker() - tm.addRowBlockHash("Hash", res.LastBlockHash) - tm.addRowInt("Height", int(res.LastBlockHeight)) + tm.addRowBlockHash("Last Block Hash", res.LastBlockHash) + tm.addRowInt("Last Block Height", int(res.LastBlockHeight)) tm.addRowString("--- Committee", "---") tm.addRowAmount("Total Power", res.TotalPower) tm.addRowAmount("Committee Power", res.CommitteePower) for i, val := range res.CommitteeValidators { tm.addRowInt("--- Validator", i+1) - s.writeValidatorTable(w, val) + tmVal := s.writeValidatorTable(val) + tm.addRowString("", tmVal.html()) } s.writeHTML(w, tm.html()) diff --git a/www/http/validator.go b/www/http/validator.go index a3d73f8c2..82f224d28 100644 --- a/www/http/validator.go +++ b/www/http/validator.go @@ -18,7 +18,8 @@ func (s *Server) GetValidatorHandler(w http.ResponseWriter, r *http.Request) { return } - s.writeValidatorTable(w, res.Validator) + tm := s.writeValidatorTable(res.Validator) + s.writeHTML(w, tm.html()) } // GetValidatorByNumberHandler returns a handler to get validator by number. @@ -39,10 +40,11 @@ func (s *Server) GetValidatorByNumberHandler(w http.ResponseWriter, r *http.Requ return } - s.writeValidatorTable(w, res.Validator) + tm := s.writeValidatorTable(res.Validator) + s.writeHTML(w, tm.html()) } -func (s *Server) writeValidatorTable(w http.ResponseWriter, val *pactus.ValidatorInfo) { +func (s *Server) writeValidatorTable(val *pactus.ValidatorInfo) *tableMaker { tm := newTableMaker() tm.addRowString("Public Key", val.PublicKey) tm.addRowValAddress("Address", val.Address) @@ -53,5 +55,5 @@ func (s *Server) writeValidatorTable(w http.ResponseWriter, val *pactus.Validato tm.addRowInt("UnbondingHeight", int(val.UnbondingHeight)) tm.addRowBytes("Hash", val.Hash) - s.writeHTML(w, tm.html()) + return tm }