diff --git a/asp/api-spec/openapi/swagger/ark/v1/service.swagger.json b/asp/api-spec/openapi/swagger/ark/v1/service.swagger.json index 9681905..ef5d9de 100644 --- a/asp/api-spec/openapi/swagger/ark/v1/service.swagger.json +++ b/asp/api-spec/openapi/swagger/ark/v1/service.swagger.json @@ -424,12 +424,14 @@ "v1Output": { "type": "object", "properties": { - "pubkey": { - "type": "string" + "address": { + "type": "string", + "description": "Either the offchain or onchain address." }, "amount": { "type": "string", - "format": "uint64" + "format": "uint64", + "description": "Amount to send in satoshis." } } }, diff --git a/asp/api-spec/openapi/swagger/ocean/v1/transaction.swagger.json b/asp/api-spec/openapi/swagger/ocean/v1/transaction.swagger.json index e07d044..abf754c 100644 --- a/asp/api-spec/openapi/swagger/ocean/v1/transaction.swagger.json +++ b/asp/api-spec/openapi/swagger/ocean/v1/transaction.swagger.json @@ -262,6 +262,14 @@ } } }, + "v1SignPsetWithSchnorrKeyResponse": { + "type": "object", + "properties": { + "signedTx": { + "type": "string" + } + } + }, "v1SignTransactionResponse": { "type": "object", "properties": { diff --git a/asp/api-spec/protobuf/ark/v1/service.proto b/asp/api-spec/protobuf/ark/v1/service.proto index 49fa32d..dd46725 100755 --- a/asp/api-spec/protobuf/ark/v1/service.proto +++ b/asp/api-spec/protobuf/ark/v1/service.proto @@ -98,7 +98,9 @@ message Input { } message Output { - string pubkey = 1; + // Either the offchain or onchain address. + string address = 1; + // Amount to send in satoshis. uint64 amount = 2; } diff --git a/asp/api-spec/protobuf/gen/ark/v1/service.pb.go b/asp/api-spec/protobuf/gen/ark/v1/service.pb.go index 3b9518e..471bb5a 100644 --- a/asp/api-spec/protobuf/gen/ark/v1/service.pb.go +++ b/asp/api-spec/protobuf/gen/ark/v1/service.pb.go @@ -530,7 +530,9 @@ type Output struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Pubkey string `protobuf:"bytes,1,opt,name=pubkey,proto3" json:"pubkey,omitempty"` + // Either the offchain or onchain address. + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // Amount to send in satoshis. Amount uint64 `protobuf:"varint,2,opt,name=amount,proto3" json:"amount,omitempty"` } @@ -566,9 +568,9 @@ func (*Output) Descriptor() ([]byte, []int) { return file_ark_v1_service_proto_rawDescGZIP(), []int{10} } -func (x *Output) GetPubkey() string { +func (x *Output) GetAddress() string { if x != nil { - return x.Pubkey + return x.Address } return "" } @@ -1507,148 +1509,148 @@ var file_ark_v1_service_proto_rawDesc = []byte{ 0x65, 0x22, 0x2f, 0x0a, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x76, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x76, 0x6f, - 0x75, 0x74, 0x22, 0x38, 0x0a, 0x06, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x16, 0x0a, 0x06, - 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, - 0x62, 0x6b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xa8, 0x01, 0x0a, - 0x16, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, - 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0d, 0x70, 0x6f, 0x6f, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x54, 0x78, 0x12, - 0x1f, 0x0a, 0x0b, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x5f, 0x74, 0x78, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, - 0x12, 0x35, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, - 0x72, 0x65, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x67, 0x65, 0x73, 0x74, - 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x65, 0x65, 0x22, 0x31, 0x0a, 0x04, 0x54, 0x72, 0x65, 0x65, 0x12, - 0x29, 0x0a, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x11, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x65, 0x76, - 0x65, 0x6c, 0x52, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x22, 0x2f, 0x0a, 0x09, 0x54, 0x72, - 0x65, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x22, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, - 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x04, 0x4e, - 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x78, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x74, 0x78, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x54, 0x78, 0x69, 0x64, 0x22, 0x42, 0x0a, 0x13, 0x52, 0x6f, 0x75, 0x6e, - 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, - 0x1b, 0x0a, 0x09, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x70, 0x6f, 0x6f, 0x6c, 0x54, 0x78, 0x69, 0x64, 0x22, 0x35, 0x0a, 0x0b, - 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, - 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, - 0x73, 0x6f, 0x6e, 0x22, 0x17, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xf4, 0x01, 0x0a, - 0x16, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x12, 0x72, 0x6f, 0x75, 0x6e, 0x64, - 0x5f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, - 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x11, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, - 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x0f, 0x72, 0x6f, 0x75, 0x6e, - 0x64, 0x5f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, - 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, - 0x52, 0x0e, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, - 0x12, 0x38, 0x0a, 0x0c, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, - 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0b, 0x72, - 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x22, 0x2c, 0x0a, 0x0b, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x49, - 0x64, 0x22, 0x0e, 0x0a, 0x0c, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x29, 0x0a, 0x0d, 0x46, 0x61, 0x75, 0x63, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x10, 0x0a, 0x0e, - 0x46, 0x61, 0x75, 0x63, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, - 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x37, 0x0a, 0x11, - 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x22, 0x0a, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x05, - 0x76, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x73, 0x0a, 0x04, 0x56, 0x74, 0x78, 0x6f, 0x12, 0x29, 0x0a, - 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x08, - 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x08, 0x72, 0x65, 0x63, 0x65, - 0x69, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x72, 0x6b, - 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x52, 0x08, 0x72, 0x65, 0x63, 0x65, - 0x69, 0x76, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x22, 0x12, 0x0a, 0x10, 0x47, 0x65, - 0x74, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2b, - 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x32, 0xfd, 0x06, 0x0a, 0x0a, - 0x41, 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x73, 0x0a, 0x0f, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1e, 0x2e, - 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, + 0x75, 0x74, 0x22, 0x3a, 0x0a, 0x06, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x18, 0x0a, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xa8, + 0x01, 0x0a, 0x16, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x6f, 0x6f, + 0x6c, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x70, 0x6f, 0x6f, 0x6c, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x54, + 0x78, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x5f, 0x74, 0x78, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, + 0x78, 0x73, 0x12, 0x35, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x67, 0x65, + 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x72, 0x65, 0x65, 0x22, 0x31, 0x0a, 0x04, 0x54, 0x72, 0x65, + 0x65, 0x12, 0x29, 0x0a, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, + 0x65, 0x76, 0x65, 0x6c, 0x52, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x22, 0x2f, 0x0a, 0x09, + 0x54, 0x72, 0x65, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x22, 0x0a, 0x05, 0x6e, 0x6f, 0x64, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, + 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x4b, 0x0a, + 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x78, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x74, 0x78, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x72, + 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x54, 0x78, 0x69, 0x64, 0x22, 0x42, 0x0a, 0x13, 0x52, 0x6f, + 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6f, 0x6f, 0x6c, 0x54, 0x78, 0x69, 0x64, 0x22, 0x35, + 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, + 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, + 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x17, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xf4, + 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x12, 0x72, 0x6f, 0x75, + 0x6e, 0x64, 0x5f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x11, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, + 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x0f, 0x72, 0x6f, + 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, + 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x48, 0x00, 0x52, 0x0e, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, + 0x65, 0x64, 0x12, 0x38, 0x0a, 0x0c, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x61, 0x69, 0x6c, + 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x48, 0x00, 0x52, + 0x0b, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x42, 0x07, 0x0a, 0x05, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x2c, 0x0a, 0x0b, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x49, 0x64, 0x22, 0x0e, 0x0a, 0x0c, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x29, 0x0a, 0x0d, 0x46, 0x61, 0x75, 0x63, 0x65, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x10, + 0x0a, 0x0e, 0x46, 0x61, 0x75, 0x63, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x2c, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x37, + 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, + 0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x73, 0x0a, 0x04, 0x56, 0x74, 0x78, 0x6f, 0x12, + 0x29, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, + 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x08, 0x72, 0x65, + 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x52, 0x08, 0x72, 0x65, + 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x22, 0x12, 0x0a, 0x10, + 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x22, 0x2b, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x32, 0xfd, 0x06, + 0x0a, 0x0a, 0x41, 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x73, 0x0a, 0x0f, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, + 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1f, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x3a, 0x01, 0x2a, 0x22, 0x14, 0x2f, 0x76, 0x31, + 0x2f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x12, 0x67, 0x0a, 0x0c, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x12, 0x1b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x6d, + 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, + 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x50, 0x61, 0x79, + 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x16, 0x3a, 0x01, 0x2a, 0x22, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x61, 0x79, + 0x6d, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x12, 0x73, 0x0a, 0x0f, 0x46, 0x69, + 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1e, 0x2e, + 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, - 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, + 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x3a, 0x01, 0x2a, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x70, - 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, - 0x67, 0x0a, 0x0c, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, - 0x1b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x50, 0x61, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x50, 0x61, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x16, 0x3a, 0x01, 0x2a, 0x22, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x61, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x2f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x12, 0x73, 0x0a, 0x0f, 0x46, 0x69, 0x6e, 0x61, - 0x6c, 0x69, 0x7a, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1e, 0x2e, 0x61, 0x72, - 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x50, 0x61, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x61, 0x72, - 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x50, 0x61, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x19, 0x3a, 0x01, 0x2a, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x61, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x2f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x12, 0x57, 0x0a, - 0x08, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x17, 0x2e, 0x61, 0x72, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, - 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, - 0x7b, 0x74, 0x78, 0x69, 0x64, 0x7d, 0x12, 0x65, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0c, 0x12, - 0x0a, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x30, 0x01, 0x12, 0x50, 0x0a, - 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x13, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x50, - 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x72, 0x6b, - 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x69, - 0x6e, 0x67, 0x2f, 0x7b, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x12, - 0x55, 0x0a, 0x06, 0x46, 0x61, 0x75, 0x63, 0x65, 0x74, 0x12, 0x15, 0x2e, 0x61, 0x72, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x46, 0x61, 0x75, 0x63, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x16, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x75, 0x63, 0x65, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, - 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x61, 0x75, 0x63, 0x65, 0x74, 0x2f, 0x7b, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x7d, 0x12, 0x5d, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, - 0x78, 0x6f, 0x73, 0x12, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, - 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, - 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x2f, 0x7b, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x7d, 0x12, 0x54, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6b, - 0x65, 0x79, 0x12, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, - 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, - 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0c, 0x12, - 0x0a, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x42, 0x92, 0x01, 0x0a, 0x0a, - 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x6b, 0x2d, 0x6e, 0x65, 0x74, 0x77, 0x6f, - 0x72, 0x6b, 0x2f, 0x61, 0x72, 0x6b, 0x2f, 0x61, 0x70, 0x69, 0x2d, 0x73, 0x70, 0x65, 0x63, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x72, 0x6b, - 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x72, 0x6b, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x41, 0x58, 0x58, 0xaa, - 0x02, 0x06, 0x41, 0x72, 0x6b, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x5c, 0x56, - 0x31, 0xe2, 0x02, 0x12, 0x41, 0x72, 0x6b, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x41, 0x72, 0x6b, 0x3a, 0x3a, 0x56, 0x31, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x2f, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x12, + 0x57, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x17, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, + 0x64, 0x2f, 0x7b, 0x74, 0x78, 0x69, 0x64, 0x7d, 0x12, 0x65, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x0c, 0x12, 0x0a, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x30, 0x01, 0x12, + 0x50, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x13, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, + 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, 0x31, 0x2f, + 0x70, 0x69, 0x6e, 0x67, 0x2f, 0x7b, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, + 0x7d, 0x12, 0x55, 0x0a, 0x06, 0x46, 0x61, 0x75, 0x63, 0x65, 0x74, 0x12, 0x15, 0x2e, 0x61, 0x72, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x75, 0x63, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x61, 0x75, 0x63, + 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x16, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x61, 0x75, 0x63, 0x65, 0x74, 0x2f, 0x7b, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x7d, 0x12, 0x5d, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, + 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, + 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x2f, 0x7b, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x7d, 0x12, 0x54, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x50, 0x75, + 0x62, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, + 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6b, 0x65, + 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x0c, 0x12, 0x0a, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x42, 0x92, 0x01, + 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3d, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x6b, 0x2d, 0x6e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x61, 0x72, 0x6b, 0x2f, 0x61, 0x70, 0x69, 0x2d, 0x73, 0x70, 0x65, + 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, + 0x72, 0x6b, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x72, 0x6b, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x41, 0x58, + 0x58, 0xaa, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x06, 0x41, 0x72, 0x6b, + 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x12, 0x41, 0x72, 0x6b, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x41, 0x72, 0x6b, 0x3a, 0x3a, + 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/asp/api-spec/protobuf/gen/ocean/v1/transaction.pb.go b/asp/api-spec/protobuf/gen/ocean/v1/transaction.pb.go index cb95fdc..e8a7ab2 100644 --- a/asp/api-spec/protobuf/gen/ocean/v1/transaction.pb.go +++ b/asp/api-spec/protobuf/gen/ocean/v1/transaction.pb.go @@ -1786,6 +1786,110 @@ func (x *ClaimPegInResponse) GetTxHex() string { return "" } +type SignPsetWithSchnorrKeyRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The partial transaction to sign in base64 format. + Tx string `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"` + // The sighash type. SIGHASH_DEFAULT is used for any input that does not specify one. + SighashType uint32 `protobuf:"varint,2,opt,name=sighash_type,json=sighashType,proto3" json:"sighash_type,omitempty"` +} + +func (x *SignPsetWithSchnorrKeyRequest) Reset() { + *x = SignPsetWithSchnorrKeyRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_ocean_v1_transaction_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignPsetWithSchnorrKeyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignPsetWithSchnorrKeyRequest) ProtoMessage() {} + +func (x *SignPsetWithSchnorrKeyRequest) ProtoReflect() protoreflect.Message { + mi := &file_ocean_v1_transaction_proto_msgTypes[30] + 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 SignPsetWithSchnorrKeyRequest.ProtoReflect.Descriptor instead. +func (*SignPsetWithSchnorrKeyRequest) Descriptor() ([]byte, []int) { + return file_ocean_v1_transaction_proto_rawDescGZIP(), []int{30} +} + +func (x *SignPsetWithSchnorrKeyRequest) GetTx() string { + if x != nil { + return x.Tx + } + return "" +} + +func (x *SignPsetWithSchnorrKeyRequest) GetSighashType() uint32 { + if x != nil { + return x.SighashType + } + return 0 +} + +type SignPsetWithSchnorrKeyResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SignedTx string `protobuf:"bytes,1,opt,name=signed_tx,json=signedTx,proto3" json:"signed_tx,omitempty"` +} + +func (x *SignPsetWithSchnorrKeyResponse) Reset() { + *x = SignPsetWithSchnorrKeyResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_ocean_v1_transaction_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignPsetWithSchnorrKeyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignPsetWithSchnorrKeyResponse) ProtoMessage() {} + +func (x *SignPsetWithSchnorrKeyResponse) ProtoReflect() protoreflect.Message { + mi := &file_ocean_v1_transaction_proto_msgTypes[31] + 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 SignPsetWithSchnorrKeyResponse.ProtoReflect.Descriptor instead. +func (*SignPsetWithSchnorrKeyResponse) Descriptor() ([]byte, []int) { + return file_ocean_v1_transaction_proto_rawDescGZIP(), []int{31} +} + +func (x *SignPsetWithSchnorrKeyResponse) GetSignedTx() string { + if x != nil { + return x.SignedTx + } + return "" +} + var File_ocean_v1_transaction_proto protoreflect.FileDescriptor var file_ocean_v1_transaction_proto_rawDesc = []byte{ @@ -1970,77 +2074,93 @@ var file_ocean_v1_transaction_proto_rawDesc = []byte{ 0x61, 0x69, 0x6d, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x2b, 0x0a, 0x12, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x50, 0x65, 0x67, 0x49, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x74, 0x78, 0x5f, 0x68, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x74, 0x78, 0x48, 0x65, 0x78, 0x32, 0xe4, 0x08, 0x0a, 0x12, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x53, 0x0a, - 0x0e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x1f, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x20, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0b, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x55, 0x74, 0x78, 0x6f, - 0x73, 0x12, 0x1c, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1d, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, - 0x0a, 0x0c, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x73, 0x12, 0x1d, - 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, - 0x74, 0x65, 0x46, 0x65, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, - 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, - 0x65, 0x46, 0x65, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, - 0x0f, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x20, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x14, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, - 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x2e, - 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, - 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0a, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x73, 0x65, 0x74, 0x12, 0x1b, 0x2e, 0x6f, 0x63, 0x65, + 0x05, 0x74, 0x78, 0x48, 0x65, 0x78, 0x22, 0x52, 0x0a, 0x1d, 0x53, 0x69, 0x67, 0x6e, 0x50, 0x73, + 0x65, 0x74, 0x57, 0x69, 0x74, 0x68, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x4b, 0x65, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x78, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x74, 0x78, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x69, 0x67, 0x68, 0x61, + 0x73, 0x68, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x73, + 0x69, 0x67, 0x68, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3d, 0x0a, 0x1e, 0x53, 0x69, + 0x67, 0x6e, 0x50, 0x73, 0x65, 0x74, 0x57, 0x69, 0x74, 0x68, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, + 0x72, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x78, 0x32, 0xd1, 0x09, 0x0a, 0x12, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x53, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x1f, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0b, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x55, + 0x74, 0x78, 0x6f, 0x73, 0x12, 0x1c, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, + 0x6c, 0x65, 0x63, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x4d, 0x0a, 0x0c, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, + 0x73, 0x12, 0x1d, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x73, 0x74, + 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1e, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x73, 0x74, 0x69, + 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x56, 0x0a, 0x0f, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x14, 0x42, 0x72, 0x6f, 0x61, + 0x64, 0x63, 0x61, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x25, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x72, 0x6f, 0x61, + 0x64, 0x63, 0x61, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x47, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x73, 0x65, 0x74, 0x12, 0x1b, 0x2e, + 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, + 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x73, 0x65, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, - 0x73, 0x65, 0x74, 0x12, 0x1b, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1c, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x50, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, - 0x0a, 0x09, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x50, 0x73, 0x65, 0x74, 0x12, 0x1a, 0x2e, 0x6f, 0x63, - 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x50, 0x73, 0x65, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x50, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x08, 0x53, 0x69, 0x67, 0x6e, 0x50, 0x73, 0x65, 0x74, - 0x12, 0x19, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x50, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6f, 0x63, - 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x50, 0x73, 0x65, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x4d, 0x69, 0x6e, 0x74, 0x12, - 0x15, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x69, 0x6e, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x4d, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, - 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x69, 0x6e, 0x74, 0x12, 0x17, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x18, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, - 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x42, - 0x75, 0x72, 0x6e, 0x12, 0x15, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x42, - 0x75, 0x72, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6f, 0x63, 0x65, - 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x41, 0x0a, 0x08, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x12, 0x19, - 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, - 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6f, 0x63, 0x65, 0x61, - 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0c, 0x50, 0x65, 0x67, 0x49, 0x6e, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1d, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x65, 0x67, 0x49, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x65, 0x67, 0x49, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0a, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x50, 0x65, 0x67, - 0x49, 0x6e, 0x12, 0x1b, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, - 0x61, 0x69, 0x6d, 0x50, 0x65, 0x67, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1c, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x6d, - 0x50, 0x65, 0x67, 0x49, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0xa4, 0x01, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x50, 0x73, 0x65, 0x74, 0x12, 0x1b, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x44, 0x0a, 0x09, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x50, 0x73, 0x65, 0x74, 0x12, 0x1a, + 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x50, + 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6f, 0x63, 0x65, + 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x50, 0x73, 0x65, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x08, 0x53, 0x69, 0x67, 0x6e, 0x50, + 0x73, 0x65, 0x74, 0x12, 0x19, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x50, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, + 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x50, 0x73, + 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x4d, 0x69, + 0x6e, 0x74, 0x12, 0x15, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x69, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6f, 0x63, 0x65, 0x61, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x3b, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x69, 0x6e, 0x74, 0x12, 0x17, 0x2e, 0x6f, 0x63, + 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x6d, 0x69, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, + 0x0a, 0x04, 0x42, 0x75, 0x72, 0x6e, 0x12, 0x15, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x72, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x08, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, + 0x72, 0x12, 0x19, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x66, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6f, + 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0c, 0x50, 0x65, 0x67, 0x49, + 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1d, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x67, 0x49, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x65, 0x67, 0x49, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0a, 0x43, 0x6c, 0x61, 0x69, 0x6d, + 0x50, 0x65, 0x67, 0x49, 0x6e, 0x12, 0x1b, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x50, 0x65, 0x67, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, + 0x61, 0x69, 0x6d, 0x50, 0x65, 0x67, 0x49, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x6b, 0x0a, 0x16, 0x53, 0x69, 0x67, 0x6e, 0x50, 0x73, 0x65, 0x74, 0x57, 0x69, 0x74, 0x68, + 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x27, 0x2e, 0x6f, 0x63, 0x65, + 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x50, 0x73, 0x65, 0x74, 0x57, 0x69, + 0x74, 0x68, 0x53, 0x63, 0x68, 0x6e, 0x6f, 0x72, 0x72, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x50, 0x73, 0x65, 0x74, 0x57, 0x69, 0x74, 0x68, 0x53, 0x63, 0x68, 0x6e, 0x6f, + 0x72, 0x72, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0xa4, 0x01, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x42, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, @@ -2067,58 +2187,60 @@ func file_ocean_v1_transaction_proto_rawDescGZIP() []byte { } var file_ocean_v1_transaction_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_ocean_v1_transaction_proto_msgTypes = make([]protoimpl.MessageInfo, 30) +var file_ocean_v1_transaction_proto_msgTypes = make([]protoimpl.MessageInfo, 32) var file_ocean_v1_transaction_proto_goTypes = []interface{}{ - (SelectUtxosRequest_Strategy)(0), // 0: ocean.v1.SelectUtxosRequest.Strategy - (*GetTransactionRequest)(nil), // 1: ocean.v1.GetTransactionRequest - (*GetTransactionResponse)(nil), // 2: ocean.v1.GetTransactionResponse - (*SelectUtxosRequest)(nil), // 3: ocean.v1.SelectUtxosRequest - (*SelectUtxosResponse)(nil), // 4: ocean.v1.SelectUtxosResponse - (*EstimateFeesRequest)(nil), // 5: ocean.v1.EstimateFeesRequest - (*EstimateFeesResponse)(nil), // 6: ocean.v1.EstimateFeesResponse - (*SignTransactionRequest)(nil), // 7: ocean.v1.SignTransactionRequest - (*SignTransactionResponse)(nil), // 8: ocean.v1.SignTransactionResponse - (*BroadcastTransactionRequest)(nil), // 9: ocean.v1.BroadcastTransactionRequest - (*BroadcastTransactionResponse)(nil), // 10: ocean.v1.BroadcastTransactionResponse - (*CreatePsetRequest)(nil), // 11: ocean.v1.CreatePsetRequest - (*CreatePsetResponse)(nil), // 12: ocean.v1.CreatePsetResponse - (*UpdatePsetRequest)(nil), // 13: ocean.v1.UpdatePsetRequest - (*UpdatePsetResponse)(nil), // 14: ocean.v1.UpdatePsetResponse - (*BlindPsetRequest)(nil), // 15: ocean.v1.BlindPsetRequest - (*BlindPsetResponse)(nil), // 16: ocean.v1.BlindPsetResponse - (*SignPsetRequest)(nil), // 17: ocean.v1.SignPsetRequest - (*SignPsetResponse)(nil), // 18: ocean.v1.SignPsetResponse - (*MintRequest)(nil), // 19: ocean.v1.MintRequest - (*MintResponse)(nil), // 20: ocean.v1.MintResponse - (*RemintRequest)(nil), // 21: ocean.v1.RemintRequest - (*RemintResponse)(nil), // 22: ocean.v1.RemintResponse - (*BurnRequest)(nil), // 23: ocean.v1.BurnRequest - (*BurnResponse)(nil), // 24: ocean.v1.BurnResponse - (*TransferRequest)(nil), // 25: ocean.v1.TransferRequest - (*TransferResponse)(nil), // 26: ocean.v1.TransferResponse - (*PegInAddressRequest)(nil), // 27: ocean.v1.PegInAddressRequest - (*PegInAddressResponse)(nil), // 28: ocean.v1.PegInAddressResponse - (*ClaimPegInRequest)(nil), // 29: ocean.v1.ClaimPegInRequest - (*ClaimPegInResponse)(nil), // 30: ocean.v1.ClaimPegInResponse - (*BlockDetails)(nil), // 31: ocean.v1.BlockDetails - (*Utxo)(nil), // 32: ocean.v1.Utxo - (*Input)(nil), // 33: ocean.v1.Input - (*Output)(nil), // 34: ocean.v1.Output - (*UnblindedInput)(nil), // 35: ocean.v1.UnblindedInput + (SelectUtxosRequest_Strategy)(0), // 0: ocean.v1.SelectUtxosRequest.Strategy + (*GetTransactionRequest)(nil), // 1: ocean.v1.GetTransactionRequest + (*GetTransactionResponse)(nil), // 2: ocean.v1.GetTransactionResponse + (*SelectUtxosRequest)(nil), // 3: ocean.v1.SelectUtxosRequest + (*SelectUtxosResponse)(nil), // 4: ocean.v1.SelectUtxosResponse + (*EstimateFeesRequest)(nil), // 5: ocean.v1.EstimateFeesRequest + (*EstimateFeesResponse)(nil), // 6: ocean.v1.EstimateFeesResponse + (*SignTransactionRequest)(nil), // 7: ocean.v1.SignTransactionRequest + (*SignTransactionResponse)(nil), // 8: ocean.v1.SignTransactionResponse + (*BroadcastTransactionRequest)(nil), // 9: ocean.v1.BroadcastTransactionRequest + (*BroadcastTransactionResponse)(nil), // 10: ocean.v1.BroadcastTransactionResponse + (*CreatePsetRequest)(nil), // 11: ocean.v1.CreatePsetRequest + (*CreatePsetResponse)(nil), // 12: ocean.v1.CreatePsetResponse + (*UpdatePsetRequest)(nil), // 13: ocean.v1.UpdatePsetRequest + (*UpdatePsetResponse)(nil), // 14: ocean.v1.UpdatePsetResponse + (*BlindPsetRequest)(nil), // 15: ocean.v1.BlindPsetRequest + (*BlindPsetResponse)(nil), // 16: ocean.v1.BlindPsetResponse + (*SignPsetRequest)(nil), // 17: ocean.v1.SignPsetRequest + (*SignPsetResponse)(nil), // 18: ocean.v1.SignPsetResponse + (*MintRequest)(nil), // 19: ocean.v1.MintRequest + (*MintResponse)(nil), // 20: ocean.v1.MintResponse + (*RemintRequest)(nil), // 21: ocean.v1.RemintRequest + (*RemintResponse)(nil), // 22: ocean.v1.RemintResponse + (*BurnRequest)(nil), // 23: ocean.v1.BurnRequest + (*BurnResponse)(nil), // 24: ocean.v1.BurnResponse + (*TransferRequest)(nil), // 25: ocean.v1.TransferRequest + (*TransferResponse)(nil), // 26: ocean.v1.TransferResponse + (*PegInAddressRequest)(nil), // 27: ocean.v1.PegInAddressRequest + (*PegInAddressResponse)(nil), // 28: ocean.v1.PegInAddressResponse + (*ClaimPegInRequest)(nil), // 29: ocean.v1.ClaimPegInRequest + (*ClaimPegInResponse)(nil), // 30: ocean.v1.ClaimPegInResponse + (*SignPsetWithSchnorrKeyRequest)(nil), // 31: ocean.v1.SignPsetWithSchnorrKeyRequest + (*SignPsetWithSchnorrKeyResponse)(nil), // 32: ocean.v1.SignPsetWithSchnorrKeyResponse + (*BlockDetails)(nil), // 33: ocean.v1.BlockDetails + (*Utxo)(nil), // 34: ocean.v1.Utxo + (*Input)(nil), // 35: ocean.v1.Input + (*Output)(nil), // 36: ocean.v1.Output + (*UnblindedInput)(nil), // 37: ocean.v1.UnblindedInput } var file_ocean_v1_transaction_proto_depIdxs = []int32{ - 31, // 0: ocean.v1.GetTransactionResponse.block_details:type_name -> ocean.v1.BlockDetails + 33, // 0: ocean.v1.GetTransactionResponse.block_details:type_name -> ocean.v1.BlockDetails 0, // 1: ocean.v1.SelectUtxosRequest.strategy:type_name -> ocean.v1.SelectUtxosRequest.Strategy - 32, // 2: ocean.v1.SelectUtxosResponse.utxos:type_name -> ocean.v1.Utxo - 33, // 3: ocean.v1.EstimateFeesRequest.inputs:type_name -> ocean.v1.Input - 34, // 4: ocean.v1.EstimateFeesRequest.outputs:type_name -> ocean.v1.Output - 33, // 5: ocean.v1.CreatePsetRequest.inputs:type_name -> ocean.v1.Input - 34, // 6: ocean.v1.CreatePsetRequest.outputs:type_name -> ocean.v1.Output - 33, // 7: ocean.v1.UpdatePsetRequest.inputs:type_name -> ocean.v1.Input - 34, // 8: ocean.v1.UpdatePsetRequest.outputs:type_name -> ocean.v1.Output - 35, // 9: ocean.v1.BlindPsetRequest.extra_unblinded_inputs:type_name -> ocean.v1.UnblindedInput - 34, // 10: ocean.v1.BurnRequest.receivers:type_name -> ocean.v1.Output - 34, // 11: ocean.v1.TransferRequest.receivers:type_name -> ocean.v1.Output + 34, // 2: ocean.v1.SelectUtxosResponse.utxos:type_name -> ocean.v1.Utxo + 35, // 3: ocean.v1.EstimateFeesRequest.inputs:type_name -> ocean.v1.Input + 36, // 4: ocean.v1.EstimateFeesRequest.outputs:type_name -> ocean.v1.Output + 35, // 5: ocean.v1.CreatePsetRequest.inputs:type_name -> ocean.v1.Input + 36, // 6: ocean.v1.CreatePsetRequest.outputs:type_name -> ocean.v1.Output + 35, // 7: ocean.v1.UpdatePsetRequest.inputs:type_name -> ocean.v1.Input + 36, // 8: ocean.v1.UpdatePsetRequest.outputs:type_name -> ocean.v1.Output + 37, // 9: ocean.v1.BlindPsetRequest.extra_unblinded_inputs:type_name -> ocean.v1.UnblindedInput + 36, // 10: ocean.v1.BurnRequest.receivers:type_name -> ocean.v1.Output + 36, // 11: ocean.v1.TransferRequest.receivers:type_name -> ocean.v1.Output 1, // 12: ocean.v1.TransactionService.GetTransaction:input_type -> ocean.v1.GetTransactionRequest 3, // 13: ocean.v1.TransactionService.SelectUtxos:input_type -> ocean.v1.SelectUtxosRequest 5, // 14: ocean.v1.TransactionService.EstimateFees:input_type -> ocean.v1.EstimateFeesRequest @@ -2134,23 +2256,25 @@ var file_ocean_v1_transaction_proto_depIdxs = []int32{ 25, // 24: ocean.v1.TransactionService.Transfer:input_type -> ocean.v1.TransferRequest 27, // 25: ocean.v1.TransactionService.PegInAddress:input_type -> ocean.v1.PegInAddressRequest 29, // 26: ocean.v1.TransactionService.ClaimPegIn:input_type -> ocean.v1.ClaimPegInRequest - 2, // 27: ocean.v1.TransactionService.GetTransaction:output_type -> ocean.v1.GetTransactionResponse - 4, // 28: ocean.v1.TransactionService.SelectUtxos:output_type -> ocean.v1.SelectUtxosResponse - 6, // 29: ocean.v1.TransactionService.EstimateFees:output_type -> ocean.v1.EstimateFeesResponse - 8, // 30: ocean.v1.TransactionService.SignTransaction:output_type -> ocean.v1.SignTransactionResponse - 10, // 31: ocean.v1.TransactionService.BroadcastTransaction:output_type -> ocean.v1.BroadcastTransactionResponse - 12, // 32: ocean.v1.TransactionService.CreatePset:output_type -> ocean.v1.CreatePsetResponse - 14, // 33: ocean.v1.TransactionService.UpdatePset:output_type -> ocean.v1.UpdatePsetResponse - 16, // 34: ocean.v1.TransactionService.BlindPset:output_type -> ocean.v1.BlindPsetResponse - 18, // 35: ocean.v1.TransactionService.SignPset:output_type -> ocean.v1.SignPsetResponse - 20, // 36: ocean.v1.TransactionService.Mint:output_type -> ocean.v1.MintResponse - 22, // 37: ocean.v1.TransactionService.Remint:output_type -> ocean.v1.RemintResponse - 24, // 38: ocean.v1.TransactionService.Burn:output_type -> ocean.v1.BurnResponse - 26, // 39: ocean.v1.TransactionService.Transfer:output_type -> ocean.v1.TransferResponse - 28, // 40: ocean.v1.TransactionService.PegInAddress:output_type -> ocean.v1.PegInAddressResponse - 30, // 41: ocean.v1.TransactionService.ClaimPegIn:output_type -> ocean.v1.ClaimPegInResponse - 27, // [27:42] is the sub-list for method output_type - 12, // [12:27] is the sub-list for method input_type + 31, // 27: ocean.v1.TransactionService.SignPsetWithSchnorrKey:input_type -> ocean.v1.SignPsetWithSchnorrKeyRequest + 2, // 28: ocean.v1.TransactionService.GetTransaction:output_type -> ocean.v1.GetTransactionResponse + 4, // 29: ocean.v1.TransactionService.SelectUtxos:output_type -> ocean.v1.SelectUtxosResponse + 6, // 30: ocean.v1.TransactionService.EstimateFees:output_type -> ocean.v1.EstimateFeesResponse + 8, // 31: ocean.v1.TransactionService.SignTransaction:output_type -> ocean.v1.SignTransactionResponse + 10, // 32: ocean.v1.TransactionService.BroadcastTransaction:output_type -> ocean.v1.BroadcastTransactionResponse + 12, // 33: ocean.v1.TransactionService.CreatePset:output_type -> ocean.v1.CreatePsetResponse + 14, // 34: ocean.v1.TransactionService.UpdatePset:output_type -> ocean.v1.UpdatePsetResponse + 16, // 35: ocean.v1.TransactionService.BlindPset:output_type -> ocean.v1.BlindPsetResponse + 18, // 36: ocean.v1.TransactionService.SignPset:output_type -> ocean.v1.SignPsetResponse + 20, // 37: ocean.v1.TransactionService.Mint:output_type -> ocean.v1.MintResponse + 22, // 38: ocean.v1.TransactionService.Remint:output_type -> ocean.v1.RemintResponse + 24, // 39: ocean.v1.TransactionService.Burn:output_type -> ocean.v1.BurnResponse + 26, // 40: ocean.v1.TransactionService.Transfer:output_type -> ocean.v1.TransferResponse + 28, // 41: ocean.v1.TransactionService.PegInAddress:output_type -> ocean.v1.PegInAddressResponse + 30, // 42: ocean.v1.TransactionService.ClaimPegIn:output_type -> ocean.v1.ClaimPegInResponse + 32, // 43: ocean.v1.TransactionService.SignPsetWithSchnorrKey:output_type -> ocean.v1.SignPsetWithSchnorrKeyResponse + 28, // [28:44] is the sub-list for method output_type + 12, // [12:28] is the sub-list for method input_type 12, // [12:12] is the sub-list for extension type_name 12, // [12:12] is the sub-list for extension extendee 0, // [0:12] is the sub-list for field type_name @@ -2523,6 +2647,30 @@ func file_ocean_v1_transaction_proto_init() { return nil } } + file_ocean_v1_transaction_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignPsetWithSchnorrKeyRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ocean_v1_transaction_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignPsetWithSchnorrKeyResponse); 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{ @@ -2530,7 +2678,7 @@ func file_ocean_v1_transaction_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_ocean_v1_transaction_proto_rawDesc, NumEnums: 1, - NumMessages: 30, + NumMessages: 32, NumExtensions: 0, NumServices: 1, }, diff --git a/asp/api-spec/protobuf/gen/ocean/v1/transaction_grpc.pb.go b/asp/api-spec/protobuf/gen/ocean/v1/transaction_grpc.pb.go index 5724dfa..c0037a0 100644 --- a/asp/api-spec/protobuf/gen/ocean/v1/transaction_grpc.pb.go +++ b/asp/api-spec/protobuf/gen/ocean/v1/transaction_grpc.pb.go @@ -56,6 +56,9 @@ type TransactionServiceClient interface { // ClaimPegIn returns a transaction to claim funds pegged on the Bitcoin // main-chain to have them available on the Liquid side-chain. ClaimPegIn(ctx context.Context, in *ClaimPegInRequest, opts ...grpc.CallOption) (*ClaimPegInResponse, error) + // SignPsetWithSchnorrKey signs all taproot inputs of the provided tx with + // the key at the given derivation path. + SignPsetWithSchnorrKey(ctx context.Context, in *SignPsetWithSchnorrKeyRequest, opts ...grpc.CallOption) (*SignPsetWithSchnorrKeyResponse, error) } type transactionServiceClient struct { @@ -201,6 +204,15 @@ func (c *transactionServiceClient) ClaimPegIn(ctx context.Context, in *ClaimPegI return out, nil } +func (c *transactionServiceClient) SignPsetWithSchnorrKey(ctx context.Context, in *SignPsetWithSchnorrKeyRequest, opts ...grpc.CallOption) (*SignPsetWithSchnorrKeyResponse, error) { + out := new(SignPsetWithSchnorrKeyResponse) + err := c.cc.Invoke(ctx, "/ocean.v1.TransactionService/SignPsetWithSchnorrKey", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // TransactionServiceServer is the server API for TransactionService service. // All implementations should embed UnimplementedTransactionServiceServer // for forward compatibility @@ -243,6 +255,9 @@ type TransactionServiceServer interface { // ClaimPegIn returns a transaction to claim funds pegged on the Bitcoin // main-chain to have them available on the Liquid side-chain. ClaimPegIn(context.Context, *ClaimPegInRequest) (*ClaimPegInResponse, error) + // SignPsetWithSchnorrKey signs all taproot inputs of the provided tx with + // the key at the given derivation path. + SignPsetWithSchnorrKey(context.Context, *SignPsetWithSchnorrKeyRequest) (*SignPsetWithSchnorrKeyResponse, error) } // UnimplementedTransactionServiceServer should be embedded to have forward compatible implementations. @@ -294,6 +309,9 @@ func (UnimplementedTransactionServiceServer) PegInAddress(context.Context, *PegI func (UnimplementedTransactionServiceServer) ClaimPegIn(context.Context, *ClaimPegInRequest) (*ClaimPegInResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ClaimPegIn not implemented") } +func (UnimplementedTransactionServiceServer) SignPsetWithSchnorrKey(context.Context, *SignPsetWithSchnorrKeyRequest) (*SignPsetWithSchnorrKeyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SignPsetWithSchnorrKey not implemented") +} // UnsafeTransactionServiceServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to TransactionServiceServer will @@ -576,6 +594,24 @@ func _TransactionService_ClaimPegIn_Handler(srv interface{}, ctx context.Context return interceptor(ctx, in, info, handler) } +func _TransactionService_SignPsetWithSchnorrKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SignPsetWithSchnorrKeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TransactionServiceServer).SignPsetWithSchnorrKey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ocean.v1.TransactionService/SignPsetWithSchnorrKey", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TransactionServiceServer).SignPsetWithSchnorrKey(ctx, req.(*SignPsetWithSchnorrKeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + // TransactionService_ServiceDesc is the grpc.ServiceDesc for TransactionService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -643,6 +679,10 @@ var TransactionService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ClaimPegIn", Handler: _TransactionService_ClaimPegIn_Handler, }, + { + MethodName: "SignPsetWithSchnorrKey", + Handler: _TransactionService_SignPsetWithSchnorrKey_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "ocean/v1/transaction.proto", diff --git a/asp/internal/core/application/service.go b/asp/internal/core/application/service.go index 7b517e6..fe075d0 100644 --- a/asp/internal/core/application/service.go +++ b/asp/internal/core/application/service.go @@ -395,6 +395,10 @@ func (s *service) getNewVtxos(round *domain.Round) []domain.Vtxo { var pubkey string found := false for _, r := range p.Receivers { + if r.IsOnchain() { + continue + } + buf, _ := hex.DecodeString(r.Pubkey) pk, _ := secp256k1.ParsePubKey(buf) script, _ := s.builder.GetLeafOutputScript(pk, s.pubkey) diff --git a/asp/internal/core/application/utils.go b/asp/internal/core/application/utils.go index d62defd..6feff89 100644 --- a/asp/internal/core/application/utils.go +++ b/asp/internal/core/application/utils.go @@ -34,7 +34,13 @@ func (m *paymentsMap) len() int64 { m.lock.RLock() defer m.lock.RUnlock() - return int64(len(m.payments)) + count := int64(0) + for _, p := range m.payments { + if len(p.Receivers) > 0 { + count++ + } + } + return count } func (m *paymentsMap) push(payment domain.Payment) error { diff --git a/asp/internal/core/domain/payment.go b/asp/internal/core/domain/payment.go index 0b16b81..727ef47 100644 --- a/asp/internal/core/domain/payment.go +++ b/asp/internal/core/domain/payment.go @@ -9,6 +9,8 @@ import ( "github.com/google/uuid" ) +const dustAmount = 450 + type Payment struct { Id string Inputs []Vtxo @@ -71,7 +73,16 @@ func (p Payment) validate(ignoreOuts bool) error { } // Check that input and output and output amounts match. inAmount := p.TotalInputAmount() - outAmount := p.TotalOutputAmount() + outAmount := uint64(0) + for _, r := range p.Receivers { + if len(r.OnchainAddress) <= 0 && len(r.Pubkey) <= 0 { + return fmt.Errorf("missing receiver destination") + } + if r.Amount < dustAmount { + return fmt.Errorf("receiver amount must be greater than dust") + } + outAmount += r.Amount + } if inAmount != outAmount { return fmt.Errorf("input and output amounts mismatch") } @@ -99,8 +110,13 @@ func (k VtxoKey) Hash() string { } type Receiver struct { - Pubkey string - Amount uint64 + Pubkey string + Amount uint64 + OnchainAddress string +} + +func (r Receiver) IsOnchain() bool { + return len(r.OnchainAddress) > 0 } type Vtxo struct { diff --git a/asp/internal/infrastructure/tx-builder/covenant/builder.go b/asp/internal/infrastructure/tx-builder/covenant/builder.go index 216f5fa..add0b8c 100644 --- a/asp/internal/infrastructure/tx-builder/covenant/builder.go +++ b/asp/internal/infrastructure/tx-builder/covenant/builder.go @@ -153,13 +153,13 @@ func (b *txBuilder) BuildPoolTx( ) (poolTx string, congestionTree domain.CongestionTree, err error) { aspScriptBytes, err := p2wpkhScript(aspPubkey, b.net) if err != nil { - return "", nil, err + return } aspScript := hex.EncodeToString(aspScriptBytes) - receivers := receiversFromPayments(payments) - sharedOutputAmount := sumReceivers(receivers) + offchainReceivers, onchainReceivers := receiversFromPayments(payments) + sharedOutputAmount := sumReceivers(offchainReceivers) numberOfConnectors := numberOfVTXOs(payments) connectorOutputAmount := connectorAmount * numberOfConnectors @@ -169,36 +169,46 @@ func (b *txBuilder) BuildPoolTx( makeTree, sharedOutputScript, err := buildCongestionTree( b.net, aspPubkey, - receivers, + offchainReceivers, ) if err != nil { - return "", nil, err + return } sharedOutputScriptHex := hex.EncodeToString(sharedOutputScript) - poolTx, err = wallet.Transfer(ctx, []ports.TxOutput{ + poolTxOuts := []ports.TxOutput{ newOutput(sharedOutputScriptHex, sharedOutputAmount, b.net.AssetID), newOutput(aspScript, connectorOutputAmount, b.net.AssetID), - }) - if err != nil { - return "", nil, err } - poolTransaction, err := transaction.NewTxFromHex(poolTx) - if err != nil { - return "", nil, err + for _, receiver := range onchainReceivers { + buf, _ := address.ToOutputScript(receiver.OnchainAddress) + script := hex.EncodeToString(buf) + poolTxOuts = append(poolTxOuts, newOutput(script, receiver.Amount, b.net.AssetID)) } - congestionTree, err = makeTree(psetv2.InputArgs{ - Txid: poolTransaction.TxHash().String(), + txHex, err := wallet.Transfer(ctx, poolTxOuts) + if err != nil { + return + } + + tx, err := transaction.NewTxFromHex(txHex) + if err != nil { + return + } + + tree, err := makeTree(psetv2.InputArgs{ + Txid: tx.TxHash().String(), TxIndex: 0, }) if err != nil { - return "", nil, err + return } - return poolTx, congestionTree, nil + poolTx = txHex + congestionTree = tree + return } func connectorsToInputArgs(connectors []string) ([]psetv2.InputArgs, error) { @@ -248,12 +258,19 @@ func numberOfVTXOs(payments []domain.Payment) uint64 { return sum } -func receiversFromPayments(payments []domain.Payment) []domain.Receiver { - receivers := make([]domain.Receiver, 0) +func receiversFromPayments( + payments []domain.Payment, +) (offchainReceivers, onchainReceivers []domain.Receiver) { for _, payment := range payments { - receivers = append(receivers, payment.Receivers...) + for _, receiver := range payment.Receivers { + if receiver.IsOnchain() { + onchainReceivers = append(onchainReceivers, receiver) + } else { + offchainReceivers = append(offchainReceivers, receiver) + } + } } - return receivers + return } func sumReceivers(receivers []domain.Receiver) uint64 { diff --git a/asp/internal/infrastructure/tx-builder/covenant/tree.go b/asp/internal/infrastructure/tx-builder/covenant/tree.go index e3bb69d..0fc6b79 100644 --- a/asp/internal/infrastructure/tx-builder/covenant/tree.go +++ b/asp/internal/infrastructure/tx-builder/covenant/tree.go @@ -116,9 +116,12 @@ func sweepTapLeaf(sweepKey *secp256k1.PublicKey) (*taproot.TapElementsLeaf, erro func forceSplitCoinTapLeaf( leftKey, rightKey *secp256k1.PublicKey, leftAmount, rightAmount uint32, ) taproot.TapElementsLeaf { - nextScriptLeft := withOutput(0, schnorr.SerializePubKey(leftKey), leftAmount, true) - nextScriptRight := withOutput(1, schnorr.SerializePubKey(rightKey), rightAmount, false) - branchScript := append(nextScriptLeft, nextScriptRight...) + nextScriptLeft := withOutput(0, schnorr.SerializePubKey(leftKey), leftAmount, rightKey != nil) + branchScript := append([]byte{}, nextScriptLeft...) + if rightKey != nil { + nextScriptRight := withOutput(1, schnorr.SerializePubKey(rightKey), rightAmount, false) + branchScript = append(branchScript, nextScriptRight...) + } return taproot.NewBaseTapElementsLeaf(branchScript) } @@ -204,9 +207,7 @@ func buildCongestionTree( if err != nil { return nil, nil, err } - leftOutput := rootPset.Outputs[0] - rightOutput := rootPset.Outputs[1] leftWitnessProgram := leftOutput.Script[2:] leftKey, err := schnorr.ParsePubKey(leftWitnessProgram) @@ -214,14 +215,19 @@ func buildCongestionTree( return nil, nil, err } - rightWitnessProgram := rightOutput.Script[2:] - rightKey, err := schnorr.ParsePubKey(rightWitnessProgram) - if err != nil { - return nil, nil, err + var rightAmount uint32 + var rightKey *secp256k1.PublicKey + + if len(rootPset.Outputs) > 1 { + rightAmount = uint32(rootPset.Outputs[1].Value) + rightKey, err = schnorr.ParsePubKey(rootPset.Outputs[1].Script[2:]) + if err != nil { + return nil, nil, err + } } goToTreeScript := forceSplitCoinTapLeaf( - leftKey, rightKey, uint32(leftOutput.Value), uint32(rightOutput.Value), + leftKey, rightKey, uint32(leftOutput.Value), rightAmount, ) taprootTree := taproot.AssembleTaprootScriptTree(goToTreeScript, *sweepLeaf) diff --git a/asp/internal/infrastructure/tx-builder/dummy/builder.go b/asp/internal/infrastructure/tx-builder/dummy/builder.go index e74aa3d..6334415 100644 --- a/asp/internal/infrastructure/tx-builder/dummy/builder.go +++ b/asp/internal/infrastructure/tx-builder/dummy/builder.go @@ -99,18 +99,25 @@ func (b *txBuilder) BuildPoolTx( aspScript := hex.EncodeToString(aspScriptBytes) - receivers := receiversFromPayments(payments) - sharedOutputAmount := sumReceivers(receivers) + offchainReceivers, onchainReceivers := receiversFromPayments(payments) + sharedOutputAmount := sumReceivers(offchainReceivers) numberOfConnectors := numberOfVTXOs(payments) connectorOutputAmount := connectorAmount * numberOfConnectors - ctx := context.Background() - - poolTx, err = wallet.Transfer(ctx, []ports.TxOutput{ + poolTxOuts := []ports.TxOutput{ newOutput(aspScript, sharedOutputAmount, b.net.AssetID), newOutput(aspScript, connectorOutputAmount, b.net.AssetID), - }) + } + for _, receiver := range onchainReceivers { + buf, _ := address.ToOutputScript(receiver.OnchainAddress) + script := hex.EncodeToString(buf) + poolTxOuts = append(poolTxOuts, newOutput(script, receiver.Amount, b.net.AssetID)) + } + + ctx := context.Background() + + poolTx, err = wallet.Transfer(ctx, poolTxOuts) if err != nil { return "", nil, err } @@ -124,7 +131,7 @@ func (b *txBuilder) BuildPoolTx( newOutputScriptFactory(aspPubkey, b.net), b.net, poolTxID, - receivers, + offchainReceivers, ) return poolTx, congestionTree, err @@ -187,12 +194,19 @@ func numberOfVTXOs(payments []domain.Payment) uint64 { return sum } -func receiversFromPayments(payments []domain.Payment) []domain.Receiver { - receivers := make([]domain.Receiver, 0) +func receiversFromPayments( + payments []domain.Payment, +) (offchainReceivers, onchainReceivers []domain.Receiver) { for _, payment := range payments { - receivers = append(receivers, payment.Receivers...) + for _, receiver := range payment.Receivers { + if receiver.IsOnchain() { + onchainReceivers = append(onchainReceivers, receiver) + } else { + offchainReceivers = append(offchainReceivers, receiver) + } + } } - return receivers + return } func sumReceivers(receivers []domain.Receiver) uint64 { diff --git a/asp/internal/interface/grpc/handlers/arkservice.go b/asp/internal/interface/grpc/handlers/arkservice.go index bcb5664..6547eeb 100644 --- a/asp/internal/interface/grpc/handlers/arkservice.go +++ b/asp/internal/interface/grpc/handlers/arkservice.go @@ -2,11 +2,14 @@ package handlers import ( "context" + "encoding/hex" "sync" arkv1 "github.com/ark-network/ark/api-spec/protobuf/gen/ark/v1" + "github.com/ark-network/ark/common" "github.com/ark-network/ark/internal/core/application" "github.com/ark-network/ark/internal/core/domain" + "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/google/uuid" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -68,16 +71,12 @@ func (h *handler) RegisterPayment(ctx context.Context, req *arkv1.RegisterPaymen } func (h *handler) ClaimPayment(ctx context.Context, req *arkv1.ClaimPaymentRequest) (*arkv1.ClaimPaymentResponse, error) { - receivers := make([]domain.Receiver, 0, len(req.GetOutputs())) - for _, output := range req.GetOutputs() { - receivers = append(receivers, domain.Receiver{ - Pubkey: output.GetPubkey(), - Amount: output.GetAmount(), - }) + receivers, err := parseReceivers(req.GetOutputs()) + if err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) } - err := h.svc.ClaimVtxos(ctx, req.GetId(), receivers) - if err != nil { + if err := h.svc.ClaimVtxos(ctx, req.GetId(), receivers); err != nil { return nil, err } @@ -97,7 +96,7 @@ func (h *handler) FinalizePayment(ctx context.Context, req *arkv1.FinalizePaymen } func (h *handler) Faucet(ctx context.Context, req *arkv1.FaucetRequest) (*arkv1.FaucetResponse, error) { - pubkey, err := parseAddress(req.GetAddress()) + _, pubkey, _, err := parseAddress(req.GetAddress()) if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } @@ -163,18 +162,18 @@ func (h *handler) GetEventStream(_ *arkv1.GetEventStreamRequest, stream arkv1.Ar } func (h *handler) ListVtxos(ctx context.Context, req *arkv1.ListVtxosRequest) (*arkv1.ListVtxosResponse, error) { - pubkey, err := parseAddress(req.GetAddress()) + hrp, userPubkey, aspPubkey, err := parseAddress(req.GetAddress()) if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } - vtxos, err := h.svc.ListVtxos(ctx, pubkey) + vtxos, err := h.svc.ListVtxos(ctx, userPubkey) if err != nil { return nil, err } return &arkv1.ListVtxosResponse{ - Vtxos: vtxoList(vtxos).toProto(), + Vtxos: vtxoList(vtxos).toProto(hrp, aspPubkey), }, nil } @@ -256,17 +255,23 @@ func (h *handler) listenToEvents() { type vtxoList []domain.Vtxo -func (v vtxoList) toProto() []*arkv1.Vtxo { +func (v vtxoList) toProto(hrp string, aspKey *secp256k1.PublicKey) []*arkv1.Vtxo { list := make([]*arkv1.Vtxo, 0, len(v)) for _, vv := range v { + addr := vv.OnchainAddress + if vv.Pubkey != "" { + buf, _ := hex.DecodeString(vv.Pubkey) + key, _ := secp256k1.ParsePubKey(buf) + addr, _ = common.EncodeAddress(hrp, key, aspKey) + } list = append(list, &arkv1.Vtxo{ Outpoint: &arkv1.Input{ Txid: vv.Txid, Vout: vv.VOut, }, Receiver: &arkv1.Output{ - Pubkey: vv.Pubkey, - Amount: vv.Amount, + Address: addr, + Amount: vv.Amount, }, Spent: vv.Spent, }) diff --git a/asp/internal/interface/grpc/handlers/utils.go b/asp/internal/interface/grpc/handlers/utils.go index 69e7e50..02e04a6 100644 --- a/asp/internal/interface/grpc/handlers/utils.go +++ b/asp/internal/interface/grpc/handlers/utils.go @@ -1,10 +1,14 @@ package handlers import ( + "encoding/hex" "fmt" + arkv1 "github.com/ark-network/ark/api-spec/protobuf/gen/ark/v1" "github.com/ark-network/ark/common" + "github.com/ark-network/ark/internal/core/domain" "github.com/decred/dcrd/dcrec/secp256k1/v4" + "github.com/vulpemventures/go-elements/address" "github.com/vulpemventures/go-elements/psetv2" ) @@ -20,13 +24,41 @@ func parseTxs(txs []string) ([]string, error) { return txs, nil } -func parseAddress(addr string) (*secp256k1.PublicKey, error) { +func parseAddress(addr string) (string, *secp256k1.PublicKey, *secp256k1.PublicKey, error) { if len(addr) <= 0 { - return nil, fmt.Errorf("missing address") + return "", nil, nil, fmt.Errorf("missing address") } - _, userPubkey, _, err := common.DecodeAddress(addr) - if err != nil { - return nil, fmt.Errorf("invalid address: %s", err) - } - return userPubkey, nil + return common.DecodeAddress(addr) +} + +func parseReceivers(outs []*arkv1.Output) ([]domain.Receiver, error) { + receivers := make([]domain.Receiver, 0, len(outs)) + for _, out := range outs { + if out.GetAmount() == 0 { + return nil, fmt.Errorf("missing output amount") + } + if len(out.GetAddress()) <= 0 { + return nil, fmt.Errorf("missing output address") + } + var pubkey, addr string + _, pk, _, err := common.DecodeAddress(out.GetAddress()) + if err != nil { + if _, err := address.ToOutputScript(out.GetAddress()); err != nil { + return nil, fmt.Errorf("invalid output address: unknown format") + } + if isConf, _ := address.IsConfidential(out.GetAddress()); isConf { + return nil, fmt.Errorf("invalid output address: must be unconfidential") + } + addr = out.GetAddress() + } + if pk != nil { + pubkey = hex.EncodeToString(pk.SerializeCompressed()) + } + receivers = append(receivers, domain.Receiver{ + Pubkey: pubkey, + Amount: out.GetAmount(), + OnchainAddress: addr, + }) + } + return receivers, nil } diff --git a/noah/balance.go b/noah/balance.go index 89fa293..4fd31af 100644 --- a/noah/balance.go +++ b/noah/balance.go @@ -1,6 +1,8 @@ package main import ( + "sync" + "github.com/urfave/cli/v2" ) @@ -11,20 +13,68 @@ var balanceCommand = cli.Command{ } func balanceAction(ctx *cli.Context) error { - client, close, err := getArkClient(ctx) + client, cancel, err := getClientFromState(ctx) if err != nil { return err } - defer close() + defer cancel() - vtxos, err := getVtxos(ctx, client) + offchainAddr, onchainAddr, err := getAddress() if err != nil { return err } - balance := computeBalance(vtxos) + wg := &sync.WaitGroup{} + wg.Add(2) + + chRes := make(chan balanceRes, 2) + go func() { + defer wg.Done() + balance, err := getOffchainBalance(ctx, client, offchainAddr) + if err != nil { + chRes <- balanceRes{0, 0, err} + return + } + chRes <- balanceRes{balance, 0, nil} + }() + go func() { + defer wg.Done() + balance, err := getOnchainBalance(onchainAddr) + if err != nil { + chRes <- balanceRes{0, 0, err} + return + } + chRes <- balanceRes{0, balance, nil} + }() + + wg.Wait() + + offchainBalance, onchainBalance := uint64(0), uint64(0) + count := 0 + for res := range chRes { + if res.err != nil { + return res.err + } + if res.offchainBalance > 0 { + offchainBalance = res.offchainBalance + } + if res.onchainBalance > 0 { + onchainBalance = res.onchainBalance + } + count++ + if count == 2 { + break + } + } return printJSON(map[string]interface{}{ - "balance": balance, + "offchain_balance": offchainBalance, + "onchain_balance": onchainBalance, }) } + +type balanceRes struct { + offchainBalance uint64 + onchainBalance uint64 + err error +} diff --git a/noah/client.go b/noah/client.go index 4a2c7b8..0f096c7 100644 --- a/noah/client.go +++ b/noah/client.go @@ -15,12 +15,9 @@ type vtxo struct { vout uint32 } -func getVtxos(ctx *cli.Context, client arkv1.ArkServiceClient) ([]vtxo, error) { - addr, err := getAddress() - if err != nil { - return nil, err - } - +func getVtxos( + ctx *cli.Context, client arkv1.ArkServiceClient, addr string, +) ([]vtxo, error) { response, err := client.ListVtxos(ctx.Context, &arkv1.ListVtxosRequest{ Address: addr, }) @@ -40,9 +37,20 @@ func getVtxos(ctx *cli.Context, client arkv1.ArkServiceClient) ([]vtxo, error) { return vtxos, nil } -// get the ark client and a function closing the connection -func getArkClient(ctx *cli.Context) (arkv1.ArkServiceClient, func(), error) { - conn, err := getConn(ctx) +func getClientFromState(ctx *cli.Context) (arkv1.ArkServiceClient, func(), error) { + state, err := getState() + if err != nil { + return nil, nil, err + } + addr, ok := state["ark_url"] + if !ok { + return nil, nil, fmt.Errorf("missing ark_url") + } + return getClient(ctx, addr) +} + +func getClient(ctx *cli.Context, addr string) (arkv1.ArkServiceClient, func(), error) { + conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { return nil, nil, err } @@ -58,23 +66,3 @@ func getArkClient(ctx *cli.Context) (arkv1.ArkServiceClient, func(), error) { return client, closeFn, nil } - -// connect to the ark rpc URL specified in the config -func getConn(ctx *cli.Context) (*grpc.ClientConn, error) { - state, err := getState() - if err != nil { - return nil, err - } - - rpcUrl, ok := state["ark_url"] - if !ok { - return nil, fmt.Errorf("missing ark_url") - } - - conn, err := grpc.Dial(rpcUrl, grpc.WithTransportCredentials(insecure.NewCredentials())) - if err != nil { - return nil, err - } - - return conn, nil -} diff --git a/noah/common.go b/noah/common.go index 69e28c7..764a63c 100644 --- a/noah/common.go +++ b/noah/common.go @@ -6,10 +6,16 @@ import ( "encoding/hex" "encoding/json" "fmt" + "io" + "net/http" "syscall" + arkv1 "github.com/ark-network/ark/api-spec/protobuf/gen/ark/v1" "github.com/ark-network/ark/common" "github.com/decred/dcrd/dcrec/secp256k1/v4" + "github.com/urfave/cli/v2" + "github.com/vulpemventures/go-elements/network" + "github.com/vulpemventures/go-elements/payment" "golang.org/x/term" ) @@ -150,49 +156,103 @@ func coinSelect(vtxos []vtxo, amount uint64) ([]vtxo, uint64, error) { return selected, change, nil } -func computeBalance(vtxos []vtxo) uint64 { +func getOffchainBalance( + ctx *cli.Context, client arkv1.ArkServiceClient, addr string, +) (uint64, error) { + vtxos, err := getVtxos(ctx, client, addr) + if err != nil { + return 0, err + } var balance uint64 for _, vtxo := range vtxos { balance += vtxo.amount } - return balance + return balance, nil } -func getNetwork() common.Network { +func getOnchainBalance(addr string) (uint64, error) { + _, net, err := getNetwork() + if err != nil { + return 0, err + } + + baseUrl := explorerUrl[net.Name] + resp, err := http.Get(fmt.Sprintf("%s/address/%s/utxo", baseUrl, addr)) + if err != nil { + return 0, err + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + return 0, err + } + if resp.StatusCode != http.StatusOK { + return 0, fmt.Errorf(string(body)) + } + payload := []interface{}{} + if err := json.Unmarshal(body, &payload); err != nil { + return 0, err + } + balance := uint64(0) + for _, p := range payload { + utxo := p.(map[string]interface{}) + asset, ok := utxo["asset"].(string) + if !ok || asset != net.AssetID { + continue + } + balance += uint64(utxo["value"].(float64)) + + } + return balance, nil +} + +func getNetwork() (*common.Network, *network.Network, error) { state, err := getState() if err != nil { - return common.MainNet + return nil, nil, err } - network, ok := state["network"] + net, ok := state["network"] if !ok { - return common.MainNet + return &common.MainNet, &network.Liquid, nil } - if network == "testnet" { - return common.TestNet + if net == "testnet" { + return &common.TestNet, &network.Testnet, nil } - return common.MainNet + return &common.MainNet, &network.Liquid, nil } -func getAddress() (string, error) { +func getAddress() (offchainAddr, onchainAddr string, err error) { publicKey, err := getWalletPublicKey() if err != nil { - return "", err + return } aspPublicKey, err := getServiceProviderPublicKey() if err != nil { - return "", err + return } - net := getNetwork() - - addr, err := common.EncodeAddress(net.Addr, publicKey, aspPublicKey) + arkNet, liquidNet, err := getNetwork() if err != nil { - return "", err + return } - return addr, nil + arkAddr, err := common.EncodeAddress(arkNet.Addr, publicKey, aspPublicKey) + if err != nil { + return + } + + p2wpkh := payment.FromPublicKey(publicKey, liquidNet, nil) + liquidAddr, err := p2wpkh.WitnessPubKeyHash() + if err != nil { + return + } + + offchainAddr = arkAddr + onchainAddr = liquidAddr + + return } func printJSON(resp interface{}) error { diff --git a/noah/config.go b/noah/config.go index e12ed06..a7cb83b 100644 --- a/noah/config.go +++ b/noah/config.go @@ -1,33 +1,13 @@ package main import ( - "fmt" - - arkv1 "github.com/ark-network/ark/api-spec/protobuf/gen/ark/v1" "github.com/urfave/cli/v2" ) -var networkFlag = cli.StringFlag{ - Name: "network", - Usage: "network to use (mainnet, testnet)", - Value: "mainnet", - Required: false, -} - var configCommand = cli.Command{ Name: "config", Usage: "Print local configuration of the Noah CLI", Action: printConfigAction, - Subcommands: []*cli.Command{ - { - Name: "connect", - Usage: "connect [--network ]", - Action: connectAction, - Flags: []cli.Flag{ - &networkFlag, - }, - }, - }, } func printConfigAction(ctx *cli.Context) error { @@ -38,50 +18,3 @@ func printConfigAction(ctx *cli.Context) error { return printJSON(state) } - -func connectAction(ctx *cli.Context) error { - if ctx.NArg() != 1 { - return fmt.Errorf("missing ark URL") - } - - url := ctx.Args().First() - network := ctx.String("network") - - if network != "mainnet" && network != "testnet" { - return fmt.Errorf("invalid network: %s", network) - } - - updateState := map[string]string{ - "ark_url": url, - "network": network, - } - - if err := setState(updateState); err != nil { - return err - } - - client, close, err := getArkClient(ctx) - if err != nil { - return err - } - defer close() - - resp, err := client.GetPubkey(ctx.Context, &arkv1.GetPubkeyRequest{}) - if err != nil { - return err - } - - updateState = map[string]string{ - "ark_pubkey": resp.Pubkey, - } - - if err := setState(updateState); err != nil { - return err - } - - return printJSON(map[string]string{ - "ark_url": url, - "ark_pubkey": resp.Pubkey, - "network": network, - }) -} diff --git a/noah/faucet.go b/noah/faucet.go index 50193ae..2e3ff0a 100644 --- a/noah/faucet.go +++ b/noah/faucet.go @@ -16,12 +16,12 @@ var faucetCommand = cli.Command{ } func faucetAction(ctx *cli.Context) error { - addr, err := getAddress() + addr, _, err := getAddress() if err != nil { return err } - client, close, err := getArkClient(ctx) + client, close, err := getClientFromState(ctx) if err != nil { return err } @@ -62,7 +62,7 @@ func faucetAction(ctx *cli.Context) error { if event.GetRoundFinalized() != nil { return printJSON(map[string]interface{}{ - "poolTxId": event.GetRoundFinalized().GetPoolTxid(), + "pool_txid": event.GetRoundFinalized().GetPoolTxid(), }) } } diff --git a/noah/init.go b/noah/init.go index c99caec..9283b76 100644 --- a/noah/init.go +++ b/noah/init.go @@ -3,7 +3,9 @@ package main import ( "encoding/hex" "fmt" + "strings" + arkv1 "github.com/ark-network/ark/api-spec/protobuf/gen/ark/v1" "github.com/ark-network/ark/common" "github.com/btcsuite/btcd/btcec/v2" "github.com/decred/dcrd/dcrec/secp256k1/v4" @@ -14,46 +16,91 @@ var ( passwordFlag = cli.StringFlag{ Name: "password", Usage: "password to encrypt private key", - Value: "", Required: true, } privateKeyFlag = cli.StringFlag{ - Name: "prvkey", - Usage: "optional, private key to encrypt", - Value: "", - Required: false, + Name: "prvkey", + Usage: "optional, private key to encrypt", + } + networkFlag = cli.StringFlag{ + Name: "network", + Usage: "network to use (mainnet, testnet)", + Value: "testnet", + } + urlFlag = cli.StringFlag{ + Name: "ark-url", + Usage: "the url of the ASP to connect to", + Required: true, } ) var initCommand = cli.Command{ Name: "init", - Usage: "Initialize Noah wallet private key, encrypted with password", + Usage: "initialize the wallet with an encryption password, and connect it to an ASP", Action: initAction, - Flags: []cli.Flag{ - &passwordFlag, - &privateKeyFlag, - }, + Flags: []cli.Flag{&passwordFlag, &privateKeyFlag, &networkFlag, &urlFlag}, } func initAction(ctx *cli.Context) error { - privateKeyString := ctx.String("prvkey") + key := ctx.String("prvkey") password := ctx.String("password") + net := strings.ToLower(ctx.String("network")) + url := ctx.String("ark-url") if len(password) <= 0 { - return fmt.Errorf("missing password flag (--password)") + return fmt.Errorf("invalid password") + } + if len(url) <= 0 { + return fmt.Errorf("invalid ark url") + } + if net != "mainnet" && net != "testnet" { + return fmt.Errorf("invalid network") } - var privateKey *secp256k1.PrivateKey + if err := connectToAsp(ctx, net, url); err != nil { + return err + } + return initWallet(ctx, key, password) +} - if len(privateKeyString) <= 0 { +func generateRandomPrivateKey() (*secp256k1.PrivateKey, error) { + privKey, err := btcec.NewPrivateKey() + if err != nil { + return nil, err + } + return privKey, nil +} + +func connectToAsp(ctx *cli.Context, net, url string) error { + client, close, err := getClient(ctx, url) + if err != nil { + return err + } + defer close() + + resp, err := client.GetPubkey(ctx.Context, &arkv1.GetPubkeyRequest{}) + if err != nil { + return err + } + + return setState(map[string]string{ + "ark_url": url, + "network": net, + "ark_pubkey": resp.Pubkey, + }) +} + +func initWallet(ctx *cli.Context, key, password string) error { + var privateKey *secp256k1.PrivateKey + if len(key) <= 0 { privKey, err := generateRandomPrivateKey() if err != nil { return err } privateKey = privKey } else { - privKeyBytes, err := hex.DecodeString(privateKeyString) + privKeyBytes, err := hex.DecodeString(key) if err != nil { return err } @@ -63,9 +110,12 @@ func initAction(ctx *cli.Context) error { cypher := NewAES128Cypher() - net := getNetwork() + arkNetwork, _, err := getNetwork() + if err != nil { + return err + } - publicKey, err := common.EncodePubKey(net.PubKey, privateKey.PubKey()) + publicKey, err := common.EncodePubKey(arkNetwork.PubKey, privateKey.PubKey()) if err != nil { return err } @@ -83,17 +133,5 @@ func initAction(ctx *cli.Context) error { "public_key": publicKey, } - if err := setState(state); err != nil { - return err - } - - return nil -} - -func generateRandomPrivateKey() (*secp256k1.PrivateKey, error) { - privKey, err := btcec.NewPrivateKey() - if err != nil { - return nil, err - } - return privKey, nil + return setState(state) } diff --git a/noah/main.go b/noah/main.go index 999703d..0432c8e 100644 --- a/noah/main.go +++ b/noah/main.go @@ -10,12 +10,14 @@ import ( "github.com/ark-network/ark/common" "github.com/urfave/cli/v2" + "github.com/vulpemventures/go-elements/network" ) const ( DATADIR_ENVVAR = "NOAH_DATADIR" STATE_FILE = "state.json" - defaultArkURL = "ark://apub1qgvdtj5ttpuhkldavhq8thtm5auyk0ec4dcmrfdgu0u5hgp9we22v3hrs4x?relays=arelay1qt6f8p7h5f6tm7fv2z5wg92sz92rn9desfhd5733se4lkrptqtdrq65987l-arelay1qt6f8p7h5f6tm7fv2z5wg92sz92rn9desfhd5733se4lkrptqtdrq65987l" + defaultArkURL = "localhost:6000" + defaultNetwork = "testnet" ) var ( @@ -23,6 +25,10 @@ var ( noahDataDirectory = common.AppDataDir("noah", false) statePath = filepath.Join(noahDataDirectory, STATE_FILE) + explorerUrl = map[string]string{ + network.Liquid.Name: "https://blockstream.info/liquid/api", + network.Testnet.Name: "https://blockstream.info/liquidtestnet/api", + } initialState = map[string]string{ "ark_url": defaultArkURL, @@ -30,7 +36,7 @@ var ( "encrypted_private_key": "", "password_hash": "", "public_key": "", - "network": "mainnet", + "network": defaultNetwork, } ) diff --git a/noah/receive.go b/noah/receive.go index f46b63c..8ddd1c0 100644 --- a/noah/receive.go +++ b/noah/receive.go @@ -11,12 +11,19 @@ var receiveCommand = cli.Command{ } func receiveAction(ctx *cli.Context) error { - addr, err := getAddress() + offchainAddr, onchainAddr, err := getAddress() if err != nil { return err } + state, err := getState() + if err != nil { + return err + } + relays := []string{state["ark_url"]} return printJSON(map[string]interface{}{ - "address": addr, + "offchain_address": offchainAddr, + "onchain_address": onchainAddr, + "relays": relays, }) } diff --git a/noah/redeem.go b/noah/redeem.go index 229a4eb..7036471 100644 --- a/noah/redeem.go +++ b/noah/redeem.go @@ -2,8 +2,13 @@ package main import ( "fmt" + "io" + arkv1 "github.com/ark-network/ark/api-spec/protobuf/gen/ark/v1" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/urfave/cli/v2" + "github.com/vulpemventures/go-elements/address" + "github.com/vulpemventures/go-elements/psetv2" ) var ( @@ -37,27 +42,176 @@ var redeemCommand = cli.Command{ } func redeemAction(ctx *cli.Context) error { - address := ctx.String("address") + addr := ctx.String("address") amount := ctx.Uint64("amount") force := ctx.Bool("force") - if len(address) <= 0 { + if len(addr) <= 0 { return fmt.Errorf("missing address flag (--address)") } + if _, err := address.ToOutputScript(addr); err != nil { + return fmt.Errorf("invalid onchain address") + } + if isConf, _ := address.IsConfidential(addr); isConf { + return fmt.Errorf("invalid onchain address: must be unconfidential") + } + net, err := address.NetworkForAddress(addr) + if err != nil { + return fmt.Errorf("invalid onchain address: unknown network") + } + _, liquidNet, _ := getNetwork() + if net.Name != liquidNet.Name { + return fmt.Errorf("invalid onchain address: must be for %s network", liquidNet.Name) + } if !force && amount <= 0 { return fmt.Errorf("missing amount flag (--amount)") } if force { - return unilateralRedeem(address) + return unilateralRedeem(addr) } - return collaborativeRedeem(address, amount) + return collaborativeRedeem(ctx, addr, amount) } -func collaborativeRedeem(address string, amount uint64) error { - fmt.Println("collaborative redeem is not implemented yet") +func collaborativeRedeem(ctx *cli.Context, address string, amount uint64) error { + offchainAddr, _, err := getAddress() + if err != nil { + return err + } + + receivers := []*arkv1.Output{ + { + Address: address, + Amount: amount, + }, + } + + client, close, err := getClientFromState(ctx) + if err != nil { + return err + } + defer close() + + vtxos, err := getVtxos(ctx, client, offchainAddr) + if err != nil { + return err + } + + selectedCoins, changeAmount, err := coinSelect(vtxos, amount) + if err != nil { + return err + } + + if changeAmount > 0 { + receivers = append(receivers, &arkv1.Output{ + Address: offchainAddr, + Amount: changeAmount, + }) + } + + inputs := make([]*arkv1.Input, 0, len(selectedCoins)) + + for _, coin := range selectedCoins { + inputs = append(inputs, &arkv1.Input{ + Txid: coin.txid, + Vout: coin.vout, + }) + } + + registerResponse, err := client.RegisterPayment(ctx.Context, &arkv1.RegisterPaymentRequest{ + Inputs: inputs, + }) + if err != nil { + return err + } + + _, err = client.ClaimPayment(ctx.Context, &arkv1.ClaimPaymentRequest{ + Id: registerResponse.GetId(), + Outputs: receivers, + }) + if err != nil { + return err + } + + stream, err := client.GetEventStream(ctx.Context, &arkv1.GetEventStreamRequest{}) + if err != nil { + return err + } + + var pingStop func() + pingReq := &arkv1.PingRequest{ + PaymentId: registerResponse.GetId(), + } + for pingStop == nil { + pingStop = ping(ctx, client, pingReq) + } + + for { + event, err := stream.Recv() + if err == io.EOF { + break + } + if err != nil { + return err + } + + if event.GetRoundFailed() != nil { + return fmt.Errorf("round failed: %s", event.GetRoundFailed().GetReason()) + } + + if event.GetRoundFinalization() != nil { + // stop pinging as soon as we receive some forfeit txs + pingStop() + forfeits := event.GetRoundFinalization().GetForfeitTxs() + signedForfeits := make([]string, 0) + + for _, forfeit := range forfeits { + pset, err := psetv2.NewPsetFromBase64(forfeit) + if err != nil { + return err + } + + // check if it contains one of the input to sign + for _, input := range pset.Inputs { + inputTxid := chainhash.Hash(input.PreviousTxid).String() + + for _, coin := range selectedCoins { + if inputTxid == coin.txid { + // TODO: sign the vtxo input + signedForfeits = append(signedForfeits, forfeit) + } + } + } + } + + // if no forfeit txs have been signed, start pinging again and wait for the next round + if len(signedForfeits) == 0 { + pingStop = nil + for pingStop == nil { + pingStop = ping(ctx, client, pingReq) + } + continue + } + + _, err := client.FinalizePayment(ctx.Context, &arkv1.FinalizePaymentRequest{ + SignedForfeitTxs: signedForfeits, + }) + if err != nil { + return err + } + + continue + } + + if event.GetRoundFinalized() != nil { + return printJSON(map[string]interface{}{ + "pool_txid": event.GetRoundFinalized().GetPoolTxid(), + }) + } + } + return nil } diff --git a/noah/send.go b/noah/send.go index 8a6a568..f831d71 100644 --- a/noah/send.go +++ b/noah/send.go @@ -2,7 +2,6 @@ package main import ( "bytes" - "encoding/hex" "encoding/json" "fmt" "io" @@ -49,7 +48,12 @@ func sendAction(ctx *cli.Context) error { return fmt.Errorf("no receivers specified") } - aspPubKey, err := getServiceProviderPublicKey() + offchainAddr, _, err := getAddress() + if err != nil { + return err + } + + _, _, aspPubKey, err := common.DecodeAddress(offchainAddr) if err != nil { return err } @@ -58,7 +62,7 @@ func sendAction(ctx *cli.Context) error { sumOfReceivers := uint64(0) for _, receiver := range receiversJSON { - _, userKey, aspKey, err := common.DecodeAddress(receiver.To) + _, _, aspKey, err := common.DecodeAddress(receiver.To) if err != nil { return fmt.Errorf("invalid receiver address: %s", err) } @@ -71,20 +75,19 @@ func sendAction(ctx *cli.Context) error { return fmt.Errorf("invalid amount: %d", receiver.Amount) } - encodedKey := hex.EncodeToString(userKey.SerializeCompressed()) receiversOutput = append(receiversOutput, &arkv1.Output{ - Pubkey: encodedKey, - Amount: uint64(receiver.Amount), + Address: receiver.To, + Amount: uint64(receiver.Amount), }) sumOfReceivers += receiver.Amount } - client, close, err := getArkClient(ctx) + client, close, err := getClientFromState(ctx) if err != nil { return err } defer close() - vtxos, err := getVtxos(ctx, client) + vtxos, err := getVtxos(ctx, client, offchainAddr) if err != nil { return err } @@ -95,17 +98,9 @@ func sendAction(ctx *cli.Context) error { } if changeAmount > 0 { - walletPrvKey, err := privateKeyFromPassword() - if err != nil { - return err - } - - walletPubKey := walletPrvKey.PubKey() - encodedPubKey := hex.EncodeToString(walletPubKey.SerializeCompressed()) - changeReceiver := &arkv1.Output{ - Pubkey: encodedPubKey, - Amount: changeAmount, + Address: offchainAddr, + Amount: changeAmount, } receiversOutput = append(receiversOutput, changeReceiver) } @@ -139,9 +134,13 @@ func sendAction(ctx *cli.Context) error { return err } - pingStop := ping(ctx, client, &arkv1.PingRequest{ + var pingStop func() + pingReq := &arkv1.PingRequest{ PaymentId: registerResponse.GetId(), - }) + } + for pingStop == nil { + pingStop = ping(ctx, client, pingReq) + } for { event, err := stream.Recv() @@ -157,6 +156,7 @@ func sendAction(ctx *cli.Context) error { } if event.GetRoundFinalization() != nil { + // stop pinging as soon as we receive some forfeit txs pingStop() forfeits := event.GetRoundFinalization().GetForfeitTxs() signedForfeits := make([]string, 0) @@ -180,7 +180,12 @@ func sendAction(ctx *cli.Context) error { } } + // if no forfeit txs have been signed, start pinging again and wait for the next round if len(signedForfeits) == 0 { + pingStop = nil + for pingStop == nil { + pingStop = ping(ctx, client, pingReq) + } continue } @@ -196,8 +201,7 @@ func sendAction(ctx *cli.Context) error { if event.GetRoundFinalized() != nil { return printJSON(map[string]interface{}{ - "paymentId": registerResponse.GetId(), - "poolTxId": event.GetRoundFinalized().GetPoolTxid(), + "pool_txid": event.GetRoundFinalized().GetPoolTxid(), }) } } @@ -208,14 +212,16 @@ func sendAction(ctx *cli.Context) error { // send 1 ping message every 5 seconds to signal to the ark service that we are still alive // returns a function that can be used to stop the pinging func ping(ctx *cli.Context, client arkv1.ArkServiceClient, req *arkv1.PingRequest) func() { + _, err := client.Ping(ctx.Context, req) + if err != nil { + return nil + } + ticker := time.NewTicker(5 * time.Second) go func(t *time.Ticker) { for range t.C { - _, err := client.Ping(ctx.Context, req) - if err != nil { - return - } + client.Ping(ctx.Context, req) } }(ticker)