From 4c453a397be693e03f4fe06b6beea2e29f8b273a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Olav?= Date: Tue, 24 Sep 2024 10:31:05 +0200 Subject: [PATCH] rpc: add listactivesidechains --- drivechain/drivechain.go | 3 + gen/bitcoin/drivechaind/v1/drivechain.pb.go | 338 ++++++++++++++++-- .../drivechain.connect.go | 30 ++ proto/bitcoin/drivechaind/v1/drivechain.proto | 18 + server/commands/drivechain.go | 10 + server/drivechain_server.go | 127 +++++++ server/server.go | 2 + 7 files changed, 491 insertions(+), 37 deletions(-) diff --git a/drivechain/drivechain.go b/drivechain/drivechain.go index a5bef97..e9c8010 100644 --- a/drivechain/drivechain.go +++ b/drivechain/drivechain.go @@ -29,3 +29,6 @@ func ValidateDepositAddress(depositAddress string) error { return nil } + +//nolint:staticcheck +var ErrNoCTip = "No CTIP found for sidechain!" diff --git a/gen/bitcoin/drivechaind/v1/drivechain.pb.go b/gen/bitcoin/drivechaind/v1/drivechain.pb.go index 439585f..dd8c43d 100644 --- a/gen/bitcoin/drivechaind/v1/drivechain.pb.go +++ b/gen/bitcoin/drivechaind/v1/drivechain.pb.go @@ -133,6 +133,194 @@ func (x *CreateSidechainDepositResponse) GetTxid() string { return "" } +type ListActiveSidechainsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ListActiveSidechainsRequest) Reset() { + *x = ListActiveSidechainsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_bitcoin_drivechaind_v1_drivechain_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListActiveSidechainsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListActiveSidechainsRequest) ProtoMessage() {} + +func (x *ListActiveSidechainsRequest) ProtoReflect() protoreflect.Message { + mi := &file_bitcoin_drivechaind_v1_drivechain_proto_msgTypes[2] + 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 ListActiveSidechainsRequest.ProtoReflect.Descriptor instead. +func (*ListActiveSidechainsRequest) Descriptor() ([]byte, []int) { + return file_bitcoin_drivechaind_v1_drivechain_proto_rawDescGZIP(), []int{2} +} + +type ListActiveSidechainsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Sidechains []*ListActiveSidechainsResponse_Sidechain `protobuf:"bytes,1,rep,name=sidechains,proto3" json:"sidechains,omitempty"` +} + +func (x *ListActiveSidechainsResponse) Reset() { + *x = ListActiveSidechainsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_bitcoin_drivechaind_v1_drivechain_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListActiveSidechainsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListActiveSidechainsResponse) ProtoMessage() {} + +func (x *ListActiveSidechainsResponse) ProtoReflect() protoreflect.Message { + mi := &file_bitcoin_drivechaind_v1_drivechain_proto_msgTypes[3] + 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 ListActiveSidechainsResponse.ProtoReflect.Descriptor instead. +func (*ListActiveSidechainsResponse) Descriptor() ([]byte, []int) { + return file_bitcoin_drivechaind_v1_drivechain_proto_rawDescGZIP(), []int{3} +} + +func (x *ListActiveSidechainsResponse) GetSidechains() []*ListActiveSidechainsResponse_Sidechain { + if x != nil { + return x.Sidechains + } + return nil +} + +type ListActiveSidechainsResponse_Sidechain struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + Nversion uint32 `protobuf:"varint,3,opt,name=nversion,proto3" json:"nversion,omitempty"` + Hashid1 string `protobuf:"bytes,4,opt,name=hashid1,proto3" json:"hashid1,omitempty"` + Hashid2 string `protobuf:"bytes,5,opt,name=hashid2,proto3" json:"hashid2,omitempty"` + Slot int32 `protobuf:"varint,6,opt,name=slot,proto3" json:"slot,omitempty"` + AmountSatoshi int64 `protobuf:"varint,7,opt,name=amount_satoshi,json=amountSatoshi,proto3" json:"amount_satoshi,omitempty"` + ChaintipTxid string `protobuf:"bytes,8,opt,name=chaintip_txid,json=chaintipTxid,proto3" json:"chaintip_txid,omitempty"` +} + +func (x *ListActiveSidechainsResponse_Sidechain) Reset() { + *x = ListActiveSidechainsResponse_Sidechain{} + if protoimpl.UnsafeEnabled { + mi := &file_bitcoin_drivechaind_v1_drivechain_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListActiveSidechainsResponse_Sidechain) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListActiveSidechainsResponse_Sidechain) ProtoMessage() {} + +func (x *ListActiveSidechainsResponse_Sidechain) ProtoReflect() protoreflect.Message { + mi := &file_bitcoin_drivechaind_v1_drivechain_proto_msgTypes[4] + 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 ListActiveSidechainsResponse_Sidechain.ProtoReflect.Descriptor instead. +func (*ListActiveSidechainsResponse_Sidechain) Descriptor() ([]byte, []int) { + return file_bitcoin_drivechaind_v1_drivechain_proto_rawDescGZIP(), []int{3, 0} +} + +func (x *ListActiveSidechainsResponse_Sidechain) GetTitle() string { + if x != nil { + return x.Title + } + return "" +} + +func (x *ListActiveSidechainsResponse_Sidechain) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *ListActiveSidechainsResponse_Sidechain) GetNversion() uint32 { + if x != nil { + return x.Nversion + } + return 0 +} + +func (x *ListActiveSidechainsResponse_Sidechain) GetHashid1() string { + if x != nil { + return x.Hashid1 + } + return "" +} + +func (x *ListActiveSidechainsResponse_Sidechain) GetHashid2() string { + if x != nil { + return x.Hashid2 + } + return "" +} + +func (x *ListActiveSidechainsResponse_Sidechain) GetSlot() int32 { + if x != nil { + return x.Slot + } + return 0 +} + +func (x *ListActiveSidechainsResponse_Sidechain) GetAmountSatoshi() int64 { + if x != nil { + return x.AmountSatoshi + } + return 0 +} + +func (x *ListActiveSidechainsResponse_Sidechain) GetChaintipTxid() string { + if x != nil { + return x.ChaintipTxid + } + return "" +} + var File_bitcoin_drivechaind_v1_drivechain_proto protoreflect.FileDescriptor var file_bitcoin_drivechaind_v1_drivechain_proto_rawDesc = []byte{ @@ -150,32 +338,66 @@ var file_bitcoin_drivechaind_v1_drivechain_proto_rawDesc = []byte{ 0x0a, 0x1e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x69, 0x64, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x74, 0x78, 0x69, 0x64, 0x32, 0x9d, 0x01, 0x0a, 0x11, 0x44, 0x72, 0x69, 0x76, 0x65, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x87, 0x01, 0x0a, 0x16, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x69, 0x64, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x44, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x35, 0x2e, 0x62, 0x69, 0x74, 0x63, 0x6f, 0x69, 0x6e, 0x2e, - 0x64, 0x72, 0x69, 0x76, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x69, 0x64, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x44, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x62, - 0x69, 0x74, 0x63, 0x6f, 0x69, 0x6e, 0x2e, 0x64, 0x72, 0x69, 0x76, 0x65, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x69, 0x64, 0x65, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x42, 0xf0, 0x01, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x62, 0x69, 0x74, - 0x63, 0x6f, 0x69, 0x6e, 0x2e, 0x64, 0x72, 0x69, 0x76, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x64, - 0x2e, 0x76, 0x31, 0x42, 0x0f, 0x44, 0x72, 0x69, 0x76, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x47, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x62, 0x61, 0x72, 0x65, 0x62, 0x69, 0x74, 0x63, 0x6f, 0x69, 0x6e, 0x2f, 0x62, - 0x74, 0x63, 0x2d, 0x62, 0x75, 0x66, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x62, 0x69, 0x74, 0x63, 0x6f, - 0x69, 0x6e, 0x2f, 0x64, 0x72, 0x69, 0x76, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x64, 0x2f, 0x76, - 0x31, 0x3b, 0x64, 0x72, 0x69, 0x76, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x64, 0x76, 0x31, 0xa2, - 0x02, 0x03, 0x42, 0x44, 0x58, 0xaa, 0x02, 0x16, 0x42, 0x69, 0x74, 0x63, 0x6f, 0x69, 0x6e, 0x2e, - 0x44, 0x72, 0x69, 0x76, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x64, 0x2e, 0x56, 0x31, 0xca, 0x02, - 0x16, 0x42, 0x69, 0x74, 0x63, 0x6f, 0x69, 0x6e, 0x5c, 0x44, 0x72, 0x69, 0x76, 0x65, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x64, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x22, 0x42, 0x69, 0x74, 0x63, 0x6f, 0x69, - 0x6e, 0x5c, 0x44, 0x72, 0x69, 0x76, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x64, 0x5c, 0x56, 0x31, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x18, 0x42, - 0x69, 0x74, 0x63, 0x6f, 0x69, 0x6e, 0x3a, 0x3a, 0x44, 0x72, 0x69, 0x76, 0x65, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x64, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x78, 0x69, 0x64, 0x22, 0x1d, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, + 0x76, 0x65, 0x53, 0x69, 0x64, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x22, 0xf4, 0x02, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, + 0x76, 0x65, 0x53, 0x69, 0x64, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x0a, 0x73, 0x69, 0x64, 0x65, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x62, 0x69, 0x74, 0x63, 0x6f, + 0x69, 0x6e, 0x2e, 0x64, 0x72, 0x69, 0x76, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x64, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x69, 0x64, 0x65, + 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, + 0x69, 0x64, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x0a, 0x73, 0x69, 0x64, 0x65, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x73, 0x1a, 0xf3, 0x01, 0x0a, 0x09, 0x53, 0x69, 0x64, 0x65, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x6e, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x68, 0x61, 0x73, 0x68, 0x69, 0x64, + 0x31, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x68, 0x61, 0x73, 0x68, 0x69, 0x64, 0x31, + 0x12, 0x18, 0x0a, 0x07, 0x68, 0x61, 0x73, 0x68, 0x69, 0x64, 0x32, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x68, 0x61, 0x73, 0x68, 0x69, 0x64, 0x32, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6c, + 0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x25, + 0x0a, 0x0e, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x73, 0x61, 0x74, 0x6f, 0x73, 0x68, 0x69, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x61, + 0x74, 0x6f, 0x73, 0x68, 0x69, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x74, 0x69, + 0x70, 0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x74, 0x69, 0x70, 0x54, 0x78, 0x69, 0x64, 0x32, 0xa1, 0x02, 0x0a, 0x11, 0x44, + 0x72, 0x69, 0x76, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x87, 0x01, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x69, 0x64, 0x65, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x35, 0x2e, 0x62, 0x69, + 0x74, 0x63, 0x6f, 0x69, 0x6e, 0x2e, 0x64, 0x72, 0x69, 0x76, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x69, 0x64, 0x65, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x62, 0x69, 0x74, 0x63, 0x6f, 0x69, 0x6e, 0x2e, 0x64, 0x72, 0x69, + 0x76, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x53, 0x69, 0x64, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x44, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x81, 0x01, 0x0a, 0x14, 0x4c, + 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x69, 0x64, 0x65, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x73, 0x12, 0x33, 0x2e, 0x62, 0x69, 0x74, 0x63, 0x6f, 0x69, 0x6e, 0x2e, 0x64, 0x72, + 0x69, 0x76, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x69, 0x64, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x62, 0x69, 0x74, 0x63, 0x6f, + 0x69, 0x6e, 0x2e, 0x64, 0x72, 0x69, 0x76, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x64, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x53, 0x69, 0x64, 0x65, + 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0xf0, + 0x01, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x62, 0x69, 0x74, 0x63, 0x6f, 0x69, 0x6e, 0x2e, 0x64, + 0x72, 0x69, 0x76, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x64, 0x2e, 0x76, 0x31, 0x42, 0x0f, 0x44, + 0x72, 0x69, 0x76, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, + 0x5a, 0x47, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x62, 0x61, 0x72, + 0x65, 0x62, 0x69, 0x74, 0x63, 0x6f, 0x69, 0x6e, 0x2f, 0x62, 0x74, 0x63, 0x2d, 0x62, 0x75, 0x66, + 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x62, 0x69, 0x74, 0x63, 0x6f, 0x69, 0x6e, 0x2f, 0x64, 0x72, 0x69, + 0x76, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x64, 0x2f, 0x76, 0x31, 0x3b, 0x64, 0x72, 0x69, 0x76, + 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x64, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x42, 0x44, 0x58, 0xaa, + 0x02, 0x16, 0x42, 0x69, 0x74, 0x63, 0x6f, 0x69, 0x6e, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x64, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x16, 0x42, 0x69, 0x74, 0x63, 0x6f, + 0x69, 0x6e, 0x5c, 0x44, 0x72, 0x69, 0x76, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x64, 0x5c, 0x56, + 0x31, 0xe2, 0x02, 0x22, 0x42, 0x69, 0x74, 0x63, 0x6f, 0x69, 0x6e, 0x5c, 0x44, 0x72, 0x69, 0x76, + 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x64, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x18, 0x42, 0x69, 0x74, 0x63, 0x6f, 0x69, 0x6e, + 0x3a, 0x3a, 0x44, 0x72, 0x69, 0x76, 0x65, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x64, 0x3a, 0x3a, 0x56, + 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -190,19 +412,25 @@ func file_bitcoin_drivechaind_v1_drivechain_proto_rawDescGZIP() []byte { return file_bitcoin_drivechaind_v1_drivechain_proto_rawDescData } -var file_bitcoin_drivechaind_v1_drivechain_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_bitcoin_drivechaind_v1_drivechain_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_bitcoin_drivechaind_v1_drivechain_proto_goTypes = []any{ - (*CreateSidechainDepositRequest)(nil), // 0: bitcoin.drivechaind.v1.CreateSidechainDepositRequest - (*CreateSidechainDepositResponse)(nil), // 1: bitcoin.drivechaind.v1.CreateSidechainDepositResponse + (*CreateSidechainDepositRequest)(nil), // 0: bitcoin.drivechaind.v1.CreateSidechainDepositRequest + (*CreateSidechainDepositResponse)(nil), // 1: bitcoin.drivechaind.v1.CreateSidechainDepositResponse + (*ListActiveSidechainsRequest)(nil), // 2: bitcoin.drivechaind.v1.ListActiveSidechainsRequest + (*ListActiveSidechainsResponse)(nil), // 3: bitcoin.drivechaind.v1.ListActiveSidechainsResponse + (*ListActiveSidechainsResponse_Sidechain)(nil), // 4: bitcoin.drivechaind.v1.ListActiveSidechainsResponse.Sidechain } var file_bitcoin_drivechaind_v1_drivechain_proto_depIdxs = []int32{ - 0, // 0: bitcoin.drivechaind.v1.DrivechainService.CreateSidechainDeposit:input_type -> bitcoin.drivechaind.v1.CreateSidechainDepositRequest - 1, // 1: bitcoin.drivechaind.v1.DrivechainService.CreateSidechainDeposit:output_type -> bitcoin.drivechaind.v1.CreateSidechainDepositResponse - 1, // [1:2] is the sub-list for method output_type - 0, // [0:1] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name + 4, // 0: bitcoin.drivechaind.v1.ListActiveSidechainsResponse.sidechains:type_name -> bitcoin.drivechaind.v1.ListActiveSidechainsResponse.Sidechain + 0, // 1: bitcoin.drivechaind.v1.DrivechainService.CreateSidechainDeposit:input_type -> bitcoin.drivechaind.v1.CreateSidechainDepositRequest + 2, // 2: bitcoin.drivechaind.v1.DrivechainService.ListActiveSidechains:input_type -> bitcoin.drivechaind.v1.ListActiveSidechainsRequest + 1, // 3: bitcoin.drivechaind.v1.DrivechainService.CreateSidechainDeposit:output_type -> bitcoin.drivechaind.v1.CreateSidechainDepositResponse + 3, // 4: bitcoin.drivechaind.v1.DrivechainService.ListActiveSidechains:output_type -> bitcoin.drivechaind.v1.ListActiveSidechainsResponse + 3, // [3:5] is the sub-list for method output_type + 1, // [1:3] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name } func init() { file_bitcoin_drivechaind_v1_drivechain_proto_init() } @@ -235,6 +463,42 @@ func file_bitcoin_drivechaind_v1_drivechain_proto_init() { return nil } } + file_bitcoin_drivechaind_v1_drivechain_proto_msgTypes[2].Exporter = func(v any, i int) any { + switch v := v.(*ListActiveSidechainsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_bitcoin_drivechaind_v1_drivechain_proto_msgTypes[3].Exporter = func(v any, i int) any { + switch v := v.(*ListActiveSidechainsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_bitcoin_drivechaind_v1_drivechain_proto_msgTypes[4].Exporter = func(v any, i int) any { + switch v := v.(*ListActiveSidechainsResponse_Sidechain); 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{ @@ -242,7 +506,7 @@ func file_bitcoin_drivechaind_v1_drivechain_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_bitcoin_drivechaind_v1_drivechain_proto_rawDesc, NumEnums: 0, - NumMessages: 2, + NumMessages: 5, NumExtensions: 0, NumServices: 1, }, diff --git a/gen/bitcoin/drivechaind/v1/drivechaindv1connect/drivechain.connect.go b/gen/bitcoin/drivechaind/v1/drivechaindv1connect/drivechain.connect.go index 57f4fa5..24406a7 100644 --- a/gen/bitcoin/drivechaind/v1/drivechaindv1connect/drivechain.connect.go +++ b/gen/bitcoin/drivechaind/v1/drivechaindv1connect/drivechain.connect.go @@ -36,17 +36,22 @@ const ( // DrivechainServiceCreateSidechainDepositProcedure is the fully-qualified name of the // DrivechainService's CreateSidechainDeposit RPC. DrivechainServiceCreateSidechainDepositProcedure = "/bitcoin.drivechaind.v1.DrivechainService/CreateSidechainDeposit" + // DrivechainServiceListActiveSidechainsProcedure is the fully-qualified name of the + // DrivechainService's ListActiveSidechains RPC. + DrivechainServiceListActiveSidechainsProcedure = "/bitcoin.drivechaind.v1.DrivechainService/ListActiveSidechains" ) // These variables are the protoreflect.Descriptor objects for the RPCs defined in this package. var ( drivechainServiceServiceDescriptor = v1.File_bitcoin_drivechaind_v1_drivechain_proto.Services().ByName("DrivechainService") drivechainServiceCreateSidechainDepositMethodDescriptor = drivechainServiceServiceDescriptor.Methods().ByName("CreateSidechainDeposit") + drivechainServiceListActiveSidechainsMethodDescriptor = drivechainServiceServiceDescriptor.Methods().ByName("ListActiveSidechains") ) // DrivechainServiceClient is a client for the bitcoin.drivechaind.v1.DrivechainService service. type DrivechainServiceClient interface { CreateSidechainDeposit(context.Context, *connect.Request[v1.CreateSidechainDepositRequest]) (*connect.Response[v1.CreateSidechainDepositResponse], error) + ListActiveSidechains(context.Context, *connect.Request[v1.ListActiveSidechainsRequest]) (*connect.Response[v1.ListActiveSidechainsResponse], error) } // NewDrivechainServiceClient constructs a client for the bitcoin.drivechaind.v1.DrivechainService @@ -65,12 +70,19 @@ func NewDrivechainServiceClient(httpClient connect.HTTPClient, baseURL string, o connect.WithSchema(drivechainServiceCreateSidechainDepositMethodDescriptor), connect.WithClientOptions(opts...), ), + listActiveSidechains: connect.NewClient[v1.ListActiveSidechainsRequest, v1.ListActiveSidechainsResponse]( + httpClient, + baseURL+DrivechainServiceListActiveSidechainsProcedure, + connect.WithSchema(drivechainServiceListActiveSidechainsMethodDescriptor), + connect.WithClientOptions(opts...), + ), } } // drivechainServiceClient implements DrivechainServiceClient. type drivechainServiceClient struct { createSidechainDeposit *connect.Client[v1.CreateSidechainDepositRequest, v1.CreateSidechainDepositResponse] + listActiveSidechains *connect.Client[v1.ListActiveSidechainsRequest, v1.ListActiveSidechainsResponse] } // CreateSidechainDeposit calls bitcoin.drivechaind.v1.DrivechainService.CreateSidechainDeposit. @@ -78,10 +90,16 @@ func (c *drivechainServiceClient) CreateSidechainDeposit(ctx context.Context, re return c.createSidechainDeposit.CallUnary(ctx, req) } +// ListActiveSidechains calls bitcoin.drivechaind.v1.DrivechainService.ListActiveSidechains. +func (c *drivechainServiceClient) ListActiveSidechains(ctx context.Context, req *connect.Request[v1.ListActiveSidechainsRequest]) (*connect.Response[v1.ListActiveSidechainsResponse], error) { + return c.listActiveSidechains.CallUnary(ctx, req) +} + // DrivechainServiceHandler is an implementation of the bitcoin.drivechaind.v1.DrivechainService // service. type DrivechainServiceHandler interface { CreateSidechainDeposit(context.Context, *connect.Request[v1.CreateSidechainDepositRequest]) (*connect.Response[v1.CreateSidechainDepositResponse], error) + ListActiveSidechains(context.Context, *connect.Request[v1.ListActiveSidechainsRequest]) (*connect.Response[v1.ListActiveSidechainsResponse], error) } // NewDrivechainServiceHandler builds an HTTP handler from the service implementation. It returns @@ -96,10 +114,18 @@ func NewDrivechainServiceHandler(svc DrivechainServiceHandler, opts ...connect.H connect.WithSchema(drivechainServiceCreateSidechainDepositMethodDescriptor), connect.WithHandlerOptions(opts...), ) + drivechainServiceListActiveSidechainsHandler := connect.NewUnaryHandler( + DrivechainServiceListActiveSidechainsProcedure, + svc.ListActiveSidechains, + connect.WithSchema(drivechainServiceListActiveSidechainsMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) return "/bitcoin.drivechaind.v1.DrivechainService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case DrivechainServiceCreateSidechainDepositProcedure: drivechainServiceCreateSidechainDepositHandler.ServeHTTP(w, r) + case DrivechainServiceListActiveSidechainsProcedure: + drivechainServiceListActiveSidechainsHandler.ServeHTTP(w, r) default: http.NotFound(w, r) } @@ -112,3 +138,7 @@ type UnimplementedDrivechainServiceHandler struct{} func (UnimplementedDrivechainServiceHandler) CreateSidechainDeposit(context.Context, *connect.Request[v1.CreateSidechainDepositRequest]) (*connect.Response[v1.CreateSidechainDepositResponse], error) { return nil, connect.NewError(connect.CodeUnimplemented, errors.New("bitcoin.drivechaind.v1.DrivechainService.CreateSidechainDeposit is not implemented")) } + +func (UnimplementedDrivechainServiceHandler) ListActiveSidechains(context.Context, *connect.Request[v1.ListActiveSidechainsRequest]) (*connect.Response[v1.ListActiveSidechainsResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("bitcoin.drivechaind.v1.DrivechainService.ListActiveSidechains is not implemented")) +} diff --git a/proto/bitcoin/drivechaind/v1/drivechain.proto b/proto/bitcoin/drivechaind/v1/drivechain.proto index a02a179..f989b4a 100644 --- a/proto/bitcoin/drivechaind/v1/drivechain.proto +++ b/proto/bitcoin/drivechaind/v1/drivechain.proto @@ -4,6 +4,7 @@ package bitcoin.drivechaind.v1; service DrivechainService { rpc CreateSidechainDeposit(CreateSidechainDepositRequest) returns (CreateSidechainDepositResponse); + rpc ListActiveSidechains(ListActiveSidechainsRequest) returns (ListActiveSidechainsResponse); } message CreateSidechainDepositRequest { @@ -18,3 +19,20 @@ message CreateSidechainDepositRequest { message CreateSidechainDepositResponse { string txid = 1; } + +message ListActiveSidechainsRequest {} + +message ListActiveSidechainsResponse { + message Sidechain { + string title = 1; + string description = 2; + uint32 nversion = 3; + string hashid1 = 4; + string hashid2 = 5; + int32 slot = 6; + int64 amount_satoshi = 7; + string chaintip_txid = 8; + } + + repeated Sidechain sidechains = 1; +} diff --git a/server/commands/drivechain.go b/server/commands/drivechain.go index 22d531d..9322c43 100644 --- a/server/commands/drivechain.go +++ b/server/commands/drivechain.go @@ -1,8 +1,18 @@ package commands +// Create a sidechain deposit of an amount to a given address. type CreateSidechainDeposit struct { Slot int `json:"slot"` Destination string `json:"destination"` Amount float64 `json:"amount"` Fee float64 `json:"fee"` } + +// List active sidechains. +type ListActiveSidechains struct{} + +// Returns the crtitical transaction index pair for sidechain in a specific slot +type ListSidechainCTip struct { + // The sidechain slot + Slot int `json:"slot"` +} diff --git a/server/drivechain_server.go b/server/drivechain_server.go index 7097a00..d54e1e9 100644 --- a/server/drivechain_server.go +++ b/server/drivechain_server.go @@ -67,3 +67,130 @@ func (b *Bitcoind) CreateSidechainDeposit(ctx context.Context, c *connect.Reques }, ) } + +type activeSidechain struct { + Title string `json:"title"` + Description string `json:"description"` + NVersion int `json:"nversion"` + HashID1 string `json:"hashid1"` + HashID2 string `json:"hashid2"` +} + +// ListActiveSidechains implements drivechaindv1connect.DrivechainServiceHandler. +func (b *Bitcoind) ListActiveSidechains(ctx context.Context, _ *connect.Request[pb.ListActiveSidechainsRequest]) (*connect.Response[pb.ListActiveSidechainsResponse], error) { + return withCancel(ctx, func(ctx context.Context) ([]*pb.ListActiveSidechainsResponse_Sidechain, error) { + cmd, err := btcjson.NewCmd("listactivesidechains") + if err != nil { + return nil, fmt.Errorf("listactivesidechains new cmd: %w", err) + } + + res, err := rpcclient.ReceiveFuture(b.rpc.SendCmd(ctx, cmd)) + if err != nil { + return nil, fmt.Errorf("listactivesidechains send: %w", err) + } + + var sidechains []activeSidechain + if err := json.Unmarshal(res, &sidechains); err != nil { + return nil, fmt.Errorf("listactivesidechains unmarshal response: %w", err) + } + + // Log the unmarshaled sidechains for debugging + zerolog.Ctx(ctx).Debug(). + Interface("sidechains", sidechains). + Msg("unmarshaled active sidechains") + + pbSidechains := make([]*pb.ListActiveSidechainsResponse_Sidechain, 0, len(sidechains)) + for _, sidechain := range sidechains { + pbSidechain, err := b.sidechainToProto(ctx, sidechain) + if err != nil { + return nil, fmt.Errorf("convert sidechain to proto: %w", err) + } + + pbSidechains = append(pbSidechains, pbSidechain) + } + + return pbSidechains, nil + }, + + func(sidechains []*pb.ListActiveSidechainsResponse_Sidechain) *pb.ListActiveSidechainsResponse { + return &pb.ListActiveSidechainsResponse{ + Sidechains: sidechains, + } + }, + ) +} + +func (b *Bitcoind) getChaintipInfo(ctx context.Context, sidechainSlot int) (btcutil.Amount, string, error) { + cmd, err := btcjson.NewCmd("listsidechainctip", sidechainSlot) + if err != nil { + return 0, "", fmt.Errorf("listsidechainctip new cmd: %w", err) + } + res, err := rpcclient.ReceiveFuture(b.rpc.SendCmd(ctx, cmd)) + if err != nil { + return 0, "", fmt.Errorf("listsidechainctip send: %w", err) + } + + var result struct { + Amount btcutil.Amount `json:"amount"` + TXID string `json:"txid"` + } + if err := json.Unmarshal(res, &result); err != nil { + return 0, "", fmt.Errorf("unmarshal listsidechainctip response: %w", err) + } + + return result.Amount, result.TXID, nil +} + +func (b *Bitcoind) sidechainToProto( + ctx context.Context, sidechain activeSidechain, +) (*pb.ListActiveSidechainsResponse_Sidechain, error) { + slot, err := chainToSlot(sidechain.Title) + if err != nil { + return nil, fmt.Errorf("convert chain to slot: %w", err) + } + + balance, txid, err := b.getChaintipInfo(ctx, slot) + switch { + case err == nil: + // No error, proceed + + case strings.Contains(err.Error(), drivechain.ErrNoCTip): + zerolog.Ctx(ctx).Warn().Int("slot", slot).Msg("no ctip for sidechain") + // That's okay, proceed + + default: + return nil, fmt.Errorf("get balance for chain %s: %w", sidechain.Title, err) + } + + return &pb.ListActiveSidechainsResponse_Sidechain{ + Title: sidechain.Title, + Description: sidechain.Description, + Nversion: uint32(sidechain.NVersion), + Hashid1: sidechain.HashID1, + Hashid2: sidechain.HashID2, + Slot: int32(slot), + AmountSatoshi: int64(balance), + ChaintipTxid: txid, + }, nil +} + +func chainToSlot(chain string) (int, error) { + switch chain { + case "Testchain": + return 0, nil + case "BitNames": + return 2, nil + case "BitAssets": + return 4, nil + case "ZSide": + return 5, nil + case "EthSide": + return 6, nil + case "Thunder": + return 9, nil + case "LatestCore": + return 11, nil + default: + return 0, fmt.Errorf("unknown chain: %s", chain) + } +} diff --git a/server/server.go b/server/server.go index f89ee23..b7be1ab 100644 --- a/server/server.go +++ b/server/server.go @@ -40,6 +40,8 @@ func init() { // drivechain commands btcjson.MustRegisterCmd("createsidechaindeposit", new(commands.CreateSidechainDeposit), btcjson.UFWalletOnly) + btcjson.MustRegisterCmd("listactivesidechains", new(commands.ListActiveSidechains), btcjson.UFWalletOnly) + btcjson.MustRegisterCmd("listsidechainctip", new(commands.ListSidechainCTip), btcjson.UFWalletOnly) } type Bitcoind struct {