diff --git a/cmd/kaspawallet/config.go b/cmd/kaspawallet/config.go index 518ef351b..ec3c8b83c 100644 --- a/cmd/kaspawallet/config.go +++ b/cmd/kaspawallet/config.go @@ -59,6 +59,7 @@ type sendConfig struct { FromAddresses []string `long:"from-address" short:"a" description:"Specific public address to send Kaspa from. Use multiple times to accept several addresses" required:"false"` SendAmount float64 `long:"send-amount" short:"v" description:"An amount to send in Kaspa (e.g. 1234.12345678)" required:"true"` 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/kaspawallet/daemon/client/client.go b/cmd/kaspawallet/daemon/client/client.go index 6cfd38a32..bc25753ed 100644 --- a/cmd/kaspawallet/daemon/client/client.go +++ b/cmd/kaspawallet/daemon/client/client.go @@ -2,6 +2,7 @@ package client import ( "context" + "github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/server" "time" "github.com/pkg/errors" @@ -16,7 +17,7 @@ func Connect(address string) (pb.KaspawalletdClient, func(), error) { ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() - conn, err := grpc.DialContext(ctx, address, grpc.WithInsecure(), grpc.WithBlock()) + conn, err := grpc.DialContext(ctx, address, grpc.WithInsecure(), grpc.WithBlock(), grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(server.MaxDaemonSendMsgSize))) if err != nil { if errors.Is(err, context.DeadlineExceeded) { return nil, nil, errors.New("kaspawallet daemon is not running, start it with `kaspawallet start-daemon`") diff --git a/cmd/kaspawallet/daemon/pb/kaspawalletd.pb.go b/cmd/kaspawallet/daemon/pb/kaspawalletd.pb.go index 032d37e8e..10098cb3f 100644 --- a/cmd/kaspawallet/daemon/pb/kaspawalletd.pb.go +++ b/cmd/kaspawallet/daemon/pb/kaspawalletd.pb.go @@ -1,13 +1,12 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.25.0 +// protoc-gen-go v1.27.1 // protoc v3.12.3 // source: kaspawalletd.proto package pb import ( - proto "github.com/golang/protobuf/proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" @@ -21,10 +20,6 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// This is a compile-time assertion that a sufficiently up-to-date version -// of the legacy proto package is being used. -const _ = proto.ProtoPackageIsVersion4 - type GetBalanceRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1078,7 +1073,8 @@ type SendResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - TxIDs []string `protobuf:"bytes,1,rep,name=txIDs,proto3" json:"txIDs,omitempty"` + TxIDs []string `protobuf:"bytes,1,rep,name=txIDs,proto3" json:"txIDs,omitempty"` + SignedTransactions [][]byte `protobuf:"bytes,2,rep,name=signedTransactions,proto3" json:"signedTransactions,omitempty"` } func (x *SendResponse) Reset() { @@ -1120,6 +1116,13 @@ func (x *SendResponse) GetTxIDs() []string { return nil } +func (x *SendResponse) GetSignedTransactions() [][]byte { + if x != nil { + return x.SignedTransactions + } + return nil +} + // Since SignRequest contains a password - this command should only be used on a trusted or secure connection type SignRequest struct { state protoimpl.MessageState @@ -1333,9 +1336,12 @@ var file_kaspawalletd_proto_rawDesc = []byte{ 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x75, 0x73, 0x65, 0x45, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x22, 0x24, 0x0a, 0x0c, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x65, 0x73, 0x73, 0x22, 0x54, 0x0a, 0x0c, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x78, 0x49, 0x44, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x05, 0x74, 0x78, 0x49, 0x44, 0x73, 0x22, 0x5d, 0x0a, 0x0b, 0x53, 0x69, 0x67, + 0x28, 0x09, 0x52, 0x05, 0x74, 0x78, 0x49, 0x44, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x73, 0x69, 0x67, + 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x12, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x5d, 0x0a, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x14, 0x75, 0x6e, 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, 0x14, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, diff --git a/cmd/kaspawallet/daemon/pb/kaspawalletd.proto b/cmd/kaspawallet/daemon/pb/kaspawalletd.proto index 120a0ebe3..55e236b02 100644 --- a/cmd/kaspawallet/daemon/pb/kaspawalletd.proto +++ b/cmd/kaspawallet/daemon/pb/kaspawalletd.proto @@ -113,6 +113,7 @@ message SendRequest{ message SendResponse{ repeated string txIDs = 1; + repeated bytes signedTransactions = 2; } // Since SignRequest contains a password - this command should only be used on a trusted or secure connection diff --git a/cmd/kaspawallet/daemon/pb/kaspawalletd_grpc.pb.go b/cmd/kaspawallet/daemon/pb/kaspawalletd_grpc.pb.go index 726cd3cf6..e66db4a41 100644 --- a/cmd/kaspawallet/daemon/pb/kaspawalletd_grpc.pb.go +++ b/cmd/kaspawallet/daemon/pb/kaspawalletd_grpc.pb.go @@ -1,4 +1,8 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.12.3 +// source: kaspawalletd.proto package pb @@ -11,7 +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. -const _ = grpc.SupportPackageIsVersion6 +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 // KaspawalletdClient is the client API for Kaspawalletd service. // @@ -141,37 +146,44 @@ type KaspawalletdServer interface { type UnimplementedKaspawalletdServer struct { } -func (*UnimplementedKaspawalletdServer) GetBalance(context.Context, *GetBalanceRequest) (*GetBalanceResponse, error) { +func (UnimplementedKaspawalletdServer) GetBalance(context.Context, *GetBalanceRequest) (*GetBalanceResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetBalance not implemented") } -func (*UnimplementedKaspawalletdServer) GetExternalSpendableUTXOs(context.Context, *GetExternalSpendableUTXOsRequest) (*GetExternalSpendableUTXOsResponse, error) { +func (UnimplementedKaspawalletdServer) GetExternalSpendableUTXOs(context.Context, *GetExternalSpendableUTXOsRequest) (*GetExternalSpendableUTXOsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetExternalSpendableUTXOs not implemented") } -func (*UnimplementedKaspawalletdServer) CreateUnsignedTransactions(context.Context, *CreateUnsignedTransactionsRequest) (*CreateUnsignedTransactionsResponse, error) { +func (UnimplementedKaspawalletdServer) CreateUnsignedTransactions(context.Context, *CreateUnsignedTransactionsRequest) (*CreateUnsignedTransactionsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CreateUnsignedTransactions not implemented") } -func (*UnimplementedKaspawalletdServer) ShowAddresses(context.Context, *ShowAddressesRequest) (*ShowAddressesResponse, error) { +func (UnimplementedKaspawalletdServer) ShowAddresses(context.Context, *ShowAddressesRequest) (*ShowAddressesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ShowAddresses not implemented") } -func (*UnimplementedKaspawalletdServer) NewAddress(context.Context, *NewAddressRequest) (*NewAddressResponse, error) { +func (UnimplementedKaspawalletdServer) NewAddress(context.Context, *NewAddressRequest) (*NewAddressResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method NewAddress not implemented") } -func (*UnimplementedKaspawalletdServer) Shutdown(context.Context, *ShutdownRequest) (*ShutdownResponse, error) { +func (UnimplementedKaspawalletdServer) Shutdown(context.Context, *ShutdownRequest) (*ShutdownResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Shutdown not implemented") } -func (*UnimplementedKaspawalletdServer) Broadcast(context.Context, *BroadcastRequest) (*BroadcastResponse, error) { +func (UnimplementedKaspawalletdServer) Broadcast(context.Context, *BroadcastRequest) (*BroadcastResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Broadcast not implemented") } -func (*UnimplementedKaspawalletdServer) Send(context.Context, *SendRequest) (*SendResponse, error) { +func (UnimplementedKaspawalletdServer) Send(context.Context, *SendRequest) (*SendResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Send not implemented") } -func (*UnimplementedKaspawalletdServer) Sign(context.Context, *SignRequest) (*SignResponse, error) { +func (UnimplementedKaspawalletdServer) Sign(context.Context, *SignRequest) (*SignResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Sign not implemented") } -func (*UnimplementedKaspawalletdServer) mustEmbedUnimplementedKaspawalletdServer() {} +func (UnimplementedKaspawalletdServer) mustEmbedUnimplementedKaspawalletdServer() {} -func RegisterKaspawalletdServer(s *grpc.Server, srv KaspawalletdServer) { - s.RegisterService(&_Kaspawalletd_serviceDesc, srv) +// UnsafeKaspawalletdServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to KaspawalletdServer will +// result in compilation errors. +type UnsafeKaspawalletdServer interface { + mustEmbedUnimplementedKaspawalletdServer() +} + +func RegisterKaspawalletdServer(s grpc.ServiceRegistrar, srv KaspawalletdServer) { + s.RegisterService(&Kaspawalletd_ServiceDesc, srv) } func _Kaspawalletd_GetBalance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { @@ -336,7 +348,10 @@ func _Kaspawalletd_Sign_Handler(srv interface{}, ctx context.Context, dec func(i return interceptor(ctx, in, info, handler) } -var _Kaspawalletd_serviceDesc = grpc.ServiceDesc{ +// Kaspawalletd_ServiceDesc is the grpc.ServiceDesc for Kaspawalletd service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Kaspawalletd_ServiceDesc = grpc.ServiceDesc{ ServiceName: "kaspawalletd.kaspawalletd", HandlerType: (*KaspawalletdServer)(nil), Methods: []grpc.MethodDesc{ diff --git a/cmd/kaspawallet/daemon/server/send.go b/cmd/kaspawallet/daemon/server/send.go index a52e42005..262725243 100644 --- a/cmd/kaspawallet/daemon/server/send.go +++ b/cmd/kaspawallet/daemon/server/send.go @@ -25,5 +25,5 @@ func (s *server) Send(_ context.Context, request *pb.SendRequest) (*pb.SendRespo return nil, err } - return &pb.SendResponse{TxIDs: txIDs}, nil + return &pb.SendResponse{TxIDs: txIDs, SignedTransactions: signedTransactions}, nil } diff --git a/cmd/kaspawallet/daemon/server/server.go b/cmd/kaspawallet/daemon/server/server.go index afa140319..0640cff4e 100644 --- a/cmd/kaspawallet/daemon/server/server.go +++ b/cmd/kaspawallet/daemon/server/server.go @@ -44,6 +44,10 @@ type server struct { maxProcessedAddressesForLog uint32 } +// MaxDaemonSendMsgSize is the max send message size used for the daemon server. +// Currently, set to 100MB +const MaxDaemonSendMsgSize = 100_000_000 + // Start starts the kaspawalletd server func Start(params *dagconfig.Params, listen, rpcServer string, keysFilePath string, profile string, timeout uint32) error { initLog(defaultLogFile, defaultErrLogFile) @@ -96,7 +100,7 @@ func Start(params *dagconfig.Params, listen, rpcServer string, keysFilePath stri } }) - grpcServer := grpc.NewServer() + grpcServer := grpc.NewServer(grpc.MaxSendMsgSize(MaxDaemonSendMsgSize)) pb.RegisterKaspawalletdServer(grpcServer, serverInstance) spawn("grpcServer.Serve", func() { diff --git a/cmd/kaspawallet/send.go b/cmd/kaspawallet/send.go index c4f371b32..c251f984f 100644 --- a/cmd/kaspawallet/send.go +++ b/cmd/kaspawallet/send.go @@ -80,5 +80,12 @@ func send(conf *sendConfig) error { fmt.Printf("\t%s\n", txID) } + if conf.Verbose { + fmt.Println("Serialized Transaction(s) (can be parsed via the `parse` command or resent via `broadcast`): ") + for _, signedTx := range signedTransactions { + fmt.Printf("\t%x\n\n", signedTx) + } + } + return nil } diff --git a/go.mod b/go.mod index cdfa11128..31aab2975 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( golang.org/x/exp v0.0.0-20220414153411-bcd21879b8fd golang.org/x/term v0.0.0-20210503060354-a79de5458b56 google.golang.org/grpc v1.38.0 - google.golang.org/protobuf v1.27.1 + google.golang.org/protobuf v1.28.1 ) require ( @@ -28,5 +28,6 @@ require ( golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 // indirect golang.org/x/text v0.3.5 // indirect google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08 // indirect + google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0 // indirect gopkg.in/yaml.v2 v2.3.0 // indirect ) diff --git a/go.sum b/go.sum index 2f3280065..ed42be015 100644 --- a/go.sum +++ b/go.sum @@ -171,6 +171,8 @@ google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/l google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=