From 564c4da8915c65bd4be02b56a1d66338ec058a88 Mon Sep 17 00:00:00 2001 From: Leon1777 <168653957+Leon1777@users.noreply.github.com> Date: Wed, 18 Sep 2024 21:30:37 +0200 Subject: [PATCH 01/13] broadcast wallet transactions in chunks --- cmd/karlsenwallet/send.go | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/cmd/karlsenwallet/send.go b/cmd/karlsenwallet/send.go index fe341986c5..9ce59cfa17 100644 --- a/cmd/karlsenwallet/send.go +++ b/cmd/karlsenwallet/send.go @@ -75,23 +75,29 @@ func send(conf *sendConfig) error { signedTransactions[i] = signedTransaction } - if len(signedTransactions) > 1 { - fmt.Printf("Broadcasting %d transactions\n", len(signedTransactions)) - } - + fmt.Printf("Broadcasting %d transaction(s)\n", len(signedTransactions)) // Since we waited for user input when getting the password, which could take unbound amount of time - // create a new context for broadcast, to reset the timeout. broadcastCtx, broadcastCancel := context.WithTimeout(context.Background(), daemonTimeout) defer broadcastCancel() - response, err := daemonClient.Broadcast(broadcastCtx, &pb.BroadcastRequest{Transactions: signedTransactions}) - if err != nil { - return err - } - fmt.Println("Transactions were sent successfully") - fmt.Println("Transaction ID(s): ") - for _, txID := range response.TxIDs { - fmt.Printf("\t%s\n", txID) + const chunkSize = 100 // To avoid sending a message bigger than the gRPC max message size, we split it to chunks + for offset := 0; offset < len(signedTransactions); offset += chunkSize { + end := len(signedTransactions) + if offset+chunkSize <= len(signedTransactions) { + end = offset + chunkSize + } + + chunk := signedTransactions[offset:end] + response, err := daemonClient.Broadcast(broadcastCtx, &pb.BroadcastRequest{Transactions: chunk}) + if err != nil { + return err + } + fmt.Printf("Broadcasted %d transaction(s) (broadcasted %.2f%% of the transactions so far)\n", len(chunk), 100*float64(end)/float64(len(signedTransactions))) + fmt.Println("Broadcasted Transaction ID(s): ") + for _, txID := range response.TxIDs { + fmt.Printf("\t%s\n", txID) + } } if conf.Verbose { From 695bed8f17480f0ec156c326b7835c1c98a9ecd2 Mon Sep 17 00:00:00 2001 From: Leon1777 <168653957+Leon1777@users.noreply.github.com> Date: Wed, 18 Sep 2024 21:34:31 +0200 Subject: [PATCH 02/13] adapt wallet UTXO selection to dust patch * if the tx has change and thus so 2 outputs, try having at least 2 inputs as well (in order to not be slowed down by dust patch) --- .../daemon/server/create_unsigned_transaction.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/karlsenwallet/daemon/server/create_unsigned_transaction.go b/cmd/karlsenwallet/daemon/server/create_unsigned_transaction.go index 2df64c3c0c..5c85c4ec1d 100644 --- a/cmd/karlsenwallet/daemon/server/create_unsigned_transaction.go +++ b/cmd/karlsenwallet/daemon/server/create_unsigned_transaction.go @@ -135,7 +135,11 @@ func (s *server) selectUTXOs(spendAmount uint64, isSendAll bool, feePerInput uin fee := feePerInput * uint64(len(selectedUTXOs)) totalSpend := spendAmount + fee - if !isSendAll && totalValue >= totalSpend { + // Two break cases (if not send all): + // 1. totalValue == totalSpend, so there's no change needed -> number of outputs = 1, so a single input is sufficient + // 2. totalValue > totalSpend, so there will be change and 2 outputs, therefor in order to not struggle with new dust + // rules we try and find at least 2 inputs (even though the next one is not necessary in terms of spend value) + if !isSendAll && (totalValue == totalSpend || (totalValue > totalSpend && len(selectedUTXOs) > 1)) { break } } From 034041b1547cb03c7130d179883edfd0d24de12f Mon Sep 17 00:00:00 2001 From: Leon1777 <168653957+Leon1777@users.noreply.github.com> Date: Wed, 18 Sep 2024 22:37:36 +0200 Subject: [PATCH 03/13] add options to see wallet and wallet daemon versions --- cmd/karlsenwallet/config.go | 16 + .../daemon/pb/karlsenwalletd.pb.go | 317 ++++++++++++------ .../daemon/pb/karlsenwalletd.proto | 8 + .../daemon/pb/karlsenwalletd_grpc.pb.go | 92 ++++- cmd/karlsenwallet/daemon/server/balance.go | 2 + cmd/karlsenwallet/daemon/server/server.go | 3 + cmd/karlsenwallet/daemon/server/version.go | 17 + cmd/karlsenwallet/get_daemon_version.go | 27 ++ cmd/karlsenwallet/main.go | 9 +- cmd/karlsenwallet/version.go | 16 + 10 files changed, 391 insertions(+), 116 deletions(-) create mode 100644 cmd/karlsenwallet/daemon/server/version.go create mode 100644 cmd/karlsenwallet/get_daemon_version.go create mode 100644 cmd/karlsenwallet/version.go diff --git a/cmd/karlsenwallet/config.go b/cmd/karlsenwallet/config.go index 643838c9a2..b3df8030f2 100644 --- a/cmd/karlsenwallet/config.go +++ b/cmd/karlsenwallet/config.go @@ -22,6 +22,8 @@ const ( newAddressSubCmd = "new-address" dumpUnencryptedDataSubCmd = "dump-unencrypted-data" startDaemonSubCmd = "start-daemon" + versionSubCmd = "version" + getDaemonVersionSubCmd = "get-daemon-version" ) const ( @@ -30,6 +32,7 @@ const ( ) type configFlags struct { + ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"` config.NetworkFlags } @@ -130,6 +133,13 @@ type dumpUnencryptedDataConfig struct { config.NetworkFlags } +type versionConfig struct { +} + +type getDaemonVersionConfig struct { + DaemonAddress string `long:"daemonaddress" short:"d" description:"Wallet daemon server to connect to"` +} + func parseCommandLine() (subCommand string, config interface{}) { cfg := &configFlags{} parser := flags.NewParser(cfg, flags.PrintErrors|flags.HelpFlag) @@ -186,6 +196,9 @@ func parseCommandLine() (subCommand string, config interface{}) { Listen: defaultListen, } parser.AddCommand(startDaemonSubCmd, "Start the wallet daemon", "Start the wallet daemon", startDaemonConf) + parser.AddCommand(versionSubCmd, "Get the wallet version", "Get the wallet version", &versionConfig{}) + getDaemonVersionConf := &getDaemonVersionConfig{DaemonAddress: defaultListen} + parser.AddCommand(getDaemonVersionSubCmd, "Get the wallet daemon version", "Get the wallet daemon version", getDaemonVersionConf) _, err := parser.Parse() if err != nil { @@ -291,6 +304,9 @@ func parseCommandLine() (subCommand string, config interface{}) { printErrorAndExit(err) } config = startDaemonConf + case versionSubCmd: + case getDaemonVersionSubCmd: + config = getDaemonVersionConf } return parser.Command.Active.Name, config diff --git a/cmd/karlsenwallet/daemon/pb/karlsenwalletd.pb.go b/cmd/karlsenwallet/daemon/pb/karlsenwalletd.pb.go index 1b573b2470..f65eb8be1d 100644 --- a/cmd/karlsenwallet/daemon/pb/karlsenwalletd.pb.go +++ b/cmd/karlsenwallet/daemon/pb/karlsenwalletd.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 -// protoc v4.25.2 +// protoc-gen-go v1.34.2 +// protoc v3.12.4 // source: karlsenwalletd.proto package pb @@ -1242,6 +1242,91 @@ func (x *SignResponse) GetSignedTransactions() [][]byte { return nil } +type GetVersionRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetVersionRequest) Reset() { + *x = GetVersionRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_karlsenwalletd_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetVersionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetVersionRequest) ProtoMessage() {} + +func (x *GetVersionRequest) ProtoReflect() protoreflect.Message { + mi := &file_karlsenwalletd_proto_msgTypes[23] + 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 GetVersionRequest.ProtoReflect.Descriptor instead. +func (*GetVersionRequest) Descriptor() ([]byte, []int) { + return file_karlsenwalletd_proto_rawDescGZIP(), []int{23} +} + +type GetVersionResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` +} + +func (x *GetVersionResponse) Reset() { + *x = GetVersionResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_karlsenwalletd_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetVersionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetVersionResponse) ProtoMessage() {} + +func (x *GetVersionResponse) ProtoReflect() protoreflect.Message { + mi := &file_karlsenwalletd_proto_msgTypes[24] + 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 GetVersionResponse.ProtoReflect.Descriptor instead. +func (*GetVersionResponse) Descriptor() ([]byte, []int) { + return file_karlsenwalletd_proto_rawDescGZIP(), []int{24} +} + +func (x *GetVersionResponse) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + var File_karlsenwalletd_proto protoreflect.FileDescriptor var file_karlsenwalletd_proto_rawDesc = []byte{ @@ -1372,65 +1457,75 @@ var file_karlsenwalletd_proto_rawDesc = []byte{ 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x12, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x12, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x32, 0xda, 0x06, 0x0a, 0x0e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, - 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x12, 0x55, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, - 0x6e, 0x63, 0x65, 0x12, 0x21, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, - 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, - 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x82, 0x01, 0x0a, - 0x19, 0x47, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x70, 0x65, 0x6e, - 0x64, 0x61, 0x62, 0x6c, 0x65, 0x55, 0x54, 0x58, 0x4f, 0x73, 0x12, 0x30, 0x2e, 0x6b, 0x61, 0x72, - 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x45, - 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, - 0x55, 0x54, 0x58, 0x4f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x6b, - 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x47, 0x65, - 0x74, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, - 0x6c, 0x65, 0x55, 0x54, 0x58, 0x4f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x85, 0x01, 0x0a, 0x1a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x6e, 0x73, 0x69, - 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x31, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, - 0x64, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, - 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x6e, 0x73, 0x69, 0x67, - 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5e, 0x0a, 0x0d, 0x53, 0x68, 0x6f, - 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x24, 0x2e, 0x6b, 0x61, 0x72, - 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x53, 0x68, 0x6f, 0x77, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x25, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, - 0x64, 0x2e, 0x53, 0x68, 0x6f, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x55, 0x0a, 0x0a, 0x4e, 0x65, 0x77, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x21, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, - 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6b, 0x61, 0x72, - 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x4e, 0x65, 0x77, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x4f, 0x0a, 0x08, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x1f, 0x2e, 0x6b, - 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x53, 0x68, - 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, - 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x53, - 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x52, 0x0a, 0x09, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x12, 0x20, - 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, - 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x21, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, - 0x64, 0x2e, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x1b, 0x2e, - 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x53, - 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6b, 0x61, 0x72, - 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x53, 0x65, 0x6e, 0x64, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x04, 0x53, 0x69, - 0x67, 0x6e, 0x12, 0x1b, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, - 0x65, 0x74, 0x64, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x6e, 0x73, 0x22, 0x13, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2e, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x32, 0xb1, 0x07, 0x0a, 0x0e, 0x6b, 0x61, 0x72, 0x6c, + 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x12, 0x55, 0x0a, 0x0a, 0x47, 0x65, + 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x21, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, + 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, + 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6b, 0x61, + 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x47, 0x65, 0x74, + 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x82, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x53, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x55, 0x54, 0x58, 0x4f, 0x73, 0x12, + 0x30, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, + 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x70, 0x65, 0x6e, + 0x64, 0x61, 0x62, 0x6c, 0x65, 0x55, 0x54, 0x58, 0x4f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x31, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x70, + 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x55, 0x54, 0x58, 0x4f, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x85, 0x01, 0x0a, 0x1a, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x31, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x6e, 0x73, + 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, + 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5e, + 0x0a, 0x0d, 0x53, 0x68, 0x6f, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, + 0x24, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, + 0x2e, 0x53, 0x68, 0x6f, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x53, 0x68, 0x6f, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x55, + 0x0a, 0x0a, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x21, 0x2e, 0x6b, + 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x4e, 0x65, + 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x22, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, + 0x2e, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4f, 0x0a, 0x08, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, + 0x6e, 0x12, 0x1f, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x64, 0x2e, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x64, 0x2e, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x52, 0x0a, 0x09, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, + 0x61, 0x73, 0x74, 0x12, 0x20, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x04, 0x53, 0x65, + 0x6e, 0x64, 0x12, 0x1b, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x64, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, - 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, - 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x61, - 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x2d, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x6b, 0x61, - 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x64, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x6b, 0x61, 0x72, 0x6c, 0x73, - 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2f, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2f, - 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x43, 0x0a, 0x04, 0x53, 0x69, 0x67, 0x6e, 0x12, 0x1b, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, + 0x6e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x55, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x21, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x41, 0x5a, 0x3f, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, + 0x6e, 0x2d, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, + 0x6e, 0x64, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x6b, 0x61, 0x72, 0x6c, 0x73, 0x65, 0x6e, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x2f, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x62, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1445,8 +1540,8 @@ func file_karlsenwalletd_proto_rawDescGZIP() []byte { return file_karlsenwalletd_proto_rawDescData } -var file_karlsenwalletd_proto_msgTypes = make([]protoimpl.MessageInfo, 23) -var file_karlsenwalletd_proto_goTypes = []interface{}{ +var file_karlsenwalletd_proto_msgTypes = make([]protoimpl.MessageInfo, 25) +var file_karlsenwalletd_proto_goTypes = []any{ (*GetBalanceRequest)(nil), // 0: karlsenwalletd.GetBalanceRequest (*GetBalanceResponse)(nil), // 1: karlsenwalletd.GetBalanceResponse (*AddressBalances)(nil), // 2: karlsenwalletd.AddressBalances @@ -1470,6 +1565,8 @@ var file_karlsenwalletd_proto_goTypes = []interface{}{ (*SendResponse)(nil), // 20: karlsenwalletd.SendResponse (*SignRequest)(nil), // 21: karlsenwalletd.SignRequest (*SignResponse)(nil), // 22: karlsenwalletd.SignResponse + (*GetVersionRequest)(nil), // 23: karlsenwalletd.GetVersionRequest + (*GetVersionResponse)(nil), // 24: karlsenwalletd.GetVersionResponse } var file_karlsenwalletd_proto_depIdxs = []int32{ 2, // 0: karlsenwalletd.GetBalanceResponse.addressBalances:type_name -> karlsenwalletd.AddressBalances @@ -1486,17 +1583,19 @@ var file_karlsenwalletd_proto_depIdxs = []int32{ 9, // 11: karlsenwalletd.karlsenwalletd.Broadcast:input_type -> karlsenwalletd.BroadcastRequest 19, // 12: karlsenwalletd.karlsenwalletd.Send:input_type -> karlsenwalletd.SendRequest 21, // 13: karlsenwalletd.karlsenwalletd.Sign:input_type -> karlsenwalletd.SignRequest - 1, // 14: karlsenwalletd.karlsenwalletd.GetBalance:output_type -> karlsenwalletd.GetBalanceResponse - 18, // 15: karlsenwalletd.karlsenwalletd.GetExternalSpendableUTXOs:output_type -> karlsenwalletd.GetExternalSpendableUTXOsResponse - 4, // 16: karlsenwalletd.karlsenwalletd.CreateUnsignedTransactions:output_type -> karlsenwalletd.CreateUnsignedTransactionsResponse - 6, // 17: karlsenwalletd.karlsenwalletd.ShowAddresses:output_type -> karlsenwalletd.ShowAddressesResponse - 8, // 18: karlsenwalletd.karlsenwalletd.NewAddress:output_type -> karlsenwalletd.NewAddressResponse - 12, // 19: karlsenwalletd.karlsenwalletd.Shutdown:output_type -> karlsenwalletd.ShutdownResponse - 10, // 20: karlsenwalletd.karlsenwalletd.Broadcast:output_type -> karlsenwalletd.BroadcastResponse - 20, // 21: karlsenwalletd.karlsenwalletd.Send:output_type -> karlsenwalletd.SendResponse - 22, // 22: karlsenwalletd.karlsenwalletd.Sign:output_type -> karlsenwalletd.SignResponse - 14, // [14:23] is the sub-list for method output_type - 5, // [5:14] is the sub-list for method input_type + 23, // 14: karlsenwalletd.karlsenwalletd.GetVersion:input_type -> karlsenwalletd.GetVersionRequest + 1, // 15: karlsenwalletd.karlsenwalletd.GetBalance:output_type -> karlsenwalletd.GetBalanceResponse + 18, // 16: karlsenwalletd.karlsenwalletd.GetExternalSpendableUTXOs:output_type -> karlsenwalletd.GetExternalSpendableUTXOsResponse + 4, // 17: karlsenwalletd.karlsenwalletd.CreateUnsignedTransactions:output_type -> karlsenwalletd.CreateUnsignedTransactionsResponse + 6, // 18: karlsenwalletd.karlsenwalletd.ShowAddresses:output_type -> karlsenwalletd.ShowAddressesResponse + 8, // 19: karlsenwalletd.karlsenwalletd.NewAddress:output_type -> karlsenwalletd.NewAddressResponse + 12, // 20: karlsenwalletd.karlsenwalletd.Shutdown:output_type -> karlsenwalletd.ShutdownResponse + 10, // 21: karlsenwalletd.karlsenwalletd.Broadcast:output_type -> karlsenwalletd.BroadcastResponse + 20, // 22: karlsenwalletd.karlsenwalletd.Send:output_type -> karlsenwalletd.SendResponse + 22, // 23: karlsenwalletd.karlsenwalletd.Sign:output_type -> karlsenwalletd.SignResponse + 24, // 24: karlsenwalletd.karlsenwalletd.GetVersion:output_type -> karlsenwalletd.GetVersionResponse + 15, // [15:25] is the sub-list for method output_type + 5, // [5:15] is the sub-list for method input_type 5, // [5:5] is the sub-list for extension type_name 5, // [5:5] is the sub-list for extension extendee 0, // [0:5] is the sub-list for field type_name @@ -1508,7 +1607,7 @@ func file_karlsenwalletd_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_karlsenwalletd_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*GetBalanceRequest); i { case 0: return &v.state @@ -1520,7 +1619,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*GetBalanceResponse); i { case 0: return &v.state @@ -1532,7 +1631,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[2].Exporter = func(v any, i int) any { switch v := v.(*AddressBalances); i { case 0: return &v.state @@ -1544,7 +1643,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[3].Exporter = func(v any, i int) any { switch v := v.(*CreateUnsignedTransactionsRequest); i { case 0: return &v.state @@ -1556,7 +1655,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[4].Exporter = func(v any, i int) any { switch v := v.(*CreateUnsignedTransactionsResponse); i { case 0: return &v.state @@ -1568,7 +1667,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[5].Exporter = func(v any, i int) any { switch v := v.(*ShowAddressesRequest); i { case 0: return &v.state @@ -1580,7 +1679,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[6].Exporter = func(v any, i int) any { switch v := v.(*ShowAddressesResponse); i { case 0: return &v.state @@ -1592,7 +1691,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[7].Exporter = func(v any, i int) any { switch v := v.(*NewAddressRequest); i { case 0: return &v.state @@ -1604,7 +1703,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[8].Exporter = func(v any, i int) any { switch v := v.(*NewAddressResponse); i { case 0: return &v.state @@ -1616,7 +1715,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[9].Exporter = func(v any, i int) any { switch v := v.(*BroadcastRequest); i { case 0: return &v.state @@ -1628,7 +1727,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[10].Exporter = func(v any, i int) any { switch v := v.(*BroadcastResponse); i { case 0: return &v.state @@ -1640,7 +1739,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[11].Exporter = func(v any, i int) any { switch v := v.(*ShutdownRequest); i { case 0: return &v.state @@ -1652,7 +1751,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[12].Exporter = func(v any, i int) any { switch v := v.(*ShutdownResponse); i { case 0: return &v.state @@ -1664,7 +1763,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[13].Exporter = func(v any, i int) any { switch v := v.(*Outpoint); i { case 0: return &v.state @@ -1676,7 +1775,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[14].Exporter = func(v any, i int) any { switch v := v.(*UtxosByAddressesEntry); i { case 0: return &v.state @@ -1688,7 +1787,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[15].Exporter = func(v any, i int) any { switch v := v.(*ScriptPublicKey); i { case 0: return &v.state @@ -1700,7 +1799,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[16].Exporter = func(v any, i int) any { switch v := v.(*UtxoEntry); i { case 0: return &v.state @@ -1712,7 +1811,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[17].Exporter = func(v any, i int) any { switch v := v.(*GetExternalSpendableUTXOsRequest); i { case 0: return &v.state @@ -1724,7 +1823,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[18].Exporter = func(v any, i int) any { switch v := v.(*GetExternalSpendableUTXOsResponse); i { case 0: return &v.state @@ -1736,7 +1835,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[19].Exporter = func(v any, i int) any { switch v := v.(*SendRequest); i { case 0: return &v.state @@ -1748,7 +1847,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[20].Exporter = func(v any, i int) any { switch v := v.(*SendResponse); i { case 0: return &v.state @@ -1760,7 +1859,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[21].Exporter = func(v any, i int) any { switch v := v.(*SignRequest); i { case 0: return &v.state @@ -1772,7 +1871,7 @@ func file_karlsenwalletd_proto_init() { return nil } } - file_karlsenwalletd_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + file_karlsenwalletd_proto_msgTypes[22].Exporter = func(v any, i int) any { switch v := v.(*SignResponse); i { case 0: return &v.state @@ -1784,6 +1883,30 @@ func file_karlsenwalletd_proto_init() { return nil } } + file_karlsenwalletd_proto_msgTypes[23].Exporter = func(v any, i int) any { + switch v := v.(*GetVersionRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_karlsenwalletd_proto_msgTypes[24].Exporter = func(v any, i int) any { + switch v := v.(*GetVersionResponse); 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{ @@ -1791,7 +1914,7 @@ func file_karlsenwalletd_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_karlsenwalletd_proto_rawDesc, NumEnums: 0, - NumMessages: 23, + NumMessages: 25, NumExtensions: 0, NumServices: 1, }, diff --git a/cmd/karlsenwallet/daemon/pb/karlsenwalletd.proto b/cmd/karlsenwallet/daemon/pb/karlsenwalletd.proto index 2f69cc4d87..8a6e7905a4 100644 --- a/cmd/karlsenwallet/daemon/pb/karlsenwalletd.proto +++ b/cmd/karlsenwallet/daemon/pb/karlsenwalletd.proto @@ -15,6 +15,7 @@ service karlsenwalletd { rpc Send(SendRequest) returns (SendResponse) {} // Since SignRequest contains a password - this command should only be used on a trusted or secure connection rpc Sign(SignRequest) returns (SignResponse) {} + rpc GetVersion(GetVersionRequest) returns (GetVersionResponse) {} } message GetBalanceRequest { @@ -127,3 +128,10 @@ message SignRequest{ message SignResponse{ repeated bytes signedTransactions = 1; } + +message GetVersionRequest{ +} + +message GetVersionResponse{ + string version = 1; +} diff --git a/cmd/karlsenwallet/daemon/pb/karlsenwalletd_grpc.pb.go b/cmd/karlsenwallet/daemon/pb/karlsenwalletd_grpc.pb.go index efc4a1b706..cfcf8c09db 100644 --- a/cmd/karlsenwallet/daemon/pb/karlsenwalletd_grpc.pb.go +++ b/cmd/karlsenwallet/daemon/pb/karlsenwalletd_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.3.0 -// - protoc v4.25.2 +// - protoc-gen-go-grpc v1.5.1 +// - protoc v3.12.4 // source: karlsenwalletd.proto package pb @@ -15,8 +15,8 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 const ( Karlsenwalletd_GetBalance_FullMethodName = "/karlsenwalletd.karlsenwalletd/GetBalance" @@ -28,6 +28,7 @@ const ( Karlsenwalletd_Broadcast_FullMethodName = "/karlsenwalletd.karlsenwalletd/Broadcast" Karlsenwalletd_Send_FullMethodName = "/karlsenwalletd.karlsenwalletd/Send" Karlsenwalletd_Sign_FullMethodName = "/karlsenwalletd.karlsenwalletd/Sign" + Karlsenwalletd_GetVersion_FullMethodName = "/karlsenwalletd.karlsenwalletd/GetVersion" ) // KarlsenwalletdClient is the client API for Karlsenwalletd service. @@ -45,6 +46,7 @@ type KarlsenwalletdClient interface { Send(ctx context.Context, in *SendRequest, opts ...grpc.CallOption) (*SendResponse, error) // Since SignRequest contains a password - this command should only be used on a trusted or secure connection Sign(ctx context.Context, in *SignRequest, opts ...grpc.CallOption) (*SignResponse, error) + GetVersion(ctx context.Context, in *GetVersionRequest, opts ...grpc.CallOption) (*GetVersionResponse, error) } type karlsenwalletdClient struct { @@ -56,8 +58,9 @@ func NewKarlsenwalletdClient(cc grpc.ClientConnInterface) KarlsenwalletdClient { } func (c *karlsenwalletdClient) GetBalance(ctx context.Context, in *GetBalanceRequest, opts ...grpc.CallOption) (*GetBalanceResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetBalanceResponse) - err := c.cc.Invoke(ctx, Karlsenwalletd_GetBalance_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Karlsenwalletd_GetBalance_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -65,8 +68,9 @@ func (c *karlsenwalletdClient) GetBalance(ctx context.Context, in *GetBalanceReq } func (c *karlsenwalletdClient) GetExternalSpendableUTXOs(ctx context.Context, in *GetExternalSpendableUTXOsRequest, opts ...grpc.CallOption) (*GetExternalSpendableUTXOsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetExternalSpendableUTXOsResponse) - err := c.cc.Invoke(ctx, Karlsenwalletd_GetExternalSpendableUTXOs_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Karlsenwalletd_GetExternalSpendableUTXOs_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -74,8 +78,9 @@ func (c *karlsenwalletdClient) GetExternalSpendableUTXOs(ctx context.Context, in } func (c *karlsenwalletdClient) CreateUnsignedTransactions(ctx context.Context, in *CreateUnsignedTransactionsRequest, opts ...grpc.CallOption) (*CreateUnsignedTransactionsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(CreateUnsignedTransactionsResponse) - err := c.cc.Invoke(ctx, Karlsenwalletd_CreateUnsignedTransactions_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Karlsenwalletd_CreateUnsignedTransactions_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -83,8 +88,9 @@ func (c *karlsenwalletdClient) CreateUnsignedTransactions(ctx context.Context, i } func (c *karlsenwalletdClient) ShowAddresses(ctx context.Context, in *ShowAddressesRequest, opts ...grpc.CallOption) (*ShowAddressesResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ShowAddressesResponse) - err := c.cc.Invoke(ctx, Karlsenwalletd_ShowAddresses_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Karlsenwalletd_ShowAddresses_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -92,8 +98,9 @@ func (c *karlsenwalletdClient) ShowAddresses(ctx context.Context, in *ShowAddres } func (c *karlsenwalletdClient) NewAddress(ctx context.Context, in *NewAddressRequest, opts ...grpc.CallOption) (*NewAddressResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(NewAddressResponse) - err := c.cc.Invoke(ctx, Karlsenwalletd_NewAddress_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Karlsenwalletd_NewAddress_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -101,8 +108,9 @@ func (c *karlsenwalletdClient) NewAddress(ctx context.Context, in *NewAddressReq } func (c *karlsenwalletdClient) Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*ShutdownResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ShutdownResponse) - err := c.cc.Invoke(ctx, Karlsenwalletd_Shutdown_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Karlsenwalletd_Shutdown_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -110,8 +118,9 @@ func (c *karlsenwalletdClient) Shutdown(ctx context.Context, in *ShutdownRequest } func (c *karlsenwalletdClient) Broadcast(ctx context.Context, in *BroadcastRequest, opts ...grpc.CallOption) (*BroadcastResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(BroadcastResponse) - err := c.cc.Invoke(ctx, Karlsenwalletd_Broadcast_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Karlsenwalletd_Broadcast_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -119,8 +128,9 @@ func (c *karlsenwalletdClient) Broadcast(ctx context.Context, in *BroadcastReque } func (c *karlsenwalletdClient) Send(ctx context.Context, in *SendRequest, opts ...grpc.CallOption) (*SendResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(SendResponse) - err := c.cc.Invoke(ctx, Karlsenwalletd_Send_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Karlsenwalletd_Send_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -128,8 +138,19 @@ func (c *karlsenwalletdClient) Send(ctx context.Context, in *SendRequest, opts . } func (c *karlsenwalletdClient) Sign(ctx context.Context, in *SignRequest, opts ...grpc.CallOption) (*SignResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(SignResponse) - err := c.cc.Invoke(ctx, Karlsenwalletd_Sign_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, Karlsenwalletd_Sign_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *karlsenwalletdClient) GetVersion(ctx context.Context, in *GetVersionRequest, opts ...grpc.CallOption) (*GetVersionResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetVersionResponse) + err := c.cc.Invoke(ctx, Karlsenwalletd_GetVersion_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -138,7 +159,7 @@ func (c *karlsenwalletdClient) Sign(ctx context.Context, in *SignRequest, opts . // KarlsenwalletdServer is the server API for Karlsenwalletd service. // All implementations must embed UnimplementedKarlsenwalletdServer -// for forward compatibility +// for forward compatibility. type KarlsenwalletdServer interface { GetBalance(context.Context, *GetBalanceRequest) (*GetBalanceResponse, error) GetExternalSpendableUTXOs(context.Context, *GetExternalSpendableUTXOsRequest) (*GetExternalSpendableUTXOsResponse, error) @@ -151,12 +172,16 @@ type KarlsenwalletdServer interface { Send(context.Context, *SendRequest) (*SendResponse, error) // Since SignRequest contains a password - this command should only be used on a trusted or secure connection Sign(context.Context, *SignRequest) (*SignResponse, error) + GetVersion(context.Context, *GetVersionRequest) (*GetVersionResponse, error) mustEmbedUnimplementedKarlsenwalletdServer() } -// UnimplementedKarlsenwalletdServer must be embedded to have forward compatible implementations. -type UnimplementedKarlsenwalletdServer struct { -} +// UnimplementedKarlsenwalletdServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedKarlsenwalletdServer struct{} func (UnimplementedKarlsenwalletdServer) GetBalance(context.Context, *GetBalanceRequest) (*GetBalanceResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetBalance not implemented") @@ -185,7 +210,11 @@ func (UnimplementedKarlsenwalletdServer) Send(context.Context, *SendRequest) (*S func (UnimplementedKarlsenwalletdServer) Sign(context.Context, *SignRequest) (*SignResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Sign not implemented") } +func (UnimplementedKarlsenwalletdServer) GetVersion(context.Context, *GetVersionRequest) (*GetVersionResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetVersion not implemented") +} func (UnimplementedKarlsenwalletdServer) mustEmbedUnimplementedKarlsenwalletdServer() {} +func (UnimplementedKarlsenwalletdServer) testEmbeddedByValue() {} // UnsafeKarlsenwalletdServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to KarlsenwalletdServer will @@ -195,6 +224,13 @@ type UnsafeKarlsenwalletdServer interface { } func RegisterKarlsenwalletdServer(s grpc.ServiceRegistrar, srv KarlsenwalletdServer) { + // If the following call pancis, it indicates UnimplementedKarlsenwalletdServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } s.RegisterService(&Karlsenwalletd_ServiceDesc, srv) } @@ -360,6 +396,24 @@ func _Karlsenwalletd_Sign_Handler(srv interface{}, ctx context.Context, dec func return interceptor(ctx, in, info, handler) } +func _Karlsenwalletd_GetVersion_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetVersionRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(KarlsenwalletdServer).GetVersion(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Karlsenwalletd_GetVersion_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(KarlsenwalletdServer).GetVersion(ctx, req.(*GetVersionRequest)) + } + return interceptor(ctx, in, info, handler) +} + // Karlsenwalletd_ServiceDesc is the grpc.ServiceDesc for Karlsenwalletd service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -403,6 +457,10 @@ var Karlsenwalletd_ServiceDesc = grpc.ServiceDesc{ MethodName: "Sign", Handler: _Karlsenwalletd_Sign_Handler, }, + { + MethodName: "GetVersion", + Handler: _Karlsenwalletd_GetVersion_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "karlsenwalletd.proto", diff --git a/cmd/karlsenwallet/daemon/server/balance.go b/cmd/karlsenwallet/daemon/server/balance.go index 8b34d33bb9..2f6a4efd54 100644 --- a/cmd/karlsenwallet/daemon/server/balance.go +++ b/cmd/karlsenwallet/daemon/server/balance.go @@ -55,6 +55,8 @@ func (s *server) GetBalance(_ context.Context, _ *pb.GetBalanceRequest) (*pb.Get pending += balances.pending } + log.Infof("GetBalance request scanned %d UTXOs overall over %d addresses", len(s.utxosSortedByAmount), len(balancesMap)) + return &pb.GetBalanceResponse{ Available: available, Pending: pending, diff --git a/cmd/karlsenwallet/daemon/server/server.go b/cmd/karlsenwallet/daemon/server/server.go index 6ceb3a69d2..53f12e9e39 100644 --- a/cmd/karlsenwallet/daemon/server/server.go +++ b/cmd/karlsenwallet/daemon/server/server.go @@ -7,6 +7,8 @@ import ( "sync" "time" + "github.com/karlsen-network/karlsend/v2/domain/version" + "github.com/karlsen-network/karlsend/v2/domain/consensus/model/externalapi" "github.com/karlsen-network/karlsend/v2/util/txmass" @@ -59,6 +61,7 @@ func Start(params *dagconfig.Params, listen, rpcServer string, keysFilePath stri profiling.Start(profile, log) } + log.Infof("Version %s", version.Version()) listener, err := net.Listen("tcp", listen) if err != nil { return (errors.Wrapf(err, "Error listening to TCP on %s", listen)) diff --git a/cmd/karlsenwallet/daemon/server/version.go b/cmd/karlsenwallet/daemon/server/version.go new file mode 100644 index 0000000000..1685efc37a --- /dev/null +++ b/cmd/karlsenwallet/daemon/server/version.go @@ -0,0 +1,17 @@ +package server + +import ( + "context" + + "github.com/karlsen-network/karlsend/v2/cmd/karlsenwallet/daemon/pb" + "github.com/karlsen-network/karlsend/v2/version" +) + +func (s *server) GetVersion(_ context.Context, _ *pb.GetVersionRequest) (*pb.GetVersionResponse, error) { + s.lock.RLock() + defer s.lock.RUnlock() + + return &pb.GetVersionResponse{ + Version: version.Version(), + }, nil +} diff --git a/cmd/karlsenwallet/get_daemon_version.go b/cmd/karlsenwallet/get_daemon_version.go new file mode 100644 index 0000000000..389707bb51 --- /dev/null +++ b/cmd/karlsenwallet/get_daemon_version.go @@ -0,0 +1,27 @@ +package main + +import ( + "context" + "fmt" + + "github.com/karlsen-network/karlsend/v2//cmd/karlsenwallet/daemon/pb" + "github.com/karlsen-network/karlsend/v2/cmd/karlsenwallet/daemon/client" +) + +func getDaemonVersion(conf *getDaemonVersionConfig) error { + daemonClient, tearDown, err := client.Connect(conf.DaemonAddress) + if err != nil { + return err + } + defer tearDown() + + ctx, cancel := context.WithTimeout(context.Background(), daemonTimeout) + defer cancel() + response, err := daemonClient.GetVersion(ctx, &pb.GetVersionRequest{}) + if err != nil { + return err + } + fmt.Println(response.Version) + + return nil +} diff --git a/cmd/karlsenwallet/main.go b/cmd/karlsenwallet/main.go index 48995925b7..afe44cadc4 100644 --- a/cmd/karlsenwallet/main.go +++ b/cmd/karlsenwallet/main.go @@ -1,10 +1,11 @@ package main -import "github.com/pkg/errors" +import ( + "github.com/pkg/errors" +) func main() { subCmd, config := parseCommandLine() - var err error switch subCmd { case createSubCmd: @@ -31,6 +32,10 @@ func main() { err = startDaemon(config.(*startDaemonConfig)) case sweepSubCmd: err = sweep(config.(*sweepConfig)) + case versionSubCmd: + showVersion() + case getDaemonVersionSubCmd: + err = getDaemonVersion(config.(*getDaemonVersionConfig)) default: err = errors.Errorf("Unknown sub-command '%s'\n", subCmd) } diff --git a/cmd/karlsenwallet/version.go b/cmd/karlsenwallet/version.go new file mode 100644 index 0000000000..73956bff77 --- /dev/null +++ b/cmd/karlsenwallet/version.go @@ -0,0 +1,16 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/karlsen-network/karlsend/v2/version" +) + +func showVersion() { + appName := filepath.Base(os.Args[0]) + appName = strings.TrimSuffix(appName, filepath.Ext(appName)) + fmt.Println(appName, "version", version.Version()) +} From 23a313b48f203a88886c561a24734a998c284e6a Mon Sep 17 00:00:00 2001 From: Leon1777 <168653957+Leon1777@users.noreply.github.com> Date: Wed, 18 Sep 2024 23:52:14 +0200 Subject: [PATCH 04/13] lazy wallet utxo sync after broadcasting a tx - lazy wallet utxo sync after broadcasting tx - granular lock for `refreshutxos` - avoid pushing to `forcesyncchan` if not empty - improve policy for used outpoints; wait for first sync on unsigned tx creation - fix expire condition - lock address reading - fix memory leak - add rpc client for background ops - follow naming conventions - another rename - compare wallet addresses by value - small fixes - add comment --- cmd/karlsenwallet/daemon/server/balance.go | 12 ++- cmd/karlsenwallet/daemon/server/broadcast.go | 6 +- .../server/create_unsigned_transaction.go | 31 +++--- cmd/karlsenwallet/daemon/server/server.go | 49 +++++++--- .../daemon/server/split_transaction.go | 2 +- cmd/karlsenwallet/daemon/server/sync.go | 98 +++++++++++++------ 6 files changed, 129 insertions(+), 69 deletions(-) diff --git a/cmd/karlsenwallet/daemon/server/balance.go b/cmd/karlsenwallet/daemon/server/balance.go index 2f6a4efd54..049fbf07b3 100644 --- a/cmd/karlsenwallet/daemon/server/balance.go +++ b/cmd/karlsenwallet/daemon/server/balance.go @@ -2,6 +2,7 @@ package server import ( "context" + "github.com/pkg/errors" "github.com/karlsen-network/karlsend/v2/cmd/karlsenwallet/daemon/pb" "github.com/karlsen-network/karlsend/v2/cmd/karlsenwallet/libkarlsenwallet" @@ -14,12 +15,15 @@ func (s *server) GetBalance(_ context.Context, _ *pb.GetBalanceRequest) (*pb.Get s.lock.RLock() defer s.lock.RUnlock() + if !s.isSynced() { + return nil, errors.Errorf("wallet daemon is not synced yet, %s", s.formatSyncStateReport()) + } + dagInfo, err := s.rpcClient.GetBlockDAGInfo() if err != nil { return nil, err } daaScore := dagInfo.VirtualDAAScore - maturity := s.params.BlockCoinbaseMaturity balancesMap := make(balancesMapType, 0) for _, entry := range s.utxosSortedByAmount { @@ -30,7 +34,7 @@ func (s *server) GetBalance(_ context.Context, _ *pb.GetBalanceRequest) (*pb.Get balances = new(balancesType) balancesMap[address] = balances } - if isUTXOSpendable(entry, daaScore, maturity) { + if s.isUTXOSpendable(entry, daaScore) { balances.available += amount } else { balances.pending += amount @@ -64,9 +68,9 @@ func (s *server) GetBalance(_ context.Context, _ *pb.GetBalanceRequest) (*pb.Get }, nil } -func isUTXOSpendable(entry *walletUTXO, virtualDAAScore uint64, coinbaseMaturity uint64) bool { +func (s *server) isUTXOSpendable(entry *walletUTXO, virtualDAAScore uint64) bool { if !entry.UTXOEntry.IsCoinbase() { return true } - return entry.UTXOEntry.BlockDAAScore()+coinbaseMaturity < virtualDAAScore + return entry.UTXOEntry.BlockDAAScore()+s.coinbaseMaturity < virtualDAAScore } diff --git a/cmd/karlsenwallet/daemon/server/broadcast.go b/cmd/karlsenwallet/daemon/server/broadcast.go index 73e3e7f46c..189c785531 100644 --- a/cmd/karlsenwallet/daemon/server/broadcast.go +++ b/cmd/karlsenwallet/daemon/server/broadcast.go @@ -55,11 +55,7 @@ func (s *server) broadcast(transactions [][]byte, isDomain bool) ([]string, erro } } - err = s.refreshUTXOs() - if err != nil { - return nil, err - } - + s.forceSync() return txIDs, nil } diff --git a/cmd/karlsenwallet/daemon/server/create_unsigned_transaction.go b/cmd/karlsenwallet/daemon/server/create_unsigned_transaction.go index 5c85c4ec1d..79585fb62d 100644 --- a/cmd/karlsenwallet/daemon/server/create_unsigned_transaction.go +++ b/cmd/karlsenwallet/daemon/server/create_unsigned_transaction.go @@ -3,14 +3,12 @@ package server import ( "context" "fmt" - "time" "github.com/karlsen-network/karlsend/v2/cmd/karlsenwallet/daemon/pb" "github.com/karlsen-network/karlsend/v2/cmd/karlsenwallet/libkarlsenwallet" "github.com/karlsen-network/karlsend/v2/domain/consensus/utils/constants" "github.com/karlsen-network/karlsend/v2/util" "github.com/pkg/errors" - "golang.org/x/exp/slices" ) // TODO: Implement a better fee estimation mechanism @@ -35,7 +33,6 @@ func (s *server) createUnsignedTransactions(address string, amount uint64, isSen if !s.isSynced() { return nil, errors.Errorf("wallet daemon is not synced yet, %s", s.formatSyncStateReport()) } - // make sure address string is correct before proceeding to a // potentially long UTXO refreshment operation toAddress, err := util.DecodeAddress(address, s.params.Prefix) @@ -43,16 +40,11 @@ func (s *server) createUnsignedTransactions(address string, amount uint64, isSen return nil, err } - err = s.refreshUTXOs() - if err != nil { - return nil, err - } - var fromAddresses []*walletAddress for _, from := range fromAddressesString { fromAddress, exists := s.addressSet[from] if !exists { - return nil, fmt.Errorf("Specified from address %s does not exists", from) + return nil, fmt.Errorf("specified from address %s does not exists", from) } fromAddresses = append(fromAddresses, fromAddress) } @@ -106,19 +98,14 @@ func (s *server) selectUTXOs(spendAmount uint64, isSendAll bool, feePerInput uin return nil, 0, 0, err } - coinbaseMaturity := s.params.BlockCoinbaseMaturity - if dagInfo.NetworkName == "karlsen-testnet-1" { - coinbaseMaturity = 1000 - } - for _, utxo := range s.utxosSortedByAmount { - if (fromAddresses != nil && !slices.Contains(fromAddresses, utxo.address)) || - !isUTXOSpendable(utxo, dagInfo.VirtualDAAScore, coinbaseMaturity) { + if (fromAddresses != nil && !walletAddressesContain(fromAddresses, utxo.address)) || + !s.isUTXOSpendable(utxo, dagInfo.VirtualDAAScore) { continue } if broadcastTime, ok := s.usedOutpoints[*utxo.Outpoint]; ok { - if time.Since(broadcastTime) > time.Minute { + if s.usedOutpointHasExpired(broadcastTime) { delete(s.usedOutpoints, *utxo.Outpoint) } else { continue @@ -160,3 +147,13 @@ func (s *server) selectUTXOs(spendAmount uint64, isSendAll bool, feePerInput uin return selectedUTXOs, totalReceived, totalValue - totalSpend, nil } + +func walletAddressesContain(addresses []*walletAddress, contain *walletAddress) bool { + for _, address := range addresses { + if *address == *contain { + return true + } + } + + return false +} diff --git a/cmd/karlsenwallet/daemon/server/server.go b/cmd/karlsenwallet/daemon/server/server.go index 53f12e9e39..e86b51215b 100644 --- a/cmd/karlsenwallet/daemon/server/server.go +++ b/cmd/karlsenwallet/daemon/server/server.go @@ -5,6 +5,7 @@ import ( "net" "os" "sync" + "sync/atomic" "time" "github.com/karlsen-network/karlsend/v2/domain/version" @@ -29,17 +30,22 @@ import ( type server struct { pb.UnimplementedKarlsenwalletdServer - rpcClient *rpcclient.RPCClient - params *dagconfig.Params - - lock sync.RWMutex - utxosSortedByAmount []*walletUTXO - nextSyncStartIndex uint32 - keysFile *keys.File - shutdown chan struct{} - addressSet walletAddressSet - txMassCalculator *txmass.Calculator - usedOutpoints map[externalapi.DomainOutpoint]time.Time + rpcClient *rpcclient.RPCClient // RPC client for ongoing user requests + backgroundRPCClient *rpcclient.RPCClient // RPC client dedicated for address and UTXO background fetching + params *dagconfig.Params + coinbaseMaturity uint64 // Is different from default if we use testnet-11 + + lock sync.RWMutex + utxosSortedByAmount []*walletUTXO + nextSyncStartIndex uint32 + keysFile *keys.File + shutdown chan struct{} + forceSyncChan chan struct{} + startTimeOfLastCompletedRefresh time.Time + addressSet walletAddressSet + txMassCalculator *txmass.Calculator + usedOutpoints map[externalapi.DomainOutpoint]time.Time + firstSyncDone atomic.Bool isLogFinalProgressLineShown bool maxUsedAddressesForLog uint32 @@ -73,6 +79,10 @@ func Start(params *dagconfig.Params, listen, rpcServer string, keysFilePath stri if err != nil { return (errors.Wrapf(err, "Error connecting to RPC server %s", rpcServer)) } + backgroundRPCClient, err := connectToRPC(params, rpcServer, timeout) + if err != nil { + return (errors.Wrapf(err, "Error making a second connection to RPC server %s", rpcServer)) + } log.Infof("Connected, reading keys file %s...", keysFilePath) keysFile, err := keys.ReadKeysFile(params, keysFilePath) @@ -80,6 +90,16 @@ func Start(params *dagconfig.Params, listen, rpcServer string, keysFilePath stri return (errors.Wrapf(err, "Error reading keys file %s", keysFilePath)) } + dagInfo, err := rpcClient.GetBlockDAGInfo() + if err != nil { + return nil + } + + coinbaseMaturity := params.BlockCoinbaseMaturity + if dagInfo.NetworkName == "karlsen-testnet-1" { + coinbaseMaturity = 1000 + } + err = keysFile.TryLock() if err != nil { return err @@ -99,11 +119,14 @@ func Start(params *dagconfig.Params, listen, rpcServer string, keysFilePath stri serverInstance := &server{ rpcClient: rpcClient, + backgroundRPCClient: backgroundRPCClient, params: params, + coinbaseMaturity: coinbaseMaturity, utxosSortedByAmount: []*walletUTXO{}, nextSyncStartIndex: 0, keysFile: keysFile, shutdown: make(chan struct{}), + forceSyncChan: make(chan struct{}), addressSet: make(walletAddressSet), txMassCalculator: txmass.NewCalculator(params.MassPerTxByte, params.MassPerScriptPubKeyByte, params.MassPerSigOp), usedOutpoints: map[externalapi.DomainOutpoint]time.Time{}, @@ -113,8 +136,8 @@ func Start(params *dagconfig.Params, listen, rpcServer string, keysFilePath stri } log.Infof("Read, syncing the wallet...") - spawn("serverInstance.sync", func() { - err := serverInstance.sync() + spawn("serverInstance.syncLoop", func() { + err := serverInstance.syncLoop() if err != nil { printErrorAndExit(errors.Wrap(err, "error syncing the wallet")) } diff --git a/cmd/karlsenwallet/daemon/server/split_transaction.go b/cmd/karlsenwallet/daemon/server/split_transaction.go index 452f1c738c..5e2125e708 100644 --- a/cmd/karlsenwallet/daemon/server/split_transaction.go +++ b/cmd/karlsenwallet/daemon/server/split_transaction.go @@ -264,7 +264,7 @@ func (s *server) moreUTXOsForMergeTransaction(alreadySelectedUTXOs []*libkarlsen if _, ok := alreadySelectedUTXOsMap[*utxo.Outpoint]; ok { continue } - if !isUTXOSpendable(utxo, dagInfo.VirtualDAAScore, s.params.BlockCoinbaseMaturity) { + if !s.isUTXOSpendable(utxo, dagInfo.VirtualDAAScore) { continue } additionalUTXOs = append(additionalUTXOs, &libkarlsenwallet.UTXO{ diff --git a/cmd/karlsenwallet/daemon/server/sync.go b/cmd/karlsenwallet/daemon/server/sync.go index c9ed749b57..18a2b56639 100644 --- a/cmd/karlsenwallet/daemon/server/sync.go +++ b/cmd/karlsenwallet/daemon/server/sync.go @@ -23,7 +23,7 @@ func (was walletAddressSet) strings() []string { return addresses } -func (s *server) sync() error { +func (s *server) syncLoop() error { ticker := time.NewTicker(time.Second) defer ticker.Stop() @@ -32,29 +32,39 @@ func (s *server) sync() error { return err } - err = s.refreshExistingUTXOsWithLock() + err = s.refreshUTXOs() if err != nil { return err } - for range ticker.C { - err = s.collectFarAddresses() - if err != nil { - return err - } + s.firstSyncDone.Store(true) + log.Infof("Wallet is synced and ready for operation") - err = s.collectRecentAddresses() - if err != nil { - return err - } + for { + select { + case <-ticker.C: + case <-s.forceSyncChan: - err = s.refreshExistingUTXOsWithLock() - if err != nil { - return err + err := s.sync() + if err != nil { + return err + } } } +} - return nil +func (s *server) sync() error { + err := s.collectFarAddresses() + if err != nil { + return err + } + + err = s.collectRecentAddresses() + if err != nil { + return err + } + + return s.refreshUTXOs() } const ( @@ -158,7 +168,7 @@ func (s *server) collectAddresses(start, end uint32) error { return err } - getBalancesByAddressesResponse, err := s.rpcClient.GetBalancesByAddresses(addressSet.strings()) + getBalancesByAddressesResponse, err := s.backgroundRPCClient.GetBalancesByAddresses(addressSet.strings()) if err != nil { return err } @@ -208,15 +218,17 @@ func (s *server) updateAddressesAndLastUsedIndexes(requestedAddressSet walletAdd return s.keysFile.SetLastUsedInternalIndex(lastUsedInternalIndex) } -func (s *server) refreshExistingUTXOsWithLock() error { - s.lock.Lock() - defer s.lock.Unlock() - - return s.refreshUTXOs() +func (s *server) usedOutpointHasExpired(outpointBroadcastTime time.Time) bool { + // If the node returns a UTXO we previously attempted to spend and enough time has passed, we assume + // that the network rejected or lost the previous transaction and allow a reuse. We set this time + // interval to a minute. + // We also verify that a full refresh UTXO operation started after this time point and has already + // completed, in order to make sure that indeed this state reflects a state obtained following the required wait time. + return s.startTimeOfLastCompletedRefresh.After(outpointBroadcastTime.Add(time.Minute)) } // updateUTXOSet clears the current UTXO set, and re-fills it with the given entries -func (s *server) updateUTXOSet(entries []*appmessage.UTXOsByAddressesEntry, mempoolEntries []*appmessage.MempoolEntryByAddress) error { +func (s *server) updateUTXOSet(entries []*appmessage.UTXOsByAddressesEntry, mempoolEntries []*appmessage.MempoolEntryByAddress, refreshStart time.Time) error { utxos := make([]*walletUTXO, 0, len(entries)) exclude := make(map[appmessage.RPCOutpoint]struct{}) @@ -243,6 +255,7 @@ func (s *server) updateUTXOSet(entries []*appmessage.UTXOsByAddressesEntry, memp return err } + // No need to lock for reading since the only writer of this set is on `syncLoop` on the same goroutine. address, ok := s.addressSet[entry.Address] if !ok { return errors.Errorf("Got result from address %s even though it wasn't requested", entry.Address) @@ -256,32 +269,56 @@ func (s *server) updateUTXOSet(entries []*appmessage.UTXOsByAddressesEntry, memp sort.Slice(utxos, func(i, j int) bool { return utxos[i].UTXOEntry.Amount() > utxos[j].UTXOEntry.Amount() }) + s.lock.Lock() + s.startTimeOfLastCompletedRefresh = refreshStart s.utxosSortedByAmount = utxos + // Cleanup expired used outpoints to avoid a memory leak + for outpoint, broadcastTime := range s.usedOutpoints { + if s.usedOutpointHasExpired(broadcastTime) { + delete(s.usedOutpoints, outpoint) + } + } + s.lock.Unlock() + return nil } func (s *server) refreshUTXOs() error { + refreshStart := time.Now() + + // No need to lock for reading since the only writer of this set is on `syncLoop` on the same goroutine. + addresses := s.addressSet.strings() // It's important to check the mempool before calling `GetUTXOsByAddresses`: // If we would do it the other way around an output can be spent in the mempool // and not in consensus, and between the calls its spending transaction will be // added to consensus and removed from the mempool, so `getUTXOsByAddressesResponse` // will include an obsolete output. - mempoolEntriesByAddresses, err := s.rpcClient.GetMempoolEntriesByAddresses(s.addressSet.strings(), true, true) + mempoolEntriesByAddresses, err := s.backgroundRPCClient.GetMempoolEntriesByAddresses(addresses, true, true) if err != nil { return err } - getUTXOsByAddressesResponse, err := s.rpcClient.GetUTXOsByAddresses(s.addressSet.strings()) + getUTXOsByAddressesResponse, err := s.backgroundRPCClient.GetUTXOsByAddresses(addresses) if err != nil { return err } - return s.updateUTXOSet(getUTXOsByAddressesResponse.Entries, mempoolEntriesByAddresses.Entries) + return s.updateUTXOSet(getUTXOsByAddressesResponse.Entries, mempoolEntriesByAddresses.Entries, refreshStart) +} + +func (s *server) forceSync() { + // Technically if two callers check the `if` simultaneously they will both spawn a + // goroutine, but we don't care about the small redundancy in such a rare case. + if len(s.forceSyncChan) == 0 { + go func() { + s.forceSyncChan <- struct{}{} + }() + } } func (s *server) isSynced() bool { - return s.nextSyncStartIndex > s.maxUsedIndex() + return s.nextSyncStartIndex > s.maxUsedIndex() && s.firstSyncDone.Load() } func (s *server) formatSyncStateReport() string { @@ -291,8 +328,11 @@ func (s *server) formatSyncStateReport() string { maxUsedIndex = s.nextSyncStartIndex } - return fmt.Sprintf("scanned %d out of %d addresses (%.2f%%)", - s.nextSyncStartIndex, maxUsedIndex, float64(s.nextSyncStartIndex)*100.0/float64(maxUsedIndex)) + if s.nextSyncStartIndex < s.maxUsedIndex() { + return fmt.Sprintf("scanned %d out of %d addresses (%.2f%%)", + s.nextSyncStartIndex, maxUsedIndex, float64(s.nextSyncStartIndex)*100.0/float64(maxUsedIndex)) + } + return "loading the wallet UTXO set" } func (s *server) updateSyncingProgressLog(currProcessedAddresses, currMaxUsedAddresses uint32) { @@ -311,7 +351,7 @@ func (s *server) updateSyncingProgressLog(currProcessedAddresses, currMaxUsedAdd if s.maxProcessedAddressesForLog >= s.maxUsedAddressesForLog { if !s.isLogFinalProgressLineShown { - log.Infof("Wallet is synced, ready for queries") + log.Infof("Finished scanning recent addresses") s.isLogFinalProgressLineShown = true } } else { From 2e6f7ac3778787b001e446523fc1679bc4eeca40 Mon Sep 17 00:00:00 2001 From: Leon1777 <168653957+Leon1777@users.noreply.github.com> Date: Thu, 19 Sep 2024 00:32:45 +0200 Subject: [PATCH 05/13] RPC SubmitTransaction: Dequeue old responses from previous requests --- app/rpc/rpchandlers/submit_transaction.go | 3 +- build_and_test.sh | 0 cmd/karlsenwallet/daemon/server/broadcast.go | 3 +- cmd/karlsenwallet/get_daemon_version.go | 2 +- .../rpcclient/rpc_send_raw_transaction.go | 41 ++++++++++++++----- .../application-level-garbage/run/run.sh | 0 stability-tests/daa/run/run.sh | 0 .../infra-level-garbage/run/run.sh | 0 stability-tests/install_and_test.sh | 0 stability-tests/karlsendsanity/run/run.sh | 0 stability-tests/many-tips/run/run.sh | 0 stability-tests/mempool-limits/run/run.sh | 0 .../mempool-limits/transactions.go | 2 +- stability-tests/netsync/run/run-fast.sh | 0 stability-tests/netsync/run/run-slow.sh | 0 stability-tests/netsync/run/run.sh | 0 stability-tests/orphans/run/run.sh | 0 .../run/run-full-finality-window-reorg.sh | 0 stability-tests/reorg/run/run.sh | 0 stability-tests/rpc-idle-clients/run/run.sh | 0 stability-tests/rpc-stability/run/run.sh | 0 stability-tests/run/run-fast.sh | 0 stability-tests/run/run-slow.sh | 0 stability-tests/run/run.sh | 0 stability-tests/simple-sync/run/run.sh | 0 testing/integration/tx_relay_test.go | 2 +- testing/integration/utxo_index_test.go | 8 ++-- 27 files changed, 42 insertions(+), 19 deletions(-) mode change 100755 => 100644 build_and_test.sh mode change 100755 => 100644 stability-tests/application-level-garbage/run/run.sh mode change 100755 => 100644 stability-tests/daa/run/run.sh mode change 100755 => 100644 stability-tests/infra-level-garbage/run/run.sh mode change 100755 => 100644 stability-tests/install_and_test.sh mode change 100755 => 100644 stability-tests/karlsendsanity/run/run.sh mode change 100755 => 100644 stability-tests/many-tips/run/run.sh mode change 100755 => 100644 stability-tests/mempool-limits/run/run.sh mode change 100755 => 100644 stability-tests/netsync/run/run-fast.sh mode change 100755 => 100644 stability-tests/netsync/run/run-slow.sh mode change 100755 => 100644 stability-tests/netsync/run/run.sh mode change 100755 => 100644 stability-tests/orphans/run/run.sh mode change 100755 => 100644 stability-tests/reorg/run/run-full-finality-window-reorg.sh mode change 100755 => 100644 stability-tests/reorg/run/run.sh mode change 100755 => 100644 stability-tests/rpc-idle-clients/run/run.sh mode change 100755 => 100644 stability-tests/rpc-stability/run/run.sh mode change 100755 => 100644 stability-tests/run/run-fast.sh mode change 100755 => 100644 stability-tests/run/run-slow.sh mode change 100755 => 100644 stability-tests/run/run.sh mode change 100755 => 100644 stability-tests/simple-sync/run/run.sh diff --git a/app/rpc/rpchandlers/submit_transaction.go b/app/rpc/rpchandlers/submit_transaction.go index 4f52a61dd8..95abc68e52 100644 --- a/app/rpc/rpchandlers/submit_transaction.go +++ b/app/rpc/rpchandlers/submit_transaction.go @@ -28,7 +28,8 @@ func HandleSubmitTransaction(context *rpccontext.Context, _ *router.Router, requ } log.Debugf("Rejected transaction %s: %s", transactionID, err) - errorMessage := &appmessage.SubmitTransactionResponseMessage{} + // Return the ID also in the case of error, so that clients can match the response to the correct transaction submit request + errorMessage := appmessage.NewSubmitTransactionResponseMessage(transactionID.String()) errorMessage.Error = appmessage.RPCErrorf("Rejected transaction %s: %s", transactionID, err) return errorMessage, nil } diff --git a/build_and_test.sh b/build_and_test.sh old mode 100755 new mode 100644 diff --git a/cmd/karlsenwallet/daemon/server/broadcast.go b/cmd/karlsenwallet/daemon/server/broadcast.go index 189c785531..718c620681 100644 --- a/cmd/karlsenwallet/daemon/server/broadcast.go +++ b/cmd/karlsenwallet/daemon/server/broadcast.go @@ -9,6 +9,7 @@ import ( "github.com/karlsen-network/karlsend/v2/cmd/karlsenwallet/libkarlsenwallet" "github.com/karlsen-network/karlsend/v2/cmd/karlsenwallet/libkarlsenwallet/serialization" "github.com/karlsen-network/karlsend/v2/domain/consensus/model/externalapi" + "github.com/karlsen-network/karlsend/v2/domain/consensus/utils/consensushashing" "github.com/karlsen-network/karlsend/v2/infrastructure/network/rpcclient" "github.com/pkg/errors" ) @@ -60,7 +61,7 @@ func (s *server) broadcast(transactions [][]byte, isDomain bool) ([]string, erro } func sendTransaction(client *rpcclient.RPCClient, tx *externalapi.DomainTransaction) (string, error) { - submitTransactionResponse, err := client.SubmitTransaction(appmessage.DomainTransactionToRPCTransaction(tx), false) + submitTransactionResponse, err := client.SubmitTransaction(appmessage.DomainTransactionToRPCTransaction(tx), consensushashing.TransactionID(tx).String(), false) if err != nil { return "", errors.Wrapf(err, "error submitting transaction") } diff --git a/cmd/karlsenwallet/get_daemon_version.go b/cmd/karlsenwallet/get_daemon_version.go index 389707bb51..c31ad98866 100644 --- a/cmd/karlsenwallet/get_daemon_version.go +++ b/cmd/karlsenwallet/get_daemon_version.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/karlsen-network/karlsend/v2//cmd/karlsenwallet/daemon/pb" "github.com/karlsen-network/karlsend/v2/cmd/karlsenwallet/daemon/client" + "github.com/karlsen-network/karlsend/v2/cmd/karlsenwallet/daemon/pb" ) func getDaemonVersion(conf *getDaemonVersionConfig) error { diff --git a/infrastructure/network/rpcclient/rpc_send_raw_transaction.go b/infrastructure/network/rpcclient/rpc_send_raw_transaction.go index a892d07a17..36c881b825 100644 --- a/infrastructure/network/rpcclient/rpc_send_raw_transaction.go +++ b/infrastructure/network/rpcclient/rpc_send_raw_transaction.go @@ -1,23 +1,44 @@ package rpcclient import ( + "strings" + "github.com/karlsen-network/karlsend/v2/app/appmessage" ) // SubmitTransaction sends an RPC request respective to the function's name and returns the RPC server's response -func (c *RPCClient) SubmitTransaction(transaction *appmessage.RPCTransaction, allowOrphan bool) (*appmessage.SubmitTransactionResponseMessage, error) { +func (c *RPCClient) SubmitTransaction(transaction *appmessage.RPCTransaction, transactionID string, allowOrphan bool) (*appmessage.SubmitTransactionResponseMessage, error) { err := c.rpcRouter.outgoingRoute().Enqueue(appmessage.NewSubmitTransactionRequestMessage(transaction, allowOrphan)) if err != nil { return nil, err } - response, err := c.route(appmessage.CmdSubmitTransactionResponseMessage).DequeueWithTimeout(c.timeout) - if err != nil { - return nil, err - } - submitTransactionResponse := response.(*appmessage.SubmitTransactionResponseMessage) - if submitTransactionResponse.Error != nil { - return nil, c.convertRPCError(submitTransactionResponse.Error) - } + for { + response, err := c.route(appmessage.CmdSubmitTransactionResponseMessage).DequeueWithTimeout(c.timeout) + if err != nil { + return nil, err + } + submitTransactionResponse := response.(*appmessage.SubmitTransactionResponseMessage) + // Match the response to the expected ID. If they are different it means we got an old response which we + // previously timed-out on, so we log and continue waiting for the correct current response. + if submitTransactionResponse.TransactionID != transactionID { + if submitTransactionResponse.Error != nil { + // A non-updated Karlsend might return an empty ID in the case of error, so in + // such a case we fallback to checking if the error contains the expected ID + if submitTransactionResponse.TransactionID != "" || !strings.Contains(submitTransactionResponse.Error.Message, transactionID) { + log.Warnf("SubmitTransaction: received an error response for previous request: %s", submitTransactionResponse.Error) + continue + } + + } else { + log.Warnf("SubmitTransaction: received a successful response for previous request with ID %s", + submitTransactionResponse.TransactionID) + continue + } + } + if submitTransactionResponse.Error != nil { + return nil, c.convertRPCError(submitTransactionResponse.Error) + } - return submitTransactionResponse, nil + return submitTransactionResponse, nil + } } diff --git a/stability-tests/application-level-garbage/run/run.sh b/stability-tests/application-level-garbage/run/run.sh old mode 100755 new mode 100644 diff --git a/stability-tests/daa/run/run.sh b/stability-tests/daa/run/run.sh old mode 100755 new mode 100644 diff --git a/stability-tests/infra-level-garbage/run/run.sh b/stability-tests/infra-level-garbage/run/run.sh old mode 100755 new mode 100644 diff --git a/stability-tests/install_and_test.sh b/stability-tests/install_and_test.sh old mode 100755 new mode 100644 diff --git a/stability-tests/karlsendsanity/run/run.sh b/stability-tests/karlsendsanity/run/run.sh old mode 100755 new mode 100644 diff --git a/stability-tests/many-tips/run/run.sh b/stability-tests/many-tips/run/run.sh old mode 100755 new mode 100644 diff --git a/stability-tests/mempool-limits/run/run.sh b/stability-tests/mempool-limits/run/run.sh old mode 100755 new mode 100644 diff --git a/stability-tests/mempool-limits/transactions.go b/stability-tests/mempool-limits/transactions.go index 7ad61018c3..7caaecce23 100644 --- a/stability-tests/mempool-limits/transactions.go +++ b/stability-tests/mempool-limits/transactions.go @@ -86,7 +86,7 @@ func submitAnAmountOfTransactionsToTheMempool(t *testing.T, rpcClient *rpcclient for i, transaction := range transactions { rpcTransaction := appmessage.DomainTransactionToRPCTransaction(transaction) - _, err := rpcClient.SubmitTransaction(rpcTransaction, false) + _, err := rpcClient.SubmitTransaction(rpcTransaction, consensushashing.TransactionID(transaction).String(), false) if err != nil { if ignoreOrphanRejects && strings.Contains(err.Error(), "orphan") { continue diff --git a/stability-tests/netsync/run/run-fast.sh b/stability-tests/netsync/run/run-fast.sh old mode 100755 new mode 100644 diff --git a/stability-tests/netsync/run/run-slow.sh b/stability-tests/netsync/run/run-slow.sh old mode 100755 new mode 100644 diff --git a/stability-tests/netsync/run/run.sh b/stability-tests/netsync/run/run.sh old mode 100755 new mode 100644 diff --git a/stability-tests/orphans/run/run.sh b/stability-tests/orphans/run/run.sh old mode 100755 new mode 100644 diff --git a/stability-tests/reorg/run/run-full-finality-window-reorg.sh b/stability-tests/reorg/run/run-full-finality-window-reorg.sh old mode 100755 new mode 100644 diff --git a/stability-tests/reorg/run/run.sh b/stability-tests/reorg/run/run.sh old mode 100755 new mode 100644 diff --git a/stability-tests/rpc-idle-clients/run/run.sh b/stability-tests/rpc-idle-clients/run/run.sh old mode 100755 new mode 100644 diff --git a/stability-tests/rpc-stability/run/run.sh b/stability-tests/rpc-stability/run/run.sh old mode 100755 new mode 100644 diff --git a/stability-tests/run/run-fast.sh b/stability-tests/run/run-fast.sh old mode 100755 new mode 100644 diff --git a/stability-tests/run/run-slow.sh b/stability-tests/run/run-slow.sh old mode 100755 new mode 100644 diff --git a/stability-tests/run/run.sh b/stability-tests/run/run.sh old mode 100755 new mode 100644 diff --git a/stability-tests/simple-sync/run/run.sh b/stability-tests/simple-sync/run/run.sh old mode 100755 new mode 100644 diff --git a/testing/integration/tx_relay_test.go b/testing/integration/tx_relay_test.go index 755bcb666a..4a6dc4e9d0 100644 --- a/testing/integration/tx_relay_test.go +++ b/testing/integration/tx_relay_test.go @@ -53,7 +53,7 @@ func TestTxRelay(t *testing.T) { msgTx := generateTx(t, secondBlock.Transactions[transactionhelper.CoinbaseTransactionIndex], payer, payee) domainTransaction := appmessage.MsgTxToDomainTransaction(msgTx) rpcTransaction := appmessage.DomainTransactionToRPCTransaction(domainTransaction) - response, err := payer.rpcClient.SubmitTransaction(rpcTransaction, false) + response, err := payer.rpcClient.SubmitTransaction(rpcTransaction, consensushashing.TransactionID(domainTransaction).String(), false) if err != nil { t.Fatalf("Error submitting transaction: %+v", err) } diff --git a/testing/integration/utxo_index_test.go b/testing/integration/utxo_index_test.go index 5040697a6d..7fdeda5471 100644 --- a/testing/integration/utxo_index_test.go +++ b/testing/integration/utxo_index_test.go @@ -88,8 +88,8 @@ func TestUTXOIndex(t *testing.T) { // Submit a few transactions that spends some UTXOs const transactionAmountToSpend = 5 for i := 0; i < transactionAmountToSpend; i++ { - rpcTransaction := buildTransactionForUTXOIndexTest(t, notificationEntries[i]) - _, err = karlsend.rpcClient.SubmitTransaction(rpcTransaction, false) + rpcTransaction, transactionID := buildTransactionForUTXOIndexTest(t, notificationEntries[i]) + _, err = karlsend.rpcClient.SubmitTransaction(rpcTransaction, transactionID, false) if err != nil { t.Fatalf("Error submitting transaction: %s", err) } @@ -171,7 +171,7 @@ func TestUTXOIndex(t *testing.T) { } } -func buildTransactionForUTXOIndexTest(t *testing.T, entry *appmessage.UTXOsByAddressesEntry) *appmessage.RPCTransaction { +func buildTransactionForUTXOIndexTest(t *testing.T, entry *appmessage.UTXOsByAddressesEntry) (*appmessage.RPCTransaction, string) { transactionIDBytes, err := hex.DecodeString(entry.Outpoint.TransactionID) if err != nil { t.Fatalf("Error decoding transaction ID: %s", err) @@ -224,5 +224,5 @@ func buildTransactionForUTXOIndexTest(t *testing.T, entry *appmessage.UTXOsByAdd msgTx.TxIn[0].SignatureScript = signatureScript domainTransaction := appmessage.MsgTxToDomainTransaction(msgTx) - return appmessage.DomainTransactionToRPCTransaction(domainTransaction) + return appmessage.DomainTransactionToRPCTransaction(domainTransaction), consensushashing.TransactionID(domainTransaction).String() } From fa307bc01e2074b0c08f86b0b7de093dfa15cd17 Mon Sep 17 00:00:00 2001 From: Leon1777 <168653957+Leon1777@users.noreply.github.com> Date: Thu, 19 Sep 2024 00:50:14 +0200 Subject: [PATCH 06/13] fix deprecated Node.js warning https://github.com/actions/setup-go The V5 edition of the action offers: Upgraded Node.js runtime from node16 to node20 --- .github/workflows/deploy.yaml | 2 +- .github/workflows/tests.yaml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 0184c156a6..5f2726c8d1 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -24,7 +24,7 @@ jobs: uses: actions/checkout@v4 - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: 1.21 diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index bc3a63a763..ff2752c1b5 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -36,7 +36,7 @@ jobs: swap-size-gb: 12 - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: 1.21 @@ -59,7 +59,7 @@ jobs: swap-size-gb: 12 - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: 1.21 @@ -91,7 +91,7 @@ jobs: uses: actions/checkout@v4 - name: Setup Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: 1.21 From f5348da72ce09a07dc9c570395eed601bfc8677d Mon Sep 17 00:00:00 2001 From: Leon1777 <168653957+Leon1777@users.noreply.github.com> Date: Thu, 19 Sep 2024 00:50:47 +0200 Subject: [PATCH 07/13] bump version to v2.2.1 --- version/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version/version.go b/version/version.go index 8fdaa82f3a..e47c964b86 100644 --- a/version/version.go +++ b/version/version.go @@ -11,7 +11,7 @@ const validCharacters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrs const ( appMajor uint = 2 appMinor uint = 2 - appPatch uint = 0 + appPatch uint = 1 ) // appBuild is defined as a variable so it can be overridden during the build From 212ebee1719cfe5239cf9538c9ee083f29b8977a Mon Sep 17 00:00:00 2001 From: Leon1777 <168653957+Leon1777@users.noreply.github.com> Date: Thu, 19 Sep 2024 00:59:08 +0200 Subject: [PATCH 08/13] fix incorrect import path - corrected the import path for the version package --- cmd/karlsenwallet/daemon/server/server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/karlsenwallet/daemon/server/server.go b/cmd/karlsenwallet/daemon/server/server.go index e86b51215b..82eb333951 100644 --- a/cmd/karlsenwallet/daemon/server/server.go +++ b/cmd/karlsenwallet/daemon/server/server.go @@ -8,7 +8,7 @@ import ( "sync/atomic" "time" - "github.com/karlsen-network/karlsend/v2/domain/version" + "github.com/karlsen-network/karlsend/v2/version" "github.com/karlsen-network/karlsend/v2/domain/consensus/model/externalapi" From 3b6b1c81ab0b0e2949e2b0338365f8a288947930 Mon Sep 17 00:00:00 2001 From: Leon1777 Date: Thu, 19 Sep 2024 02:12:37 +0200 Subject: [PATCH 09/13] Fix executable permissions --- build_and_test.sh | 0 stability-tests/application-level-garbage/run/run.sh | 0 stability-tests/daa/run/run.sh | 0 stability-tests/infra-level-garbage/run/run.sh | 0 stability-tests/install_and_test.sh | 0 stability-tests/karlsendsanity/run/run.sh | 0 stability-tests/many-tips/run/run.sh | 0 stability-tests/mempool-limits/run/run.sh | 0 stability-tests/netsync/run/run-fast.sh | 0 stability-tests/netsync/run/run-slow.sh | 0 stability-tests/netsync/run/run.sh | 0 stability-tests/orphans/run/run.sh | 0 stability-tests/reorg/run/run-full-finality-window-reorg.sh | 0 stability-tests/reorg/run/run.sh | 0 stability-tests/rpc-idle-clients/run/run.sh | 0 stability-tests/rpc-stability/run/run.sh | 0 stability-tests/run/run-fast.sh | 0 stability-tests/run/run-slow.sh | 0 stability-tests/run/run.sh | 0 stability-tests/simple-sync/run/run.sh | 0 20 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 build_and_test.sh mode change 100644 => 100755 stability-tests/application-level-garbage/run/run.sh mode change 100644 => 100755 stability-tests/daa/run/run.sh mode change 100644 => 100755 stability-tests/infra-level-garbage/run/run.sh mode change 100644 => 100755 stability-tests/install_and_test.sh mode change 100644 => 100755 stability-tests/karlsendsanity/run/run.sh mode change 100644 => 100755 stability-tests/many-tips/run/run.sh mode change 100644 => 100755 stability-tests/mempool-limits/run/run.sh mode change 100644 => 100755 stability-tests/netsync/run/run-fast.sh mode change 100644 => 100755 stability-tests/netsync/run/run-slow.sh mode change 100644 => 100755 stability-tests/netsync/run/run.sh mode change 100644 => 100755 stability-tests/orphans/run/run.sh mode change 100644 => 100755 stability-tests/reorg/run/run-full-finality-window-reorg.sh mode change 100644 => 100755 stability-tests/reorg/run/run.sh mode change 100644 => 100755 stability-tests/rpc-idle-clients/run/run.sh mode change 100644 => 100755 stability-tests/rpc-stability/run/run.sh mode change 100644 => 100755 stability-tests/run/run-fast.sh mode change 100644 => 100755 stability-tests/run/run-slow.sh mode change 100644 => 100755 stability-tests/run/run.sh mode change 100644 => 100755 stability-tests/simple-sync/run/run.sh diff --git a/build_and_test.sh b/build_and_test.sh old mode 100644 new mode 100755 diff --git a/stability-tests/application-level-garbage/run/run.sh b/stability-tests/application-level-garbage/run/run.sh old mode 100644 new mode 100755 diff --git a/stability-tests/daa/run/run.sh b/stability-tests/daa/run/run.sh old mode 100644 new mode 100755 diff --git a/stability-tests/infra-level-garbage/run/run.sh b/stability-tests/infra-level-garbage/run/run.sh old mode 100644 new mode 100755 diff --git a/stability-tests/install_and_test.sh b/stability-tests/install_and_test.sh old mode 100644 new mode 100755 diff --git a/stability-tests/karlsendsanity/run/run.sh b/stability-tests/karlsendsanity/run/run.sh old mode 100644 new mode 100755 diff --git a/stability-tests/many-tips/run/run.sh b/stability-tests/many-tips/run/run.sh old mode 100644 new mode 100755 diff --git a/stability-tests/mempool-limits/run/run.sh b/stability-tests/mempool-limits/run/run.sh old mode 100644 new mode 100755 diff --git a/stability-tests/netsync/run/run-fast.sh b/stability-tests/netsync/run/run-fast.sh old mode 100644 new mode 100755 diff --git a/stability-tests/netsync/run/run-slow.sh b/stability-tests/netsync/run/run-slow.sh old mode 100644 new mode 100755 diff --git a/stability-tests/netsync/run/run.sh b/stability-tests/netsync/run/run.sh old mode 100644 new mode 100755 diff --git a/stability-tests/orphans/run/run.sh b/stability-tests/orphans/run/run.sh old mode 100644 new mode 100755 diff --git a/stability-tests/reorg/run/run-full-finality-window-reorg.sh b/stability-tests/reorg/run/run-full-finality-window-reorg.sh old mode 100644 new mode 100755 diff --git a/stability-tests/reorg/run/run.sh b/stability-tests/reorg/run/run.sh old mode 100644 new mode 100755 diff --git a/stability-tests/rpc-idle-clients/run/run.sh b/stability-tests/rpc-idle-clients/run/run.sh old mode 100644 new mode 100755 diff --git a/stability-tests/rpc-stability/run/run.sh b/stability-tests/rpc-stability/run/run.sh old mode 100644 new mode 100755 diff --git a/stability-tests/run/run-fast.sh b/stability-tests/run/run-fast.sh old mode 100644 new mode 100755 diff --git a/stability-tests/run/run-slow.sh b/stability-tests/run/run-slow.sh old mode 100644 new mode 100755 diff --git a/stability-tests/run/run.sh b/stability-tests/run/run.sh old mode 100644 new mode 100755 diff --git a/stability-tests/simple-sync/run/run.sh b/stability-tests/simple-sync/run/run.sh old mode 100644 new mode 100755 From cc0d6c0d7f44845019d8344d19b3a17f6a637363 Mon Sep 17 00:00:00 2001 From: Leon1777 Date: Thu, 19 Sep 2024 02:13:18 +0200 Subject: [PATCH 10/13] rebuild pb files with protoc v3.12.3 and grpc v1.2.0 regenerated karlsenwalletd.pb.go and karlsenwalletd_grpc.pb.go using protoc-gen-go-grpc v1.2.0 and protoc v3.12.3. resolves compatibility issues with newer gRPC methods like grpc.StaticMethod. --- .../daemon/pb/karlsenwalletd.pb.go | 2 +- .../daemon/pb/karlsenwalletd_grpc.pb.go | 90 ++++++------------- 2 files changed, 29 insertions(+), 63 deletions(-) diff --git a/cmd/karlsenwallet/daemon/pb/karlsenwalletd.pb.go b/cmd/karlsenwallet/daemon/pb/karlsenwalletd.pb.go index f65eb8be1d..6263dfe799 100644 --- a/cmd/karlsenwallet/daemon/pb/karlsenwalletd.pb.go +++ b/cmd/karlsenwallet/daemon/pb/karlsenwalletd.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.34.2 -// protoc v3.12.4 +// protoc v3.12.3 // source: karlsenwalletd.proto package pb diff --git a/cmd/karlsenwallet/daemon/pb/karlsenwalletd_grpc.pb.go b/cmd/karlsenwallet/daemon/pb/karlsenwalletd_grpc.pb.go index cfcf8c09db..6f1038d489 100644 --- a/cmd/karlsenwallet/daemon/pb/karlsenwalletd_grpc.pb.go +++ b/cmd/karlsenwallet/daemon/pb/karlsenwalletd_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.5.1 -// - protoc v3.12.4 +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.12.3 // source: karlsenwalletd.proto package pb @@ -15,21 +15,8 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.64.0 or later. -const _ = grpc.SupportPackageIsVersion9 - -const ( - Karlsenwalletd_GetBalance_FullMethodName = "/karlsenwalletd.karlsenwalletd/GetBalance" - Karlsenwalletd_GetExternalSpendableUTXOs_FullMethodName = "/karlsenwalletd.karlsenwalletd/GetExternalSpendableUTXOs" - Karlsenwalletd_CreateUnsignedTransactions_FullMethodName = "/karlsenwalletd.karlsenwalletd/CreateUnsignedTransactions" - Karlsenwalletd_ShowAddresses_FullMethodName = "/karlsenwalletd.karlsenwalletd/ShowAddresses" - Karlsenwalletd_NewAddress_FullMethodName = "/karlsenwalletd.karlsenwalletd/NewAddress" - Karlsenwalletd_Shutdown_FullMethodName = "/karlsenwalletd.karlsenwalletd/Shutdown" - Karlsenwalletd_Broadcast_FullMethodName = "/karlsenwalletd.karlsenwalletd/Broadcast" - Karlsenwalletd_Send_FullMethodName = "/karlsenwalletd.karlsenwalletd/Send" - Karlsenwalletd_Sign_FullMethodName = "/karlsenwalletd.karlsenwalletd/Sign" - Karlsenwalletd_GetVersion_FullMethodName = "/karlsenwalletd.karlsenwalletd/GetVersion" -) +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 // KarlsenwalletdClient is the client API for Karlsenwalletd service. // @@ -58,9 +45,8 @@ func NewKarlsenwalletdClient(cc grpc.ClientConnInterface) KarlsenwalletdClient { } func (c *karlsenwalletdClient) GetBalance(ctx context.Context, in *GetBalanceRequest, opts ...grpc.CallOption) (*GetBalanceResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetBalanceResponse) - err := c.cc.Invoke(ctx, Karlsenwalletd_GetBalance_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/karlsenwalletd.karlsenwalletd/GetBalance", in, out, opts...) if err != nil { return nil, err } @@ -68,9 +54,8 @@ func (c *karlsenwalletdClient) GetBalance(ctx context.Context, in *GetBalanceReq } func (c *karlsenwalletdClient) GetExternalSpendableUTXOs(ctx context.Context, in *GetExternalSpendableUTXOsRequest, opts ...grpc.CallOption) (*GetExternalSpendableUTXOsResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetExternalSpendableUTXOsResponse) - err := c.cc.Invoke(ctx, Karlsenwalletd_GetExternalSpendableUTXOs_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/karlsenwalletd.karlsenwalletd/GetExternalSpendableUTXOs", in, out, opts...) if err != nil { return nil, err } @@ -78,9 +63,8 @@ func (c *karlsenwalletdClient) GetExternalSpendableUTXOs(ctx context.Context, in } func (c *karlsenwalletdClient) CreateUnsignedTransactions(ctx context.Context, in *CreateUnsignedTransactionsRequest, opts ...grpc.CallOption) (*CreateUnsignedTransactionsResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(CreateUnsignedTransactionsResponse) - err := c.cc.Invoke(ctx, Karlsenwalletd_CreateUnsignedTransactions_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/karlsenwalletd.karlsenwalletd/CreateUnsignedTransactions", in, out, opts...) if err != nil { return nil, err } @@ -88,9 +72,8 @@ func (c *karlsenwalletdClient) CreateUnsignedTransactions(ctx context.Context, i } func (c *karlsenwalletdClient) ShowAddresses(ctx context.Context, in *ShowAddressesRequest, opts ...grpc.CallOption) (*ShowAddressesResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ShowAddressesResponse) - err := c.cc.Invoke(ctx, Karlsenwalletd_ShowAddresses_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/karlsenwalletd.karlsenwalletd/ShowAddresses", in, out, opts...) if err != nil { return nil, err } @@ -98,9 +81,8 @@ func (c *karlsenwalletdClient) ShowAddresses(ctx context.Context, in *ShowAddres } func (c *karlsenwalletdClient) NewAddress(ctx context.Context, in *NewAddressRequest, opts ...grpc.CallOption) (*NewAddressResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(NewAddressResponse) - err := c.cc.Invoke(ctx, Karlsenwalletd_NewAddress_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/karlsenwalletd.karlsenwalletd/NewAddress", in, out, opts...) if err != nil { return nil, err } @@ -108,9 +90,8 @@ func (c *karlsenwalletdClient) NewAddress(ctx context.Context, in *NewAddressReq } func (c *karlsenwalletdClient) Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*ShutdownResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ShutdownResponse) - err := c.cc.Invoke(ctx, Karlsenwalletd_Shutdown_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/karlsenwalletd.karlsenwalletd/Shutdown", in, out, opts...) if err != nil { return nil, err } @@ -118,9 +99,8 @@ func (c *karlsenwalletdClient) Shutdown(ctx context.Context, in *ShutdownRequest } func (c *karlsenwalletdClient) Broadcast(ctx context.Context, in *BroadcastRequest, opts ...grpc.CallOption) (*BroadcastResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(BroadcastResponse) - err := c.cc.Invoke(ctx, Karlsenwalletd_Broadcast_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/karlsenwalletd.karlsenwalletd/Broadcast", in, out, opts...) if err != nil { return nil, err } @@ -128,9 +108,8 @@ func (c *karlsenwalletdClient) Broadcast(ctx context.Context, in *BroadcastReque } func (c *karlsenwalletdClient) Send(ctx context.Context, in *SendRequest, opts ...grpc.CallOption) (*SendResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(SendResponse) - err := c.cc.Invoke(ctx, Karlsenwalletd_Send_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/karlsenwalletd.karlsenwalletd/Send", in, out, opts...) if err != nil { return nil, err } @@ -138,9 +117,8 @@ func (c *karlsenwalletdClient) Send(ctx context.Context, in *SendRequest, opts . } func (c *karlsenwalletdClient) Sign(ctx context.Context, in *SignRequest, opts ...grpc.CallOption) (*SignResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(SignResponse) - err := c.cc.Invoke(ctx, Karlsenwalletd_Sign_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/karlsenwalletd.karlsenwalletd/Sign", in, out, opts...) if err != nil { return nil, err } @@ -148,9 +126,8 @@ func (c *karlsenwalletdClient) Sign(ctx context.Context, in *SignRequest, opts . } func (c *karlsenwalletdClient) GetVersion(ctx context.Context, in *GetVersionRequest, opts ...grpc.CallOption) (*GetVersionResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetVersionResponse) - err := c.cc.Invoke(ctx, Karlsenwalletd_GetVersion_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, "/karlsenwalletd.karlsenwalletd/GetVersion", in, out, opts...) if err != nil { return nil, err } @@ -159,7 +136,7 @@ func (c *karlsenwalletdClient) GetVersion(ctx context.Context, in *GetVersionReq // KarlsenwalletdServer is the server API for Karlsenwalletd service. // All implementations must embed UnimplementedKarlsenwalletdServer -// for forward compatibility. +// for forward compatibility type KarlsenwalletdServer interface { GetBalance(context.Context, *GetBalanceRequest) (*GetBalanceResponse, error) GetExternalSpendableUTXOs(context.Context, *GetExternalSpendableUTXOsRequest) (*GetExternalSpendableUTXOsResponse, error) @@ -176,12 +153,9 @@ type KarlsenwalletdServer interface { mustEmbedUnimplementedKarlsenwalletdServer() } -// UnimplementedKarlsenwalletdServer must be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedKarlsenwalletdServer struct{} +// UnimplementedKarlsenwalletdServer must be embedded to have forward compatible implementations. +type UnimplementedKarlsenwalletdServer struct { +} func (UnimplementedKarlsenwalletdServer) GetBalance(context.Context, *GetBalanceRequest) (*GetBalanceResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetBalance not implemented") @@ -214,7 +188,6 @@ func (UnimplementedKarlsenwalletdServer) GetVersion(context.Context, *GetVersion return nil, status.Errorf(codes.Unimplemented, "method GetVersion not implemented") } func (UnimplementedKarlsenwalletdServer) mustEmbedUnimplementedKarlsenwalletdServer() {} -func (UnimplementedKarlsenwalletdServer) testEmbeddedByValue() {} // UnsafeKarlsenwalletdServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to KarlsenwalletdServer will @@ -224,13 +197,6 @@ type UnsafeKarlsenwalletdServer interface { } func RegisterKarlsenwalletdServer(s grpc.ServiceRegistrar, srv KarlsenwalletdServer) { - // If the following call pancis, it indicates UnimplementedKarlsenwalletdServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } s.RegisterService(&Karlsenwalletd_ServiceDesc, srv) } @@ -244,7 +210,7 @@ func _Karlsenwalletd_GetBalance_Handler(srv interface{}, ctx context.Context, de } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: Karlsenwalletd_GetBalance_FullMethodName, + FullMethod: "/karlsenwalletd.karlsenwalletd/GetBalance", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(KarlsenwalletdServer).GetBalance(ctx, req.(*GetBalanceRequest)) @@ -262,7 +228,7 @@ func _Karlsenwalletd_GetExternalSpendableUTXOs_Handler(srv interface{}, ctx cont } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: Karlsenwalletd_GetExternalSpendableUTXOs_FullMethodName, + FullMethod: "/karlsenwalletd.karlsenwalletd/GetExternalSpendableUTXOs", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(KarlsenwalletdServer).GetExternalSpendableUTXOs(ctx, req.(*GetExternalSpendableUTXOsRequest)) @@ -280,7 +246,7 @@ func _Karlsenwalletd_CreateUnsignedTransactions_Handler(srv interface{}, ctx con } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: Karlsenwalletd_CreateUnsignedTransactions_FullMethodName, + FullMethod: "/karlsenwalletd.karlsenwalletd/CreateUnsignedTransactions", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(KarlsenwalletdServer).CreateUnsignedTransactions(ctx, req.(*CreateUnsignedTransactionsRequest)) @@ -298,7 +264,7 @@ func _Karlsenwalletd_ShowAddresses_Handler(srv interface{}, ctx context.Context, } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: Karlsenwalletd_ShowAddresses_FullMethodName, + FullMethod: "/karlsenwalletd.karlsenwalletd/ShowAddresses", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(KarlsenwalletdServer).ShowAddresses(ctx, req.(*ShowAddressesRequest)) @@ -316,7 +282,7 @@ func _Karlsenwalletd_NewAddress_Handler(srv interface{}, ctx context.Context, de } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: Karlsenwalletd_NewAddress_FullMethodName, + FullMethod: "/karlsenwalletd.karlsenwalletd/NewAddress", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(KarlsenwalletdServer).NewAddress(ctx, req.(*NewAddressRequest)) @@ -334,7 +300,7 @@ func _Karlsenwalletd_Shutdown_Handler(srv interface{}, ctx context.Context, dec } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: Karlsenwalletd_Shutdown_FullMethodName, + FullMethod: "/karlsenwalletd.karlsenwalletd/Shutdown", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(KarlsenwalletdServer).Shutdown(ctx, req.(*ShutdownRequest)) @@ -352,7 +318,7 @@ func _Karlsenwalletd_Broadcast_Handler(srv interface{}, ctx context.Context, dec } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: Karlsenwalletd_Broadcast_FullMethodName, + FullMethod: "/karlsenwalletd.karlsenwalletd/Broadcast", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(KarlsenwalletdServer).Broadcast(ctx, req.(*BroadcastRequest)) @@ -370,7 +336,7 @@ func _Karlsenwalletd_Send_Handler(srv interface{}, ctx context.Context, dec func } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: Karlsenwalletd_Send_FullMethodName, + FullMethod: "/karlsenwalletd.karlsenwalletd/Send", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(KarlsenwalletdServer).Send(ctx, req.(*SendRequest)) @@ -388,7 +354,7 @@ func _Karlsenwalletd_Sign_Handler(srv interface{}, ctx context.Context, dec func } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: Karlsenwalletd_Sign_FullMethodName, + FullMethod: "/karlsenwalletd.karlsenwalletd/Sign", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(KarlsenwalletdServer).Sign(ctx, req.(*SignRequest)) @@ -406,7 +372,7 @@ func _Karlsenwalletd_GetVersion_Handler(srv interface{}, ctx context.Context, de } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: Karlsenwalletd_GetVersion_FullMethodName, + FullMethod: "/karlsenwalletd.karlsenwalletd/GetVersion", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(KarlsenwalletdServer).GetVersion(ctx, req.(*GetVersionRequest)) From b6ebc60f860d80b7b2aa3afcf89aabdac097f45e Mon Sep 17 00:00:00 2001 From: Leon1777 <168653957+Leon1777@users.noreply.github.com> Date: Thu, 19 Sep 2024 02:28:09 +0200 Subject: [PATCH 11/13] updated workflows to use Go 1.23.1 --- .github/workflows/deploy.yaml | 2 +- .github/workflows/tests.yaml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 5f2726c8d1..99f79f78a4 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -26,7 +26,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v5 with: - go-version: 1.21 + go-version: 1.23.1 - name: Update sources if: matrix.TARGET == 'linux/aarch64' || matrix.TARGET == 'windows/x64' diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index ff2752c1b5..ff346c5cfc 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -38,7 +38,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v5 with: - go-version: 1.21 + go-version: 1.23.1 - name: Test shell: bash @@ -61,7 +61,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v5 with: - go-version: 1.21 + go-version: 1.23.1 - name: Checkout uses: actions/checkout@v4 @@ -93,7 +93,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v5 with: - go-version: 1.21 + go-version: 1.23.1 - name: Delete the stability tests from coverage run: rm -r stability-tests From ab46067b8980a9884c85e11a10a18ff4494dfcc7 Mon Sep 17 00:00:00 2001 From: Leon1777 <168653957+Leon1777@users.noreply.github.com> Date: Thu, 19 Sep 2024 16:31:28 +0200 Subject: [PATCH 12/13] KIP9 basic wallet compatibility * introduce min change target * clarify wallet help messages for from-address and send-all --- cmd/karlsenwallet/config.go | 4 ++-- .../daemon/server/create_unsigned_transaction.go | 14 +++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/cmd/karlsenwallet/config.go b/cmd/karlsenwallet/config.go index b3df8030f2..e7a85d30b5 100644 --- a/cmd/karlsenwallet/config.go +++ b/cmd/karlsenwallet/config.go @@ -60,9 +60,9 @@ type sendConfig struct { Password string `long:"password" short:"p" description:"Wallet password"` DaemonAddress string `long:"daemonaddress" short:"d" description:"Wallet daemon server to connect to"` ToAddress string `long:"to-address" short:"t" description:"The public address to send Karlsen to" required:"true"` - FromAddresses []string `long:"from-address" short:"a" description:"Specific public address to send Karlsen from. Use multiple times to accept several addresses" required:"false"` + FromAddresses []string `long:"from-address" short:"a" description:"Specific public address to send Karlsen from. Repeat multiple times (adding -a before each) to accept several addresses" required:"false"` SendAmount string `long:"send-amount" short:"v" description:"An amount to send in Karlsen (e.g. 1234.12345678)"` - IsSendAll bool `long:"send-all" description:"Send all the Karlsen in the wallet (mutually exclusive with --send-amount)"` + IsSendAll bool `long:"send-all" description:"Send all the Karlsen in the wallet (mutually exclusive with --send-amount). If --from-address was used, will send all only from the specified addresses."` UseExistingChangeAddress bool `long:"use-existing-change-address" short:"u" description:"Will use an existing change address (in case no change address was ever used, it will use a new one)"` Verbose bool `long:"show-serialized" short:"s" description:"Show a list of hex encoded sent transactions"` config.NetworkFlags diff --git a/cmd/karlsenwallet/daemon/server/create_unsigned_transaction.go b/cmd/karlsenwallet/daemon/server/create_unsigned_transaction.go index 79585fb62d..3558d067a5 100644 --- a/cmd/karlsenwallet/daemon/server/create_unsigned_transaction.go +++ b/cmd/karlsenwallet/daemon/server/create_unsigned_transaction.go @@ -14,6 +14,11 @@ import ( // TODO: Implement a better fee estimation mechanism const feePerInput = 10000 +// The minimal change amount to target in order to avoid large storage mass (see KIP9 for more details). +// By having at least 0.2KLS in the change output we make sure that every transaction with send value >= 0.2KLS +// should succeed (at most 50K storage mass for each output, thus overall lower than standard mass upper bound which is 100K gram) +const minChangeTarget = constants.SompiPerKarlsen / 5 + func (s *server) CreateUnsignedTransactions(_ context.Context, request *pb.CreateUnsignedTransactionsRequest) ( *pb.CreateUnsignedTransactionsResponse, error, ) { @@ -122,11 +127,10 @@ func (s *server) selectUTXOs(spendAmount uint64, isSendAll bool, feePerInput uin fee := feePerInput * uint64(len(selectedUTXOs)) totalSpend := spendAmount + fee - // Two break cases (if not send all): - // 1. totalValue == totalSpend, so there's no change needed -> number of outputs = 1, so a single input is sufficient - // 2. totalValue > totalSpend, so there will be change and 2 outputs, therefor in order to not struggle with new dust - // rules we try and find at least 2 inputs (even though the next one is not necessary in terms of spend value) - if !isSendAll && (totalValue == totalSpend || (totalValue > totalSpend && len(selectedUTXOs) > 1)) { + // 2. totalValue > totalSpend, so there will be change and 2 outputs, therefor in order to not struggle with -- + // 2.1 go-nodes dust patch we try and find at least 2 inputs (even though the next one is not necessary in terms of spend value) + // 2.2 KIP9 we try and make sure that the change amount is not too small + if !isSendAll && (totalValue == totalSpend || (totalValue >= totalSpend+minChangeTarget && len(selectedUTXOs) > 1)) { break } } From 07c174d825fc66bd2623b59a8c65cac161712e56 Mon Sep 17 00:00:00 2001 From: Leon1777 <168653957+Leon1777@users.noreply.github.com> Date: Thu, 19 Sep 2024 16:56:05 +0200 Subject: [PATCH 13/13] update changelog --- changelog.txt | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/changelog.txt b/changelog.txt index 55a5303e29..16136a0e24 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,55 @@ +Karlsend v2.2.1 - 2024-09-19 +============================ + +* Wallet-related improvements and fixes + +Karlsend v2.2.0 - 2024-09-03 +============================ + +* Critical bug fix for difficulty adjustment after hardfork block + +* Adjust difficulty managment between rusty and golang nodes during the first block window +* fix for integration test diff manager signature +* difficulty adjustment window fix +* Hardfork in devnet and simnet after the difficulty adjustment window +* Fix simnet pruning test + +Karlsend v2.1.0 - 2024-08-29 +============================ + +* Fishhash plus implementation with hard fork procedure +* hard fork procedure from `khashv1` to `khashv2` +* HF procedure with diff adjustment +* Mainnet HFDAAScore set to 26962009 to switch to `khashv2` + +* First `fishhash` tests +* refresh seeder url +* add minor version +* fix logging +* Fix issue on word32 usage in kernel mixing step +* Fix the dataset and light cache generation +* Code cleanup and dag generation correct logging +* Added lock on mainnet connection +* Remove blocking tests on block version because node contains both algorithm +* fix critical bug in matrix generation +* align with rusty block version test +* Removed periodic race detection workflow +* Added `HFDAAScore` to `simnet` to pass tests +* Fixed pruning_test in `simnet` and `devnet` genesis from Rust node +* Fixed remaining integration tests and Go modules update +* Use 4-char abbreviation as rest of KLS logging system (POW->POWK) +* Increase windows runner pagefile to 32gb +* Remove Go cache in test workflow due to its constant failures +* Increase code coverage timeout to 120m due to `khashv2` +* Increase timeout in integration tests and sequential execution +* Fixed `BlockVersionKHashV2` in debug output and removed linebreak +* Moving `khashv2` pre-computed dag file during stability tests +* Give orphans stability test more time to process blocks +* Increase Linux swapfile size in GitHub runner to avoid OOM +* Increase swap size for code coverage to support `khashv2` +* Version bump to 2.1.0 for `khashv2` +* Updated README.md and added `khashv2` paragraph + Karlsend v1.2.0 - 2024-03-07 ============================