mirror of
https://github.com/aljazceru/ark.git
synced 2025-12-17 04:04:21 +01:00
Vars and fields renaming (#387)
* Rename asp > server * Rename pool > round * Consolidate naming for pubkey/prvkey vars and types * Fix * Fix * Fix wasm * Rename congestionTree > vtxoTree * Fix wasm * Rename payment > request * Rename congestionTree > vtxoTree after syncing with master * Fix Send API in SDK * Fix wasm * Fix wasm * Fixes * Fixes after review * Fix * Fix naming * Fix * Fix e2e tests
This commit is contained in:
committed by
GitHub
parent
12d666bfdf
commit
7f937e8418
@@ -32,10 +32,10 @@ For a quick-start with Docker, head over to our [Quick Start guide](https://arkd
|
||||
## Repository Structure
|
||||
|
||||
- [`api-spec`](./api-spec/): Ark Protocol Buffer API specification
|
||||
- [`client`](./client/): `ark` Single-key wallet CLI for interacting with the ASP
|
||||
- [`client`](./client/): `ark` Single-key wallet CLI for interacting with the server
|
||||
- [`common`](./common/): Shared code between the server and client
|
||||
- [`pkg/client-sdk`](./pkg/client-sdk/): Go SDK for interacting with ASPs running the Ark protocol. It offers WASM bindings to interact with the SDK from the browser and other environments.
|
||||
- [`server`](./server/): `arkd` Ark Service Provider (ASP) - the always-on daemon
|
||||
- [`pkg/client-sdk`](./pkg/client-sdk/): Go SDK for interacting with servers running the Ark protocol. It offers WASM bindings to interact with the SDK from the browser and other environments.
|
||||
- [`server`](./server/): `arkd` Ark server - the always-on daemon
|
||||
|
||||
## Development
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/round/ping/{paymentId}": {
|
||||
"/v1/round/ping/{requestId}": {
|
||||
"get": {
|
||||
"operationId": "ArkService_Ping",
|
||||
"responses": {
|
||||
@@ -182,7 +182,8 @@
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "paymentId",
|
||||
"name": "requestId",
|
||||
"description": "The id used to register inputs and ouptuts.",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
@@ -770,7 +771,7 @@
|
||||
"title": "VTXO outpoint signed with script's secret key"
|
||||
}
|
||||
},
|
||||
"description": "This message is used to prove to the ASP that the user controls the vtxo without revealing the whole VTXO taproot tree."
|
||||
"description": "This message is used to prove to the server that the user controls the vtxo without revealing the whole VTXO taproot tree."
|
||||
},
|
||||
"v1PingResponse": {
|
||||
"type": "object"
|
||||
@@ -821,18 +822,16 @@
|
||||
"v1RegisterInputsForNextRoundResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Mocks wabisabi's blinded credentials."
|
||||
"requestId": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"v1RegisterOutputsForNextRoundRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Mocks wabisabi's blinded credentials."
|
||||
"requestId": {
|
||||
"type": "string"
|
||||
},
|
||||
"outputs": {
|
||||
"type": "array",
|
||||
@@ -840,7 +839,7 @@
|
||||
"type": "object",
|
||||
"$ref": "#/definitions/v1Output"
|
||||
},
|
||||
"description": "List of receivers for a registered payment."
|
||||
"description": "List of receivers for to convert to leaves in the next VTXO tree."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1058,7 +1057,7 @@
|
||||
},
|
||||
"signedRoundTx": {
|
||||
"type": "string",
|
||||
"description": "If payment has boarding input, the user must sign the associated inputs."
|
||||
"description": "The user has to sign also the round tx if he registerd a boarding UTXO."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -19,7 +19,7 @@ service ArkService {
|
||||
};
|
||||
};
|
||||
|
||||
/* In-Round Payment APIs */
|
||||
/* In-Round Transaction APIs */
|
||||
|
||||
rpc RegisterInputsForNextRound(RegisterInputsForNextRoundRequest) returns (RegisterInputsForNextRoundResponse) {
|
||||
option (google.api.http) = {
|
||||
@@ -58,10 +58,12 @@ service ArkService {
|
||||
};
|
||||
rpc Ping(PingRequest) returns (PingResponse) {
|
||||
option (google.api.http) = {
|
||||
get: "/v1/round/ping/{payment_id}"
|
||||
get: "/v1/round/ping/{request_id}"
|
||||
};
|
||||
};
|
||||
|
||||
/* Out-of-Round Transaction APIs */
|
||||
|
||||
rpc SubmitRedeemTx(SubmitRedeemTxRequest) returns (SubmitRedeemTxResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/v1/redeem-tx"
|
||||
@@ -134,7 +136,7 @@ message GetBoardingAddressResponse {
|
||||
}
|
||||
}
|
||||
|
||||
/* In-Round Payment API messages */
|
||||
/* In-Round Transaction API messages */
|
||||
|
||||
message RegisterInputsForNextRoundRequest {
|
||||
repeated Input inputs = 1;
|
||||
@@ -142,14 +144,12 @@ message RegisterInputsForNextRoundRequest {
|
||||
repeated string notes = 3;
|
||||
}
|
||||
message RegisterInputsForNextRoundResponse {
|
||||
// Mocks wabisabi's blinded credentials.
|
||||
string id = 1;
|
||||
string request_id = 1;
|
||||
}
|
||||
|
||||
message RegisterOutputsForNextRoundRequest {
|
||||
// Mocks wabisabi's blinded credentials.
|
||||
string id = 1;
|
||||
// List of receivers for a registered payment.
|
||||
string request_id = 1;
|
||||
// List of receivers for to convert to leaves in the next VTXO tree.
|
||||
repeated Output outputs = 2;
|
||||
}
|
||||
message RegisterOutputsForNextRoundResponse {}
|
||||
@@ -171,7 +171,7 @@ message SubmitTreeSignaturesResponse {}
|
||||
message SubmitSignedForfeitTxsRequest {
|
||||
// Forfeit txs signed by the user.
|
||||
repeated string signed_forfeit_txs = 1;
|
||||
// If payment has boarding input, the user must sign the associated inputs.
|
||||
// The user has to sign also the round tx if he registerd a boarding UTXO.
|
||||
optional string signed_round_tx = 2;
|
||||
}
|
||||
message SubmitSignedForfeitTxsResponse {}
|
||||
@@ -188,7 +188,8 @@ message GetEventStreamResponse {
|
||||
}
|
||||
|
||||
message PingRequest {
|
||||
string payment_id = 1;
|
||||
// The id used to register inputs and ouptuts.
|
||||
string request_id = 1;
|
||||
}
|
||||
message PingResponse {}
|
||||
|
||||
@@ -343,7 +344,7 @@ message RedeemTransaction {
|
||||
repeated Vtxo spendable_vtxos = 3;
|
||||
}
|
||||
|
||||
// This message is used to prove to the ASP that the user controls the vtxo without revealing the whole VTXO taproot tree.
|
||||
// This message is used to prove to the server that the user controls the vtxo without revealing the whole VTXO taproot tree.
|
||||
message OwnershipProof {
|
||||
string control_block = 1;
|
||||
string script = 2;
|
||||
|
||||
@@ -439,8 +439,7 @@ type RegisterInputsForNextRoundResponse struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Mocks wabisabi's blinded credentials.
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RegisterInputsForNextRoundResponse) Reset() {
|
||||
@@ -475,9 +474,9 @@ func (*RegisterInputsForNextRoundResponse) Descriptor() ([]byte, []int) {
|
||||
return file_ark_v1_service_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *RegisterInputsForNextRoundResponse) GetId() string {
|
||||
func (x *RegisterInputsForNextRoundResponse) GetRequestId() string {
|
||||
if x != nil {
|
||||
return x.Id
|
||||
return x.RequestId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -487,9 +486,8 @@ type RegisterOutputsForNextRoundRequest struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Mocks wabisabi's blinded credentials.
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
// List of receivers for a registered payment.
|
||||
RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"`
|
||||
// List of receivers for to convert to leaves in the next VTXO tree.
|
||||
Outputs []*Output `protobuf:"bytes,2,rep,name=outputs,proto3" json:"outputs,omitempty"`
|
||||
}
|
||||
|
||||
@@ -525,9 +523,9 @@ func (*RegisterOutputsForNextRoundRequest) Descriptor() ([]byte, []int) {
|
||||
return file_ark_v1_service_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *RegisterOutputsForNextRoundRequest) GetId() string {
|
||||
func (x *RegisterOutputsForNextRoundRequest) GetRequestId() string {
|
||||
if x != nil {
|
||||
return x.Id
|
||||
return x.RequestId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -786,7 +784,7 @@ type SubmitSignedForfeitTxsRequest struct {
|
||||
|
||||
// Forfeit txs signed by the user.
|
||||
SignedForfeitTxs []string `protobuf:"bytes,1,rep,name=signed_forfeit_txs,json=signedForfeitTxs,proto3" json:"signed_forfeit_txs,omitempty"`
|
||||
// If payment has boarding input, the user must sign the associated inputs.
|
||||
// The user has to sign also the round tx if he registerd a boarding UTXO.
|
||||
SignedRoundTx *string `protobuf:"bytes,2,opt,name=signed_round_tx,json=signedRoundTx,proto3,oneof" json:"signed_round_tx,omitempty"`
|
||||
}
|
||||
|
||||
@@ -1040,7 +1038,8 @@ type PingRequest struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
PaymentId string `protobuf:"bytes,1,opt,name=payment_id,json=paymentId,proto3" json:"payment_id,omitempty"`
|
||||
// The id used to register inputs and ouptuts.
|
||||
RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"`
|
||||
}
|
||||
|
||||
func (x *PingRequest) Reset() {
|
||||
@@ -1075,9 +1074,9 @@ func (*PingRequest) Descriptor() ([]byte, []int) {
|
||||
return file_ark_v1_service_proto_rawDescGZIP(), []int{16}
|
||||
}
|
||||
|
||||
func (x *PingRequest) GetPaymentId() string {
|
||||
func (x *PingRequest) GetRequestId() string {
|
||||
if x != nil {
|
||||
return x.PaymentId
|
||||
return x.RequestId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -2658,7 +2657,7 @@ func (x *RedeemTransaction) GetSpendableVtxos() []*Vtxo {
|
||||
return nil
|
||||
}
|
||||
|
||||
// This message is used to prove to the ASP that the user controls the vtxo without revealing the whole VTXO taproot tree.
|
||||
// This message is used to prove to the server that the user controls the vtxo without revealing the whole VTXO taproot tree.
|
||||
type OwnershipProof struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -3136,433 +3135,435 @@ var file_ark_v1_service_proto_rawDesc = []byte{
|
||||
0x6c, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f,
|
||||
0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x6f, 0x74, 0x65, 0x73,
|
||||
0x42, 0x13, 0x0a, 0x11, 0x5f, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c, 0x5f, 0x70,
|
||||
0x75, 0x62, 0x6b, 0x65, 0x79, 0x22, 0x34, 0x0a, 0x22, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
|
||||
0x75, 0x62, 0x6b, 0x65, 0x79, 0x22, 0x43, 0x0a, 0x22, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
|
||||
0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69,
|
||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x5e, 0x0a, 0x22, 0x52,
|
||||
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f,
|
||||
0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69,
|
||||
0x64, 0x12, 0x28, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03,
|
||||
0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70,
|
||||
0x75, 0x74, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x22, 0x25, 0x0a, 0x23, 0x52,
|
||||
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f,
|
||||
0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x22, 0x6d, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65,
|
||||
0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a,
|
||||
0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b,
|
||||
0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79,
|
||||
0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65,
|
||||
0x73, 0x22, 0x1a, 0x0a, 0x18, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e,
|
||||
0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x79, 0x0a,
|
||||
0x1b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61,
|
||||
0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08,
|
||||
0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
|
||||
0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65,
|
||||
0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12,
|
||||
0x27, 0x0a, 0x0f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72,
|
||||
0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x72, 0x65, 0x65, 0x53, 0x69,
|
||||
0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0x1e, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x6d,
|
||||
0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x8e, 0x01, 0x0a, 0x1d, 0x53, 0x75, 0x62,
|
||||
0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74,
|
||||
0x54, 0x78, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x69,
|
||||
0x67, 0x6e, 0x65, 0x64, 0x5f, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x5f, 0x74, 0x78, 0x73,
|
||||
0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f,
|
||||
0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x2b, 0x0a, 0x0f, 0x73, 0x69, 0x67, 0x6e,
|
||||
0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x09, 0x48, 0x00, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x6e, 0x64,
|
||||
0x54, 0x78, 0x88, 0x01, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64,
|
||||
0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x22, 0x20, 0x0a, 0x1e, 0x53, 0x75, 0x62,
|
||||
0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74,
|
||||
0x54, 0x78, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 0xa7, 0x03, 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, 0x12, 0x40, 0x0a, 0x0d, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x69, 0x67, 0x6e,
|
||||
0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x45,
|
||||
0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67,
|
||||
0x6e, 0x69, 0x6e, 0x67, 0x12, 0x6f, 0x0a, 0x1e, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x69,
|
||||
0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x5f, 0x67, 0x65, 0x6e,
|
||||
0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61,
|
||||
0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69,
|
||||
0x6e, 0x67, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65,
|
||||
0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1b, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x53,
|
||||
0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47, 0x65, 0x6e, 0x65,
|
||||
0x72, 0x61, 0x74, 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, 0x34, 0x0a, 0x15,
|
||||
0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x5f,
|
||||
0x74, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d,
|
||||
0x54, 0x78, 0x22, 0x42, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65,
|
||||
0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x10,
|
||||
0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x5f, 0x74, 0x78,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, 0x65,
|
||||
0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x22, 0x25, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75,
|
||||
0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69,
|
||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x22, 0x37, 0x0a,
|
||||
0x10, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x12, 0x23, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x0d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52,
|
||||
0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x25, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75,
|
||||
0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a,
|
||||
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x3b, 0x0a,
|
||||
0x14, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 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, 0x79, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74,
|
||||
0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a,
|
||||
0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 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, 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x56,
|
||||
0x74, 0x78, 0x6f, 0x73, 0x12, 0x2d, 0x0a, 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x74,
|
||||
0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, 0x74,
|
||||
0x78, 0x6f, 0x73, 0x22, 0xbb, 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, 0x19,
|
||||
0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x12, 0x29, 0x0a, 0x09, 0x76, 0x74, 0x78,
|
||||
0x6f, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61,
|
||||
0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, 0x08, 0x76, 0x74, 0x78, 0x6f,
|
||||
0x54, 0x72, 0x65, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f,
|
||||
0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
|
||||
0x74, 0x6f, 0x72, 0x73, 0x12, 0x2b, 0x0a, 0x12, 0x6d, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x6c, 0x61,
|
||||
0x79, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03,
|
||||
0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x65, 0x65, 0x52, 0x61, 0x74,
|
||||
0x65, 0x22, 0x44, 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, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x6e,
|
||||
0x64, 0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x6f,
|
||||
0x75, 0x6e, 0x64, 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, 0xb8,
|
||||
0x01, 0x0a, 0x11, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x45,
|
||||
0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x02, 0x69, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x6f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72,
|
||||
0x73, 0x5f, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52,
|
||||
0x10, 0x63, 0x6f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79,
|
||||
0x73, 0x12, 0x3a, 0x0a, 0x12, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x76, 0x74,
|
||||
0x78, 0x6f, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e,
|
||||
0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, 0x10, 0x75, 0x6e, 0x73,
|
||||
0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x54, 0x72, 0x65, 0x65, 0x12, 0x2a, 0x0a,
|
||||
0x11, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f,
|
||||
0x74, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e,
|
||||
0x65, 0x64, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x22, 0x53, 0x0a, 0x20, 0x52, 0x6f, 0x75,
|
||||
0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47,
|
||||
0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a,
|
||||
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1f, 0x0a,
|
||||
0x0b, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x0a, 0x74, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x22, 0xf0,
|
||||
0x01, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72,
|
||||
0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10,
|
||||
0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64,
|
||||
0x12, 0x19, 0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x04, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x12, 0x29, 0x0a, 0x09, 0x76,
|
||||
0x74, 0x78, 0x6f, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c,
|
||||
0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, 0x08, 0x76, 0x74,
|
||||
0x78, 0x6f, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69,
|
||||
0x74, 0x5f, 0x74, 0x78, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x6f, 0x72,
|
||||
0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
|
||||
0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e,
|
||||
0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x28, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65,
|
||||
0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67,
|
||||
0x65, 0x22, 0x32, 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 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, 0x9d, 0x01, 0x0a, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12,
|
||||
0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f,
|
||||
0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x20, 0x0a,
|
||||
0x0a, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x09, 0x48, 0x00, 0x52, 0x0a, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12,
|
||||
0x34, 0x0a, 0x0a, 0x74, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x70,
|
||||
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x48, 0x00, 0x52, 0x0a, 0x74, 0x61, 0x70, 0x73, 0x63,
|
||||
0x72, 0x69, 0x70, 0x74, 0x73, 0x42, 0x0e, 0x0a, 0x0c, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74,
|
||||
0x5f, 0x74, 0x72, 0x65, 0x65, 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, 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, 0xc2, 0x02, 0x0a, 0x04, 0x56, 0x74, 0x78, 0x6f, 0x12, 0x2c, 0x0a, 0x08, 0x6f,
|
||||
0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e,
|
||||
0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52,
|
||||
0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x70, 0x65,
|
||||
0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x12,
|
||||
0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x69, 0x64, 0x12, 0x19,
|
||||
0x0a, 0x08, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x07, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x65, 0x78, 0x70,
|
||||
0x69, 0x72, 0x65, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x65, 0x78,
|
||||
0x70, 0x69, 0x72, 0x65, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x77, 0x65, 0x70, 0x74, 0x18,
|
||||
0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x77, 0x65, 0x70, 0x74, 0x12, 0x1d, 0x0a, 0x0a,
|
||||
0x69, 0x73, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08,
|
||||
0x52, 0x09, 0x69, 0x73, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x72,
|
||||
0x65, 0x64, 0x65, 0x65, 0x6d, 0x5f, 0x74, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
|
||||
0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61,
|
||||
0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72,
|
||||
0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x1e, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x54, 0x72,
|
||||
0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8c, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x54,
|
||||
0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61,
|
||||
0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x72, 0x6f, 0x75,
|
||||
0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x48, 0x00, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x33, 0x0a, 0x06, 0x72,
|
||||
0x65, 0x64, 0x65, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x72,
|
||||
0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73,
|
||||
0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d,
|
||||
0x42, 0x04, 0x0a, 0x02, 0x74, 0x78, 0x22, 0xd8, 0x01, 0x0a, 0x10, 0x52, 0x6f, 0x75, 0x6e, 0x64,
|
||||
0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74,
|
||||
0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12,
|
||||
0x31, 0x0a, 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02,
|
||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75,
|
||||
0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, 0x74, 0x78,
|
||||
0x6f, 0x73, 0x12, 0x35, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f,
|
||||
0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72,
|
||||
0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64,
|
||||
0x61, 0x62, 0x6c, 0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x46, 0x0a, 0x16, 0x63, 0x6c, 0x61,
|
||||
0x69, 0x6d, 0x65, 0x64, 0x5f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x74,
|
||||
0x78, 0x6f, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x14, 0x63, 0x6c, 0x61,
|
||||
0x69, 0x6d, 0x65, 0x64, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x55, 0x74, 0x78, 0x6f,
|
||||
0x73, 0x22, 0x91, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x72, 0x61, 0x6e,
|
||||
0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x31, 0x0a, 0x0b, 0x73,
|
||||
0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
|
||||
0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69,
|
||||
0x6e, 0x74, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x35,
|
||||
0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x74, 0x78, 0x6f,
|
||||
0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65,
|
||||
0x56, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x6b, 0x0a, 0x0e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68,
|
||||
0x69, 0x70, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x72,
|
||||
0x6f, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c,
|
||||
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x16, 0x0a, 0x06,
|
||||
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63,
|
||||
0x72, 0x69, 0x70, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72,
|
||||
0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75,
|
||||
0x72, 0x65, 0x22, 0x70, 0x0a, 0x12, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f,
|
||||
0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70,
|
||||
0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75,
|
||||
0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f,
|
||||
0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x05, 0x70,
|
||||
0x72, 0x6f, 0x6f, 0x66, 0x22, 0x75, 0x0a, 0x18, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72,
|
||||
0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x12, 0x27, 0x0a, 0x0f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69,
|
||||
0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6e, 0x6f, 0x73, 0x74, 0x72,
|
||||
0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x74, 0x78,
|
||||
0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x4f, 0x75, 0x74, 0x70,
|
||||
0x6f, 0x69, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x1b, 0x0a, 0x19, 0x53,
|
||||
0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, 0x0a, 0x1b, 0x44, 0x65, 0x6c, 0x65,
|
||||
0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73,
|
||||
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69,
|
||||
0x6e, 0x74, 0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x1e, 0x0a, 0x1c, 0x44, 0x65, 0x6c,
|
||||
0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x0a, 0x0a, 0x54, 0x61, 0x70,
|
||||
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x63, 0x72, 0x69, 0x70,
|
||||
0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
|
||||
0x73, 0x22, 0x85, 0x02, 0x0a, 0x0a, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x48, 0x6f, 0x75, 0x72,
|
||||
0x12, 0x42, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74,
|
||||
0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65,
|
||||
0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74,
|
||||
0x54, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x65, 0x6e, 0x64,
|
||||
0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f,
|
||||
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69,
|
||||
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x6e, 0x65, 0x78, 0x74, 0x45, 0x6e, 0x64,
|
||||
0x54, 0x69, 0x6d, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52,
|
||||
0x06, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12, 0x40, 0x0a, 0x0e, 0x72, 0x6f, 0x75, 0x6e, 0x64,
|
||||
0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
|
||||
0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x72, 0x6f, 0x75, 0x6e,
|
||||
0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x2a, 0x98, 0x01, 0x0a, 0x0a, 0x52, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x4f, 0x55, 0x4e,
|
||||
0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46,
|
||||
0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53,
|
||||
0x54, 0x41, 0x47, 0x45, 0x5f, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x52, 0x41, 0x54, 0x49, 0x4f,
|
||||
0x4e, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41,
|
||||
0x47, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10,
|
||||
0x02, 0x12, 0x19, 0x0a, 0x15, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45,
|
||||
0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12,
|
||||
0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c,
|
||||
0x45, 0x44, 0x10, 0x04, 0x32, 0xf0, 0x0e, 0x0a, 0x0a, 0x41, 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16,
|
||||
0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||
0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x66,
|
||||
0x6f, 0x12, 0x74, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67,
|
||||
0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x21, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72,
|
||||
0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x61, 0x72, 0x6b,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41,
|
||||
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17,
|
||||
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x3a, 0x01, 0x2a, 0x22, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x62,
|
||||
0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x98, 0x01, 0x0a, 0x1a, 0x52, 0x65, 0x67, 0x69,
|
||||
0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78,
|
||||
0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x29, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f,
|
||||
0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x1a, 0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73,
|
||||
0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74,
|
||||
0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82,
|
||||
0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75,
|
||||
0x74, 0x73, 0x12, 0x9c, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f,
|
||||
0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75,
|
||||
0x6e, 0x64, 0x12, 0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69,
|
||||
0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65,
|
||||
0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b,
|
||||
0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
|
||||
0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4,
|
||||
0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a, 0x22, 0x19, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e,
|
||||
0x64, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74,
|
||||
0x73, 0x12, 0x7d, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e,
|
||||
0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53,
|
||||
0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20,
|
||||
0x3a, 0x01, 0x2a, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x74,
|
||||
0x72, 0x65, 0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73,
|
||||
0x12, 0x8d, 0x01, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53,
|
||||
0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x23, 0x2e, 0x61, 0x72, 0x6b, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67,
|
||||
0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24,
|
||||
0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72,
|
||||
0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x3a, 0x01, 0x2a, 0x22,
|
||||
0x1f, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f,
|
||||
0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73,
|
||||
0x12, 0x8e, 0x01, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65,
|
||||
0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x25, 0x2e, 0x61, 0x72,
|
||||
0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65,
|
||||
0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x26, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d,
|
||||
0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54,
|
||||
0x78, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93,
|
||||
0x02, 0x1f, 0x3a, 0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64,
|
||||
0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78,
|
||||
0x73, 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,
|
||||
0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, 0x6d, 0x0a, 0x22, 0x52, 0x65,
|
||||
0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72,
|
||||
0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12,
|
||||
0x28, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
|
||||
0x32, 0x0e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74,
|
||||
0x52, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x22, 0x25, 0x0a, 0x23, 0x52, 0x65, 0x67,
|
||||
0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e,
|
||||
0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x22, 0x6d, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f,
|
||||
0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x72,
|
||||
0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72,
|
||||
0x6f, 0x75, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1f,
|
||||
0x0a, 0x0b, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x22,
|
||||
0x1a, 0x0a, 0x18, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e,
|
||||
0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x79, 0x0a, 0x1b, 0x53,
|
||||
0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75,
|
||||
0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x27, 0x0a,
|
||||
0x0f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e,
|
||||
0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0x1e, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74,
|
||||
0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x8e, 0x01, 0x0a, 0x1d, 0x53, 0x75, 0x62, 0x6d, 0x69,
|
||||
0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78,
|
||||
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x69, 0x67, 0x6e,
|
||||
0x65, 0x64, 0x5f, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x5f, 0x74, 0x78, 0x73, 0x18, 0x01,
|
||||
0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66,
|
||||
0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x2b, 0x0a, 0x0f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64,
|
||||
0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48,
|
||||
0x00, 0x52, 0x0d, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78,
|
||||
0x88, 0x01, 0x01, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72,
|
||||
0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x22, 0x20, 0x0a, 0x1e, 0x53, 0x75, 0x62, 0x6d, 0x69,
|
||||
0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78,
|
||||
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 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, 0x56, 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, 0x23, 0x82, 0xd3, 0xe4,
|
||||
0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x70,
|
||||
0x69, 0x6e, 0x67, 0x2f, 0x7b, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x7d,
|
||||
0x12, 0x69, 0x0a, 0x0e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d,
|
||||
0x54, 0x78, 0x12, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d,
|
||||
0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69,
|
||||
0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x3a, 0x01, 0x2a, 0x22, 0x0d, 0x2f, 0x76,
|
||||
0x31, 0x2f, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x2d, 0x74, 0x78, 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, 0x64, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64,
|
||||
0x42, 0x79, 0x49, 0x64, 0x12, 0x1b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65,
|
||||
0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||
0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75,
|
||||
0x6e, 0x64, 0x2f, 0x69, 0x64, 0x2f, 0x7b, 0x69, 0x64, 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, 0x80, 0x01, 0x0a, 0x15, 0x47, 0x65,
|
||||
0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72,
|
||||
0x65, 0x61, 0x6d, 0x12, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74,
|
||||
0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65,
|
||||
0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x72,
|
||||
0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x30, 0x01, 0x12, 0x73, 0x0a, 0x11,
|
||||
0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x12, 0x20, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x6f,
|
||||
0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74,
|
||||
0x73, 0x74, 0x22, 0xa7, 0x03, 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,
|
||||
0x12, 0x40, 0x0a, 0x0d, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e,
|
||||
0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x65,
|
||||
0x6e, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69,
|
||||
0x6e, 0x67, 0x12, 0x6f, 0x0a, 0x1e, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x69, 0x67, 0x6e,
|
||||
0x69, 0x6e, 0x67, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72,
|
||||
0x61, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x72, 0x6b,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67,
|
||||
0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x45,
|
||||
0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1b, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67,
|
||||
0x6e, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61,
|
||||
0x74, 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, 0x72,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, 0x0e, 0x0a, 0x0c, 0x50, 0x69,
|
||||
0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x0a, 0x15, 0x53, 0x75,
|
||||
0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x5f, 0x74, 0x78,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78,
|
||||
0x22, 0x42, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d,
|
||||
0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x69,
|
||||
0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x5f, 0x74, 0x78, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x52, 0x65, 0x64, 0x65,
|
||||
0x65, 0x6d, 0x54, 0x78, 0x22, 0x25, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x22, 0x37, 0x0a, 0x10, 0x47,
|
||||
0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x23, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d,
|
||||
0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x05, 0x72,
|
||||
0x6f, 0x75, 0x6e, 0x64, 0x22, 0x25, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64,
|
||||
0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69,
|
||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x3b, 0x0a, 0x14, 0x47,
|
||||
0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e,
|
||||
0x64, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 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, 0x79, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74,
|
||||
0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x0f, 0x73,
|
||||
0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 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, 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x74, 0x78,
|
||||
0x6f, 0x73, 0x12, 0x2d, 0x0a, 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x74, 0x78, 0x6f,
|
||||
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, 0x74, 0x78, 0x6f,
|
||||
0x73, 0x22, 0xbb, 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, 0x19, 0x0a, 0x08,
|
||||
0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
|
||||
0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x12, 0x29, 0x0a, 0x09, 0x76, 0x74, 0x78, 0x6f, 0x5f,
|
||||
0x74, 0x72, 0x65, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, 0x08, 0x76, 0x74, 0x78, 0x6f, 0x54, 0x72,
|
||||
0x65, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73,
|
||||
0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x6f,
|
||||
0x72, 0x73, 0x12, 0x2b, 0x0a, 0x12, 0x6d, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x5f,
|
||||
0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f,
|
||||
0x6d, 0x69, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x46, 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x22,
|
||||
0x44, 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, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f,
|
||||
0x74, 0x78, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x6e,
|
||||
0x64, 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, 0xb8, 0x01, 0x0a,
|
||||
0x11, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x65,
|
||||
0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,
|
||||
0x69, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x6f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x5f,
|
||||
0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x63,
|
||||
0x6f, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x73, 0x50, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x73, 0x12,
|
||||
0x3a, 0x0a, 0x12, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x76, 0x74, 0x78, 0x6f,
|
||||
0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72,
|
||||
0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, 0x10, 0x75, 0x6e, 0x73, 0x69, 0x67,
|
||||
0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x54, 0x72, 0x65, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x75,
|
||||
0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64,
|
||||
0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x22, 0x53, 0x0a, 0x20, 0x52, 0x6f, 0x75, 0x6e, 0x64,
|
||||
0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x47, 0x65, 0x6e,
|
||||
0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69,
|
||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x74,
|
||||
0x72, 0x65, 0x65, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x0a, 0x74, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x22, 0xf0, 0x01, 0x0a,
|
||||
0x05, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03,
|
||||
0x65, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x19,
|
||||
0x0a, 0x08, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x07, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x12, 0x29, 0x0a, 0x09, 0x76, 0x74, 0x78,
|
||||
0x6f, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61,
|
||||
0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x52, 0x08, 0x76, 0x74, 0x78, 0x6f,
|
||||
0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x5f,
|
||||
0x74, 0x78, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x6f, 0x72, 0x66, 0x65,
|
||||
0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
|
||||
0x6f, 0x72, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
|
||||
0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x28, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x08,
|
||||
0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x22,
|
||||
0x32, 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 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, 0x9d, 0x01, 0x0a, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x2c, 0x0a,
|
||||
0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e,
|
||||
0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0a, 0x64,
|
||||
0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48,
|
||||
0x00, 0x52, 0x0a, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x34, 0x0a,
|
||||
0x0a, 0x74, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x12, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x70, 0x73, 0x63,
|
||||
0x72, 0x69, 0x70, 0x74, 0x73, 0x48, 0x00, 0x52, 0x0a, 0x74, 0x61, 0x70, 0x73, 0x63, 0x72, 0x69,
|
||||
0x70, 0x74, 0x73, 0x42, 0x0e, 0x0a, 0x0c, 0x74, 0x61, 0x70, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x74,
|
||||
0x72, 0x65, 0x65, 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,
|
||||
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, 0xc2, 0x02, 0x0a, 0x04, 0x56, 0x74, 0x78, 0x6f, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74,
|
||||
0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72,
|
||||
0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f,
|
||||
0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x70, 0x65, 0x6e, 0x74,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x0a,
|
||||
0x0a, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x78, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08,
|
||||
0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
|
||||
0x73, 0x70, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72,
|
||||
0x65, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x65, 0x78, 0x70, 0x69,
|
||||
0x72, 0x65, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x77, 0x65, 0x70, 0x74, 0x18, 0x06, 0x20,
|
||||
0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x77, 0x65, 0x70, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73,
|
||||
0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09,
|
||||
0x69, 0x73, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x64,
|
||||
0x65, 0x65, 0x6d, 0x5f, 0x74, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65,
|
||||
0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16,
|
||||
0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
|
||||
0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
|
||||
0x64, 0x5f, 0x61, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61,
|
||||
0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x1e, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e,
|
||||
0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8c, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61,
|
||||
0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x48, 0x00, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x33, 0x0a, 0x06, 0x72, 0x65, 0x64,
|
||||
0x65, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x42, 0x04,
|
||||
0x0a, 0x02, 0x74, 0x78, 0x22, 0xd8, 0x01, 0x0a, 0x10, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72,
|
||||
0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69,
|
||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x31, 0x0a,
|
||||
0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03,
|
||||
0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70,
|
||||
0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73,
|
||||
0x12, 0x35, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x74,
|
||||
0x78, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62,
|
||||
0x6c, 0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x46, 0x0a, 0x16, 0x63, 0x6c, 0x61, 0x69, 0x6d,
|
||||
0x65, 0x64, 0x5f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x74, 0x78, 0x6f,
|
||||
0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x14, 0x63, 0x6c, 0x61, 0x69, 0x6d,
|
||||
0x65, 0x64, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x22,
|
||||
0x91, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61,
|
||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x31, 0x0a, 0x0b, 0x73, 0x70, 0x65,
|
||||
0x6e, 0x74, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10,
|
||||
0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||
0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x35, 0x0a, 0x0f,
|
||||
0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18,
|
||||
0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56,
|
||||
0x74, 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x74,
|
||||
0x78, 0x6f, 0x73, 0x22, 0x6b, 0x0a, 0x0e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70,
|
||||
0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
|
||||
0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f,
|
||||
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63,
|
||||
0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69,
|
||||
0x70, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
|
||||
0x22, 0x70, 0x0a, 0x12, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x4f, 0x75,
|
||||
0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69,
|
||||
0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70,
|
||||
0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x77, 0x6e,
|
||||
0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x05, 0x70, 0x72, 0x6f,
|
||||
0x6f, 0x66, 0x22, 0x75, 0x0a, 0x18, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65,
|
||||
0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27,
|
||||
0x0a, 0x0f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x5f, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65,
|
||||
0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73,
|
||||
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69,
|
||||
0x6e, 0x74, 0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x1b, 0x0a, 0x19, 0x53, 0x65, 0x74,
|
||||
0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01,
|
||||
0x2a, 0x22, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x2f, 0x6e, 0x6f, 0x73, 0x74,
|
||||
0x72, 0x12, 0x83, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74,
|
||||
0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x2e, 0x61, 0x72, 0x6b,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52,
|
||||
0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e,
|
||||
0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x3a, 0x01, 0x2a,
|
||||
0x22, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x2f, 0x6e, 0x6f, 0x73, 0x74, 0x72,
|
||||
0x2f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 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,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, 0x0a, 0x1b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65,
|
||||
0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x01,
|
||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x69,
|
||||
0x67, 0x6e, 0x65, 0x64, 0x56, 0x74, 0x78, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||
0x52, 0x05, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x1e, 0x0a, 0x1c, 0x44, 0x65, 0x6c, 0x65, 0x74,
|
||||
0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x0a, 0x0a, 0x54, 0x61, 0x70, 0x73, 0x63,
|
||||
0x72, 0x69, 0x70, 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73,
|
||||
0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x22,
|
||||
0x85, 0x02, 0x0a, 0x0a, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x48, 0x6f, 0x75, 0x72, 0x12, 0x42,
|
||||
0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d,
|
||||
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
|
||||
0x61, 0x6d, 0x70, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69,
|
||||
0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x74,
|
||||
0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65,
|
||||
0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x6e, 0x65, 0x78, 0x74, 0x45, 0x6e, 0x64, 0x54, 0x69,
|
||||
0x6d, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x70,
|
||||
0x65, 0x72, 0x69, 0x6f, 0x64, 0x12, 0x40, 0x0a, 0x0e, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69,
|
||||
0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
|
||||
0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49,
|
||||
0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x2a, 0x98, 0x01, 0x0a, 0x0a, 0x52, 0x6f, 0x75, 0x6e,
|
||||
0x64, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f,
|
||||
0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
|
||||
0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41,
|
||||
0x47, 0x45, 0x5f, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10,
|
||||
0x01, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45,
|
||||
0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12,
|
||||
0x19, 0x0a, 0x15, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46,
|
||||
0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x4f,
|
||||
0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44,
|
||||
0x10, 0x04, 0x32, 0xf0, 0x0e, 0x0a, 0x0a, 0x41, 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x12, 0x4c, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x61,
|
||||
0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65,
|
||||
0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82,
|
||||
0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x66, 0x6f, 0x12,
|
||||
0x74, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64,
|
||||
0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x21, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47,
|
||||
0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
|
||||
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64,
|
||||
0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3,
|
||||
0xe4, 0x93, 0x02, 0x11, 0x3a, 0x01, 0x2a, 0x22, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x6f, 0x61,
|
||||
0x72, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x98, 0x01, 0x0a, 0x1a, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
|
||||
0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52,
|
||||
0x6f, 0x75, 0x6e, 0x64, 0x12, 0x29, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65,
|
||||
0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e,
|
||||
0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
|
||||
0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4,
|
||||
0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e,
|
||||
0x64, 0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73,
|
||||
0x12, 0x9c, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74,
|
||||
0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64,
|
||||
0x12, 0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
|
||||
0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74,
|
||||
0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x61,
|
||||
0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75,
|
||||
0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e,
|
||||
0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02,
|
||||
0x1e, 0x3a, 0x01, 0x2a, 0x22, 0x19, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f,
|
||||
0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x12,
|
||||
0x7d, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e,
|
||||
0x63, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62,
|
||||
0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75,
|
||||
0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01,
|
||||
0x2a, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65,
|
||||
0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x8d,
|
||||
0x01, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67,
|
||||
0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x23, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61,
|
||||
0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61,
|
||||
0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65,
|
||||
0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x3a, 0x01, 0x2a, 0x22, 0x1f, 0x2f,
|
||||
0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75,
|
||||
0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x8e,
|
||||
0x01, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46,
|
||||
0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46,
|
||||
0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x26, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74,
|
||||
0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f,
|
||||
0x3a, 0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x73,
|
||||
0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 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, 0x56, 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, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02,
|
||||
0x1d, 0x12, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x70, 0x69, 0x6e,
|
||||
0x67, 0x2f, 0x7b, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x69,
|
||||
0x0a, 0x0e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78,
|
||||
0x12, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74,
|
||||
0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x52,
|
||||
0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||
0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x3a, 0x01, 0x2a, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f,
|
||||
0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x2d, 0x74, 0x78, 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, 0x64, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79,
|
||||
0x49, 0x64, 0x12, 0x1b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52,
|
||||
0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x1c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e,
|
||||
0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82,
|
||||
0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64,
|
||||
0x2f, 0x69, 0x64, 0x2f, 0x7b, 0x69, 0x64, 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, 0x80, 0x01, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x54,
|
||||
0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61,
|
||||
0x6d, 0x12, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72,
|
||||
0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
|
||||
0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18,
|
||||
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x72, 0x61, 0x6e,
|
||||
0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x30, 0x01, 0x12, 0x73, 0x0a, 0x11, 0x53, 0x65,
|
||||
0x74, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12,
|
||||
0x20, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x73, 0x74,
|
||||
0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x1a, 0x21, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x6f,
|
||||
0x73, 0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x22,
|
||||
0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x2f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x12,
|
||||
0x83, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52,
|
||||
0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73, 0x74, 0x72, 0x52, 0x65, 0x63,
|
||||
0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e,
|
||||
0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x73,
|
||||
0x74, 0x72, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x3a, 0x01, 0x2a, 0x22, 0x15,
|
||||
0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x2f, 0x6e, 0x6f, 0x73, 0x74, 0x72, 0x2f, 0x64,
|
||||
0x65, 0x6c, 0x65, 0x74, 0x65, 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 (
|
||||
|
||||
@@ -233,14 +233,14 @@ func request_ArkService_Ping_0(ctx context.Context, marshaler runtime.Marshaler,
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["payment_id"]
|
||||
val, ok = pathParams["request_id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "payment_id")
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "request_id")
|
||||
}
|
||||
|
||||
protoReq.PaymentId, err = runtime.String(val)
|
||||
protoReq.RequestId, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "payment_id", err)
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "request_id", err)
|
||||
}
|
||||
|
||||
msg, err := client.Ping(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
@@ -259,14 +259,14 @@ func local_request_ArkService_Ping_0(ctx context.Context, marshaler runtime.Mars
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["payment_id"]
|
||||
val, ok = pathParams["request_id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "payment_id")
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "request_id")
|
||||
}
|
||||
|
||||
protoReq.PaymentId, err = runtime.String(val)
|
||||
protoReq.RequestId, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "payment_id", err)
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "request_id", err)
|
||||
}
|
||||
|
||||
msg, err := server.Ping(ctx, &protoReq)
|
||||
@@ -722,7 +722,7 @@ func RegisterArkServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux,
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/Ping", runtime.WithHTTPPathPattern("/v1/round/ping/{payment_id}"))
|
||||
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/ark.v1.ArkService/Ping", runtime.WithHTTPPathPattern("/v1/round/ping/{request_id}"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
@@ -1119,7 +1119,7 @@ func RegisterArkServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux,
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/Ping", runtime.WithHTTPPathPattern("/v1/round/ping/{payment_id}"))
|
||||
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/ark.v1.ArkService/Ping", runtime.WithHTTPPathPattern("/v1/round/ping/{request_id}"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
@@ -1309,7 +1309,7 @@ var (
|
||||
|
||||
pattern_ArkService_GetEventStream_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "events"}, ""))
|
||||
|
||||
pattern_ArkService_Ping_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "round", "ping", "payment_id"}, ""))
|
||||
pattern_ArkService_Ping_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "round", "ping", "request_id"}, ""))
|
||||
|
||||
pattern_ArkService_SubmitRedeemTx_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "redeem-tx"}, ""))
|
||||
|
||||
|
||||
@@ -97,8 +97,8 @@ var (
|
||||
Usage: "optional private key to encrypt",
|
||||
}
|
||||
urlFlag = &cli.StringFlag{
|
||||
Name: "asp-url",
|
||||
Usage: "the url of the ASP to connect to",
|
||||
Name: "server-url",
|
||||
Usage: "the url of the Ark server to connect to",
|
||||
Required: true,
|
||||
}
|
||||
receiversFlag = &cli.StringFlag{
|
||||
@@ -150,7 +150,7 @@ var (
|
||||
var (
|
||||
initCommand = cli.Command{
|
||||
Name: "init",
|
||||
Usage: "Initialize Ark wallet with encryption password, connect to ASP",
|
||||
Usage: "Initialize Ark wallet with encryption password, connect to Ark server",
|
||||
Action: func(ctx *cli.Context) error {
|
||||
return initArkSdk(ctx)
|
||||
},
|
||||
@@ -180,7 +180,7 @@ var (
|
||||
}
|
||||
settleCmd = cli.Command{
|
||||
Name: "settle",
|
||||
Usage: "Settle onboarding funds or oor payments",
|
||||
Usage: "Settle onboarding or pending funds",
|
||||
Action: func(ctx *cli.Context) error {
|
||||
return settle(ctx)
|
||||
},
|
||||
@@ -196,7 +196,7 @@ var (
|
||||
}
|
||||
sendCommand = cli.Command{
|
||||
Name: "send",
|
||||
Usage: "Send funds onchain, offchain, or asynchronously",
|
||||
Usage: "Send funds offchain",
|
||||
Action: func(ctx *cli.Context) error {
|
||||
return send(ctx)
|
||||
},
|
||||
@@ -243,7 +243,7 @@ func initArkSdk(ctx *cli.Context) error {
|
||||
ctx.Context, arksdk.InitArgs{
|
||||
ClientType: clientType,
|
||||
WalletType: arksdk.SingleKeyWallet,
|
||||
AspUrl: ctx.String(urlFlag.Name),
|
||||
ServerUrl: ctx.String(urlFlag.Name),
|
||||
Seed: ctx.String(privateKeyFlag.Name),
|
||||
Password: string(password),
|
||||
ExplorerURL: ctx.String(explorerFlag.Name),
|
||||
@@ -258,8 +258,8 @@ func config(ctx *cli.Context) error {
|
||||
}
|
||||
|
||||
cfg := map[string]interface{}{
|
||||
"asp_url": cfgData.AspUrl,
|
||||
"asp_pubkey": hex.EncodeToString(cfgData.AspPubkey.SerializeCompressed()),
|
||||
"server_url": cfgData.ServerUrl,
|
||||
"server_pubkey": hex.EncodeToString(cfgData.ServerPubKey.SerializeCompressed()),
|
||||
"wallet_type": cfgData.WalletType,
|
||||
"client_tyep": cfgData.ClientType,
|
||||
"network": cfgData.Network.Name,
|
||||
@@ -368,7 +368,7 @@ func send(ctx *cli.Context) error {
|
||||
if isBitcoin {
|
||||
return sendCovenantLess(ctx, receivers)
|
||||
}
|
||||
return sendCovenant(ctx.Context, receivers)
|
||||
return sendCovenant(ctx, receivers)
|
||||
}
|
||||
|
||||
func balance(ctx *cli.Context) error {
|
||||
@@ -525,9 +525,27 @@ func parseReceivers(receveirsJSON string, isBitcoin bool) ([]arksdk.Receiver, er
|
||||
}
|
||||
|
||||
func sendCovenantLess(ctx *cli.Context, receivers []arksdk.Receiver) error {
|
||||
var onchainReceivers, offchainReceivers []arksdk.Receiver
|
||||
|
||||
for _, receiver := range receivers {
|
||||
if receiver.IsOnchain() {
|
||||
onchainReceivers = append(onchainReceivers, receiver)
|
||||
} else {
|
||||
offchainReceivers = append(offchainReceivers, receiver)
|
||||
}
|
||||
}
|
||||
|
||||
if len(onchainReceivers) > 0 {
|
||||
txid, err := arkSdkClient.SendOnChain(ctx.Context, onchainReceivers)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printJSON(map[string]interface{}{"txid": txid})
|
||||
}
|
||||
|
||||
computeExpiration := ctx.Bool(enableExpiryCoinselectFlag.Name)
|
||||
redeemTx, err := arkSdkClient.SendAsync(
|
||||
ctx.Context, computeExpiration, receivers,
|
||||
redeemTx, err := arkSdkClient.SendOffChain(
|
||||
ctx.Context, computeExpiration, offchainReceivers,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -540,7 +558,7 @@ func sendCovenantLess(ctx *cli.Context, receivers []arksdk.Receiver) error {
|
||||
return printJSON(map[string]string{"txid": ptx.UnsignedTx.TxHash().String()})
|
||||
}
|
||||
|
||||
func sendCovenant(ctx context.Context, receivers []arksdk.Receiver) error {
|
||||
func sendCovenant(ctx *cli.Context, receivers []arksdk.Receiver) error {
|
||||
var onchainReceivers, offchainReceivers []arksdk.Receiver
|
||||
|
||||
for _, receiver := range receivers {
|
||||
@@ -552,22 +570,21 @@ func sendCovenant(ctx context.Context, receivers []arksdk.Receiver) error {
|
||||
}
|
||||
|
||||
if len(onchainReceivers) > 0 {
|
||||
txID, err := arkSdkClient.SendOnChain(ctx, onchainReceivers)
|
||||
txID, err := arkSdkClient.SendOnChain(ctx.Context, onchainReceivers)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printJSON(map[string]interface{}{"txid": txID})
|
||||
}
|
||||
|
||||
if len(offchainReceivers) > 0 {
|
||||
txID, err := arkSdkClient.SendOffChain(ctx, false, offchainReceivers)
|
||||
computeExpiration := ctx.Bool(enableExpiryCoinselectFlag.Name)
|
||||
txid, err := arkSdkClient.SendOffChain(
|
||||
ctx.Context, computeExpiration, offchainReceivers,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printJSON(map[string]interface{}{"txid": txID})
|
||||
}
|
||||
|
||||
return nil
|
||||
return printJSON(map[string]interface{}{"txid": txid})
|
||||
}
|
||||
|
||||
func readPassword(ctx *cli.Context) ([]byte, error) {
|
||||
|
||||
@@ -17,11 +17,11 @@ import (
|
||||
|
||||
// CraftSharedOutput returns the taproot script and the amount of the initial root output
|
||||
func CraftSharedOutput(
|
||||
cosigners []*secp256k1.PublicKey, aspPubkey *secp256k1.PublicKey, receivers []tree.VtxoLeaf,
|
||||
cosigners []*secp256k1.PublicKey, server *secp256k1.PublicKey, receivers []tree.VtxoLeaf,
|
||||
feeSatsPerNode uint64, roundLifetime int64,
|
||||
) ([]byte, int64, error) {
|
||||
aggregatedKey, _, err := createAggregatedKeyWithSweep(
|
||||
cosigners, aspPubkey, roundLifetime,
|
||||
cosigners, server, roundLifetime,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
@@ -34,21 +34,21 @@ func CraftSharedOutput(
|
||||
|
||||
amount := root.getAmount() + int64(feeSatsPerNode)
|
||||
|
||||
scriptPubKey, err := common.P2TRScript(aggregatedKey.FinalKey)
|
||||
scriptPubkey, err := common.P2TRScript(aggregatedKey.FinalKey)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return scriptPubKey, amount, err
|
||||
return scriptPubkey, amount, err
|
||||
}
|
||||
|
||||
// CraftCongestionTree creates all the tree's transactions
|
||||
func CraftCongestionTree(
|
||||
initialInput *wire.OutPoint, cosigners []*secp256k1.PublicKey, aspPubkey *secp256k1.PublicKey, receivers []tree.VtxoLeaf,
|
||||
// BuildVtxoTree creates all the tree's transactions
|
||||
func BuildVtxoTree(
|
||||
initialInput *wire.OutPoint, cosigners []*secp256k1.PublicKey, server *secp256k1.PublicKey, receivers []tree.VtxoLeaf,
|
||||
feeSatsPerNode uint64, roundLifetime int64,
|
||||
) (tree.CongestionTree, error) {
|
||||
) (tree.VtxoTree, error) {
|
||||
aggregatedKey, sweepTapLeaf, err := createAggregatedKeyWithSweep(
|
||||
cosigners, aspPubkey, roundLifetime,
|
||||
cosigners, server, roundLifetime,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -59,7 +59,7 @@ func CraftCongestionTree(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
congestionTree := make(tree.CongestionTree, 0)
|
||||
vtxoTree := make(tree.VtxoTree, 0)
|
||||
|
||||
ins := []*wire.OutPoint{initialInput}
|
||||
nodes := []node{root}
|
||||
@@ -95,12 +95,12 @@ func CraftCongestionTree(
|
||||
}
|
||||
}
|
||||
|
||||
congestionTree = append(congestionTree, treeLevel)
|
||||
vtxoTree = append(vtxoTree, treeLevel)
|
||||
nodes = append([]node{}, nextNodes...)
|
||||
ins = append([]*wire.OutPoint{}, nextInputsArgs...)
|
||||
}
|
||||
|
||||
return congestionTree, nil
|
||||
return vtxoTree, nil
|
||||
}
|
||||
|
||||
type node interface {
|
||||
@@ -252,7 +252,7 @@ func createRootNode(
|
||||
|
||||
nodes := make([]node, 0, len(receivers))
|
||||
for _, r := range receivers {
|
||||
pubkeyBytes, err := hex.DecodeString(r.Pubkey)
|
||||
pubkeyBytes, err := hex.DecodeString(r.PubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -280,10 +280,10 @@ func createRootNode(
|
||||
}
|
||||
|
||||
func createAggregatedKeyWithSweep(
|
||||
cosigners []*secp256k1.PublicKey, aspPubkey *secp256k1.PublicKey, roundLifetime int64,
|
||||
cosigners []*secp256k1.PublicKey, server *secp256k1.PublicKey, roundLifetime int64,
|
||||
) (*musig2.AggregateKey, *psbt.TaprootTapLeafScript, error) {
|
||||
sweepClosure := &tree.CSVSigClosure{
|
||||
MultisigClosure: tree.MultisigClosure{PubKeys: []*secp256k1.PublicKey{aspPubkey}},
|
||||
MultisigClosure: tree.MultisigClosure{PubKeys: []*secp256k1.PublicKey{server}},
|
||||
Seconds: uint(roundLifetime),
|
||||
}
|
||||
|
||||
|
||||
@@ -7,29 +7,24 @@ import (
|
||||
)
|
||||
|
||||
func BuildForfeitTxs(
|
||||
connectorTx *psbt.Packet,
|
||||
vtxoInput *wire.OutPoint,
|
||||
vtxoAmount,
|
||||
connectorAmount,
|
||||
feeAmount uint64,
|
||||
vtxoScript,
|
||||
aspScript []byte,
|
||||
connectorTx *psbt.Packet, vtxoInput *wire.OutPoint,
|
||||
vtxoAmount, connectorAmount, feeAmount uint64,
|
||||
vtxoScript, serverScript []byte,
|
||||
) (forfeitTxs []*psbt.Packet, err error) {
|
||||
version := int32(2)
|
||||
locktime := uint32(0)
|
||||
connectors, prevouts := getConnectorInputs(connectorTx, int64(connectorAmount))
|
||||
|
||||
for i, connectorInput := range connectors {
|
||||
connectorPrevout := prevouts[i]
|
||||
|
||||
partialTx, err := psbt.New(
|
||||
[]*wire.OutPoint{connectorInput, vtxoInput},
|
||||
[]*wire.TxOut{{
|
||||
ins := []*wire.OutPoint{connectorInput, vtxoInput}
|
||||
outs := []*wire.TxOut{{
|
||||
Value: int64(vtxoAmount) + int64(connectorAmount) - int64(feeAmount),
|
||||
PkScript: aspScript,
|
||||
}},
|
||||
2,
|
||||
0,
|
||||
[]uint32{wire.MaxTxInSequenceNum, wire.MaxTxInSequenceNum},
|
||||
)
|
||||
PkScript: serverScript,
|
||||
}}
|
||||
sequences := []uint32{wire.MaxTxInSequenceNum, wire.MaxTxInSequenceNum}
|
||||
partialTx, err := psbt.New(ins, outs, version, locktime, sequences)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ErrCongestionTreeNotSet = errors.New("congestion tree not set")
|
||||
ErrAggregateKeyNotSet = errors.New("aggregate key not set")
|
||||
ErrMissingVtxoTree = errors.New("missing vtxo tree")
|
||||
ErrMissingAggregateKey = errors.New("missing aggregate key")
|
||||
)
|
||||
|
||||
type Musig2Nonce struct {
|
||||
@@ -62,7 +62,7 @@ type CoordinatorSession interface {
|
||||
AggregateNonces() (TreeNonces, error)
|
||||
AddSig(*btcec.PublicKey, TreePartialSigs) error
|
||||
// SignTree combines the signatures and add them to the tree's psbts
|
||||
SignTree() (tree.CongestionTree, error)
|
||||
SignTree() (tree.VtxoTree, error)
|
||||
}
|
||||
|
||||
func (n TreeNonces) Encode(w io.Writer) error {
|
||||
@@ -111,7 +111,7 @@ func ValidateTreeSigs(
|
||||
scriptRoot []byte,
|
||||
finalAggregatedKey *btcec.PublicKey,
|
||||
roundSharedOutputAmount int64,
|
||||
vtxoTree tree.CongestionTree,
|
||||
vtxoTree tree.VtxoTree,
|
||||
) error {
|
||||
prevoutFetcherFactory, err := prevOutFetcherFactory(finalAggregatedKey, vtxoTree, roundSharedOutputAmount)
|
||||
if err != nil {
|
||||
@@ -163,7 +163,7 @@ func ValidateTreeSigs(
|
||||
func NewTreeSignerSession(
|
||||
signer *btcec.PrivateKey,
|
||||
roundSharedOutputAmount int64,
|
||||
vtxoTree tree.CongestionTree,
|
||||
vtxoTree tree.VtxoTree,
|
||||
scriptRoot []byte,
|
||||
) SignerSession {
|
||||
return &treeSignerSession{
|
||||
@@ -176,7 +176,7 @@ func NewTreeSignerSession(
|
||||
|
||||
type treeSignerSession struct {
|
||||
secretKey *btcec.PrivateKey
|
||||
tree tree.CongestionTree
|
||||
tree tree.VtxoTree
|
||||
myNonces [][]*musig2.Nonces
|
||||
keys []*btcec.PublicKey
|
||||
aggregateNonces TreeNonces
|
||||
@@ -187,7 +187,7 @@ type treeSignerSession struct {
|
||||
|
||||
func (t *treeSignerSession) generateNonces() error {
|
||||
if t.tree == nil {
|
||||
return ErrCongestionTreeNotSet
|
||||
return ErrMissingVtxoTree
|
||||
}
|
||||
|
||||
myNonces := make([][]*musig2.Nonces, 0)
|
||||
@@ -213,7 +213,7 @@ func (t *treeSignerSession) generateNonces() error {
|
||||
|
||||
func (t *treeSignerSession) GetNonces() (TreeNonces, error) {
|
||||
if t.tree == nil {
|
||||
return nil, ErrCongestionTreeNotSet
|
||||
return nil, ErrMissingVtxoTree
|
||||
}
|
||||
|
||||
if t.myNonces == nil {
|
||||
@@ -267,11 +267,11 @@ func (t *treeSignerSession) SetAggregatedNonces(nonces TreeNonces) error {
|
||||
|
||||
func (t *treeSignerSession) Sign() (TreePartialSigs, error) {
|
||||
if t.tree == nil {
|
||||
return nil, ErrCongestionTreeNotSet
|
||||
return nil, ErrMissingVtxoTree
|
||||
}
|
||||
|
||||
if t.keys == nil {
|
||||
return nil, ErrAggregateKeyNotSet
|
||||
return nil, ErrMissingAggregateKey
|
||||
}
|
||||
|
||||
if t.aggregateNonces == nil {
|
||||
@@ -331,7 +331,7 @@ func (t *treeSignerSession) signPartial(partialTx *psbt.Packet, posx int, posy i
|
||||
|
||||
type treeCoordinatorSession struct {
|
||||
scriptRoot []byte
|
||||
tree tree.CongestionTree
|
||||
tree tree.VtxoTree
|
||||
keys []*btcec.PublicKey
|
||||
nonces []TreeNonces
|
||||
sigs []TreePartialSigs
|
||||
@@ -340,7 +340,7 @@ type treeCoordinatorSession struct {
|
||||
|
||||
func NewTreeCoordinatorSession(
|
||||
roundSharedOutputAmount int64,
|
||||
vtxoTree tree.CongestionTree,
|
||||
vtxoTree tree.VtxoTree,
|
||||
scriptRoot []byte,
|
||||
keys []*btcec.PublicKey,
|
||||
) (CoordinatorSession, error) {
|
||||
@@ -428,7 +428,7 @@ func (t *treeCoordinatorSession) AggregateNonces() (TreeNonces, error) {
|
||||
}
|
||||
|
||||
// SignTree implements CoordinatorSession.
|
||||
func (t *treeCoordinatorSession) SignTree() (tree.CongestionTree, error) {
|
||||
func (t *treeCoordinatorSession) SignTree() (tree.VtxoTree, error) {
|
||||
var missingSigs int
|
||||
for _, sig := range t.sigs {
|
||||
if sig == nil {
|
||||
@@ -508,7 +508,7 @@ func (t *treeCoordinatorSession) SignTree() (tree.CongestionTree, error) {
|
||||
|
||||
func prevOutFetcherFactory(
|
||||
finalAggregatedKey *btcec.PublicKey,
|
||||
vtxoTree tree.CongestionTree,
|
||||
vtxoTree tree.VtxoTree,
|
||||
roundSharedOutputAmount int64,
|
||||
) (
|
||||
func(partial *psbt.Packet) (txscript.PrevOutputFetcher, error),
|
||||
|
||||
@@ -28,33 +28,33 @@ func TestRoundTripSignTree(t *testing.T) {
|
||||
for _, f := range fixtures.Valid {
|
||||
// Generate 20 cosigners
|
||||
cosigners := make([]*secp256k1.PrivateKey, 20)
|
||||
cosignerPubKeys := make([]*btcec.PublicKey, 20)
|
||||
cosignerPubkeys := make([]*btcec.PublicKey, 20)
|
||||
for i := 0; i < 20; i++ {
|
||||
privKey, err := secp256k1.GeneratePrivateKey()
|
||||
prvkey, err := secp256k1.GeneratePrivateKey()
|
||||
require.NoError(t, err)
|
||||
cosigners[i] = privKey
|
||||
cosignerPubKeys[i] = privKey.PubKey()
|
||||
cosigners[i] = prvkey
|
||||
cosignerPubkeys[i] = prvkey.PubKey()
|
||||
}
|
||||
|
||||
asp, err := secp256k1.GeneratePrivateKey()
|
||||
server, err := secp256k1.GeneratePrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
_, sharedOutputAmount, err := bitcointree.CraftSharedOutput(
|
||||
cosignerPubKeys,
|
||||
asp.PubKey(),
|
||||
cosignerPubkeys,
|
||||
server.PubKey(),
|
||||
castReceivers(f.Receivers),
|
||||
minRelayFee,
|
||||
lifetime,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
vtxoTree, err := bitcointree.CraftCongestionTree(
|
||||
vtxoTree, err := bitcointree.BuildVtxoTree(
|
||||
&wire.OutPoint{
|
||||
Hash: *testTxid,
|
||||
Index: 0,
|
||||
},
|
||||
cosignerPubKeys,
|
||||
asp.PubKey(),
|
||||
cosignerPubkeys,
|
||||
server.PubKey(),
|
||||
castReceivers(f.Receivers),
|
||||
minRelayFee,
|
||||
lifetime,
|
||||
@@ -62,7 +62,7 @@ func TestRoundTripSignTree(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
sweepClosure := &tree.CSVSigClosure{
|
||||
MultisigClosure: tree.MultisigClosure{PubKeys: []*secp256k1.PublicKey{asp.PubKey()}},
|
||||
MultisigClosure: tree.MultisigClosure{PubKeys: []*secp256k1.PublicKey{server.PubKey()}},
|
||||
Seconds: uint(lifetime),
|
||||
}
|
||||
|
||||
@@ -73,11 +73,11 @@ func TestRoundTripSignTree(t *testing.T) {
|
||||
sweepTapTree := txscript.AssembleTaprootScriptTree(sweepTapLeaf)
|
||||
root := sweepTapTree.RootNode.TapHash()
|
||||
|
||||
aspCoordinator, err := bitcointree.NewTreeCoordinatorSession(
|
||||
serverCoordinator, err := bitcointree.NewTreeCoordinatorSession(
|
||||
sharedOutputAmount,
|
||||
vtxoTree,
|
||||
root.CloneBytes(),
|
||||
cosignerPubKeys,
|
||||
cosignerPubkeys,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -91,16 +91,16 @@ func TestRoundTripSignTree(t *testing.T) {
|
||||
for i, session := range signerSessions {
|
||||
nonces, err := session.GetNonces()
|
||||
require.NoError(t, err)
|
||||
err = aspCoordinator.AddNonce(cosignerPubKeys[i], nonces)
|
||||
err = serverCoordinator.AddNonce(cosignerPubkeys[i], nonces)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
aggregatedNonce, err := aspCoordinator.AggregateNonces()
|
||||
aggregatedNonce, err := serverCoordinator.AggregateNonces()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Set keys and aggregated nonces for all signers
|
||||
for _, session := range signerSessions {
|
||||
err = session.SetKeys(cosignerPubKeys)
|
||||
err = session.SetKeys(cosignerPubkeys)
|
||||
require.NoError(t, err)
|
||||
err = session.SetAggregatedNonces(aggregatedNonce)
|
||||
require.NoError(t, err)
|
||||
@@ -110,15 +110,15 @@ func TestRoundTripSignTree(t *testing.T) {
|
||||
for i, session := range signerSessions {
|
||||
sig, err := session.Sign()
|
||||
require.NoError(t, err)
|
||||
err = aspCoordinator.AddSig(cosignerPubKeys[i], sig)
|
||||
err = serverCoordinator.AddSig(cosignerPubkeys[i], sig)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
signedTree, err := aspCoordinator.SignTree()
|
||||
signedTree, err := serverCoordinator.SignTree()
|
||||
require.NoError(t, err)
|
||||
|
||||
// verify the tree
|
||||
aggregatedKey, err := bitcointree.AggregateKeys(cosignerPubKeys, root.CloneBytes())
|
||||
aggregatedKey, err := bitcointree.AggregateKeys(cosignerPubkeys, root.CloneBytes())
|
||||
require.NoError(t, err)
|
||||
|
||||
err = bitcointree.ValidateTreeSigs(
|
||||
@@ -140,7 +140,7 @@ func castReceivers(receivers []receiverFixture) []tree.VtxoLeaf {
|
||||
receiversOut := make([]tree.VtxoLeaf, 0, len(receivers))
|
||||
for _, r := range receivers {
|
||||
receiversOut = append(receiversOut, tree.VtxoLeaf{
|
||||
Pubkey: r.Pubkey,
|
||||
PubKey: r.Pubkey,
|
||||
Amount: uint64(r.Amount),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package bitcointree
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
@@ -15,36 +14,36 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidPoolTransaction = errors.New("invalid pool transaction")
|
||||
ErrInvalidPoolTransactionOutputs = errors.New("invalid number of outputs in pool transaction")
|
||||
ErrEmptyTree = errors.New("empty congestion tree")
|
||||
ErrInvalidRootLevel = errors.New("root level must have only one node")
|
||||
ErrNoLeaves = errors.New("no leaves in the tree")
|
||||
ErrNodeTransactionEmpty = errors.New("node transaction is empty")
|
||||
ErrNodeTxidEmpty = errors.New("node txid is empty")
|
||||
ErrNodeParentTxidEmpty = errors.New("node parent txid is empty")
|
||||
ErrNodeTxidDifferent = errors.New("node txid differs from node transaction")
|
||||
ErrNumberOfInputs = errors.New("node transaction should have only one input")
|
||||
ErrNumberOfOutputs = errors.New("node transaction should have only three or two outputs")
|
||||
ErrParentTxidInput = errors.New("parent txid should be the input of the node transaction")
|
||||
ErrNumberOfChildren = errors.New("node branch transaction should have two children")
|
||||
ErrLeafChildren = errors.New("leaf node should have max 1 child")
|
||||
ErrInvalidChildTxid = errors.New("invalid child txid")
|
||||
ErrNumberOfTapscripts = errors.New("input should have 1 tapscript leaf")
|
||||
ErrInternalKey = errors.New("invalid taproot internal key")
|
||||
ErrInvalidTaprootScript = errors.New("invalid taproot script")
|
||||
ErrInvalidControlBlock = errors.New("invalid control block")
|
||||
ErrInvalidTaprootScriptLen = errors.New("invalid taproot script length (expected 32 bytes)")
|
||||
ErrInvalidLeafTaprootScript = errors.New("invalid leaf taproot script")
|
||||
ErrInvalidAmount = errors.New("children amount is different from parent amount")
|
||||
ErrInvalidSweepSequence = errors.New("invalid sweep sequence")
|
||||
ErrInvalidASP = errors.New("invalid ASP")
|
||||
ErrMissingFeeOutput = errors.New("missing fee output")
|
||||
ErrInvalidLeftOutput = errors.New("invalid left output")
|
||||
ErrInvalidRightOutput = errors.New("invalid right output")
|
||||
ErrMissingSweepTapscript = errors.New("missing sweep tapscript")
|
||||
ErrInvalidLeaf = errors.New("leaf node shouldn't have children")
|
||||
ErrWrongPoolTxID = errors.New("root input should be the pool tx outpoint")
|
||||
ErrInvalidRoundTx = fmt.Errorf("invalid round transaction")
|
||||
ErrInvalidRoundTxOutputs = fmt.Errorf("invalid number of outputs in round transaction")
|
||||
ErrEmptyTree = fmt.Errorf("empty vtxo tree")
|
||||
ErrInvalidRootLevel = fmt.Errorf("root level must have only one node")
|
||||
ErrNoLeaves = fmt.Errorf("no leaves in the tree")
|
||||
ErrNodeTxEmpty = fmt.Errorf("node transaction is empty")
|
||||
ErrNodeTxidEmpty = fmt.Errorf("node txid is empty")
|
||||
ErrNodeParentTxidEmpty = fmt.Errorf("node parent txid is empty")
|
||||
ErrNodeTxidDifferent = fmt.Errorf("node txid differs from node transaction")
|
||||
ErrNumberOfInputs = fmt.Errorf("node transaction should have only one input")
|
||||
ErrNumberOfOutputs = fmt.Errorf("node transaction should have only three or two outputs")
|
||||
ErrParentTxidInput = fmt.Errorf("parent txid should be the input of the node transaction")
|
||||
ErrNumberOfChildren = fmt.Errorf("node branch transaction should have two children")
|
||||
ErrLeafChildren = fmt.Errorf("leaf node should have max 1 child")
|
||||
ErrInvalidChildTxid = fmt.Errorf("invalid child txid")
|
||||
ErrNumberOfTapscripts = fmt.Errorf("input should have 1 tapscript leaf")
|
||||
ErrInternalKey = fmt.Errorf("invalid taproot internal key")
|
||||
ErrInvalidTaprootScript = fmt.Errorf("invalid taproot script")
|
||||
ErrInvalidControlBlock = fmt.Errorf("invalid control block")
|
||||
ErrInvalidTaprootScriptLen = fmt.Errorf("invalid taproot script length (expected 32 bytes)")
|
||||
ErrInvalidLeafTaprootScript = fmt.Errorf("invalid leaf taproot script")
|
||||
ErrInvalidAmount = fmt.Errorf("children amount is different from parent amount")
|
||||
ErrInvalidSweepSequence = fmt.Errorf("invalid sweep sequence")
|
||||
ErrInvalidServer = fmt.Errorf("invalid server")
|
||||
ErrMissingFeeOutput = fmt.Errorf("missing fee output")
|
||||
ErrInvalidLeftOutput = fmt.Errorf("invalid left output")
|
||||
ErrInvalidRightOutput = fmt.Errorf("invalid right output")
|
||||
ErrMissingSweepTapscript = fmt.Errorf("missing sweep tapscript")
|
||||
ErrInvalidLeaf = fmt.Errorf("leaf node shouldn't have children")
|
||||
ErrWrongRoundTxid = fmt.Errorf("the input of the tree root is not the round tx's shared output")
|
||||
)
|
||||
|
||||
// 0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0
|
||||
@@ -62,28 +61,28 @@ func UnspendableKey() *secp256k1.PublicKey {
|
||||
return key
|
||||
}
|
||||
|
||||
// ValidateCongestionTree checks if the given congestion tree is valid
|
||||
// poolTxID & poolTxIndex & poolTxAmount are used to validate the root input outpoint
|
||||
// aspPublicKey & roundLifetime are used to validate the sweep tapscript leaves
|
||||
// ValidateVtxoTree checks if the given vtxo tree is valid
|
||||
// roundTxid & roundTxIndex & roundTxAmount are used to validate the root input outpoint
|
||||
// serverPubkey & roundLifetime are used to validate the sweep tapscript leaves
|
||||
// besides that, the function validates:
|
||||
// - the number of nodes
|
||||
// - the number of leaves
|
||||
// - children coherence with parent
|
||||
// - every control block and taproot output scripts
|
||||
// - input and output amounts
|
||||
func ValidateCongestionTree(
|
||||
vtxoTree tree.CongestionTree, poolTx string, aspPublicKey *secp256k1.PublicKey, roundLifetime int64,
|
||||
func ValidateVtxoTree(
|
||||
vtxoTree tree.VtxoTree, roundTx string, serverPubkey *secp256k1.PublicKey, roundLifetime int64,
|
||||
) error {
|
||||
poolTransaction, err := psbt.NewFromRawBytes(strings.NewReader(poolTx), true)
|
||||
roundTransaction, err := psbt.NewFromRawBytes(strings.NewReader(roundTx), true)
|
||||
if err != nil {
|
||||
return ErrInvalidPoolTransaction
|
||||
return ErrInvalidRoundTx
|
||||
}
|
||||
|
||||
if len(poolTransaction.Outputs) < sharedOutputIndex+1 {
|
||||
return ErrInvalidPoolTransactionOutputs
|
||||
if len(roundTransaction.Outputs) < sharedOutputIndex+1 {
|
||||
return ErrInvalidRoundTxOutputs
|
||||
}
|
||||
|
||||
poolTxAmount := poolTransaction.UnsignedTx.TxOut[sharedOutputIndex].Value
|
||||
roundTxAmount := roundTransaction.UnsignedTx.TxOut[sharedOutputIndex].Value
|
||||
|
||||
nbNodes := vtxoTree.NumberOfNodes()
|
||||
if nbNodes == 0 {
|
||||
@@ -94,7 +93,7 @@ func ValidateCongestionTree(
|
||||
return ErrInvalidRootLevel
|
||||
}
|
||||
|
||||
// check that root input is connected to the pool tx
|
||||
// check that root input is connected to the round tx
|
||||
rootPsetB64 := vtxoTree[0][0].Tx
|
||||
rootPset, err := psbt.NewFromRawBytes(strings.NewReader(rootPsetB64), true)
|
||||
if err != nil {
|
||||
@@ -106,9 +105,9 @@ func ValidateCongestionTree(
|
||||
}
|
||||
|
||||
rootInput := rootPset.UnsignedTx.TxIn[0]
|
||||
if chainhash.Hash(rootInput.PreviousOutPoint.Hash).String() != poolTransaction.UnsignedTx.TxHash().String() ||
|
||||
if chainhash.Hash(rootInput.PreviousOutPoint.Hash).String() != roundTransaction.UnsignedTx.TxHash().String() ||
|
||||
rootInput.PreviousOutPoint.Index != sharedOutputIndex {
|
||||
return ErrWrongPoolTxID
|
||||
return ErrWrongRoundTxid
|
||||
}
|
||||
|
||||
sumRootValue := int64(0)
|
||||
@@ -116,7 +115,7 @@ func ValidateCongestionTree(
|
||||
sumRootValue += output.Value
|
||||
}
|
||||
|
||||
if sumRootValue >= poolTxAmount {
|
||||
if sumRootValue >= roundTxAmount {
|
||||
return ErrInvalidAmount
|
||||
}
|
||||
|
||||
@@ -125,7 +124,7 @@ func ValidateCongestionTree(
|
||||
}
|
||||
|
||||
sweepClosure := &tree.CSVSigClosure{
|
||||
MultisigClosure: tree.MultisigClosure{PubKeys: []*secp256k1.PublicKey{aspPublicKey}},
|
||||
MultisigClosure: tree.MultisigClosure{PubKeys: []*secp256k1.PublicKey{serverPubkey}},
|
||||
Seconds: uint(roundLifetime),
|
||||
}
|
||||
|
||||
@@ -152,9 +151,9 @@ func ValidateCongestionTree(
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateNodeTransaction(node tree.Node, tree tree.CongestionTree, tapTreeRoot []byte) error {
|
||||
func validateNodeTransaction(node tree.Node, tree tree.VtxoTree, tapTreeRoot []byte) error {
|
||||
if node.Tx == "" {
|
||||
return ErrNodeTransactionEmpty
|
||||
return ErrNodeTxEmpty
|
||||
}
|
||||
|
||||
if node.Txid == "" {
|
||||
|
||||
@@ -26,8 +26,8 @@ func ParseVtxoScript(scripts []string) (VtxoScript, error) {
|
||||
return nil, fmt.Errorf("invalid vtxo scripts: %s", scripts)
|
||||
}
|
||||
|
||||
func NewDefaultVtxoScript(owner, asp *secp256k1.PublicKey, exitDelay uint) VtxoScript {
|
||||
base := tree.NewDefaultVtxoScript(owner, asp, exitDelay)
|
||||
func NewDefaultVtxoScript(owner, server *secp256k1.PublicKey, exitDelay uint) VtxoScript {
|
||||
base := tree.NewDefaultVtxoScript(owner, server, exitDelay)
|
||||
|
||||
return &TapscriptsVtxoScript{*base}
|
||||
}
|
||||
|
||||
@@ -7,14 +7,14 @@ import (
|
||||
"github.com/vulpemventures/go-elements/psetv2"
|
||||
)
|
||||
|
||||
func ValidateConnectors(poolTx string, connectors []string) error {
|
||||
ptx, err := psetv2.NewPsetFromBase64(poolTx)
|
||||
func ValidateConnectors(roundTx string, connectors []string) error {
|
||||
ptx, err := psetv2.NewPsetFromBase64(roundTx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid pool tx: %s", err)
|
||||
return fmt.Errorf("invalid round tx: %s", err)
|
||||
}
|
||||
utx, err := ptx.UnsignedTx()
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid pool tx: %s", err)
|
||||
return fmt.Errorf("invalid round tx: %s", err)
|
||||
}
|
||||
prevConnectorTxid := utx.TxHash().String()
|
||||
prevConnectorVout := uint32(1)
|
||||
|
||||
@@ -8,12 +8,12 @@ import (
|
||||
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
||||
)
|
||||
|
||||
// tr(unspendable, { and(pk(user), pk(asp)), and(older(timeout), pk(user)) })
|
||||
// tr(unspendable, { and(pk(user), pk(server)), and(older(timeout), pk(user)) })
|
||||
const DefaultVtxoDescriptorTemplate = "tr(%s,{ and(pk(%s), pk(%s)), and(older(%d), pk(%s)) })"
|
||||
|
||||
func ParseDefaultVtxoDescriptor(
|
||||
descriptor string,
|
||||
) (user, asp *secp256k1.PublicKey, timeout uint, err error) {
|
||||
) (user, server *secp256k1.PublicKey, timeout uint, err error) {
|
||||
desc, err := ParseTaprootDescriptor(descriptor)
|
||||
if err != nil {
|
||||
return nil, nil, 0, err
|
||||
@@ -42,7 +42,7 @@ func ParseDefaultVtxoDescriptor(
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
|
||||
asp, err = schnorr.ParsePubKey(keyBytes)
|
||||
server, err = schnorr.ParsePubKey(keyBytes)
|
||||
if err != nil {
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
@@ -70,7 +70,7 @@ func ParseDefaultVtxoDescriptor(
|
||||
return nil, nil, 0, errors.New("boarding descriptor is invalid")
|
||||
}
|
||||
|
||||
if asp == nil {
|
||||
if server == nil {
|
||||
return nil, nil, 0, errors.New("boarding descriptor is invalid")
|
||||
}
|
||||
|
||||
|
||||
@@ -8,24 +8,24 @@ import (
|
||||
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
||||
)
|
||||
|
||||
// Address represents an Ark address with HRP, ASP public key, and VTXO Taproot public key
|
||||
// Address represents an Ark address with HRP, server public key, and VTXO Taproot public key
|
||||
type Address struct {
|
||||
HRP string
|
||||
Asp *secp256k1.PublicKey
|
||||
Server *secp256k1.PublicKey
|
||||
VtxoTapKey *secp256k1.PublicKey
|
||||
}
|
||||
|
||||
// Encode converts the address to its bech32m string representation
|
||||
func (a *Address) Encode() (string, error) {
|
||||
if a.Asp == nil {
|
||||
return "", fmt.Errorf("missing asp public key")
|
||||
if a.Server == nil {
|
||||
return "", fmt.Errorf("missing server public key")
|
||||
}
|
||||
if a.VtxoTapKey == nil {
|
||||
return "", fmt.Errorf("missing vtxo tap public key")
|
||||
}
|
||||
|
||||
combinedKey := append(
|
||||
schnorr.SerializePubKey(a.Asp), schnorr.SerializePubKey(a.VtxoTapKey)...,
|
||||
schnorr.SerializePubKey(a.Server), schnorr.SerializePubKey(a.VtxoTapKey)...,
|
||||
)
|
||||
grp, err := bech32.ConvertBits(combinedKey, 8, 5, true)
|
||||
if err != nil {
|
||||
@@ -52,19 +52,19 @@ func DecodeAddress(addr string) (*Address, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
aKey, err := schnorr.ParsePubKey(grp[:32])
|
||||
serverKey, err := schnorr.ParsePubKey(grp[:32])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse public key: %s", err)
|
||||
}
|
||||
|
||||
vtxoKey, err := schnorr.ParsePubKey(grp[32:])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse asp public key: %s", err)
|
||||
return nil, fmt.Errorf("failed to parse server public key: %s", err)
|
||||
}
|
||||
|
||||
return &Address{
|
||||
HRP: prefix,
|
||||
Asp: aKey,
|
||||
Server: serverKey,
|
||||
VtxoTapKey: vtxoKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func TestAddressEncoding(t *testing.T) {
|
||||
Valid []struct {
|
||||
Addr string `json:"addr"`
|
||||
ExpectedUserKey string `json:"expectedUserKey"`
|
||||
ExpectedAspKey string `json:"expectedAspKey"`
|
||||
ExpectedServerKey string `json:"expectedServerKey"`
|
||||
} `json:"valid"`
|
||||
Invalid []struct {
|
||||
Addr string `json:"addr"`
|
||||
@@ -43,14 +43,14 @@ func TestAddressEncoding(t *testing.T) {
|
||||
addr, err := common.DecodeAddress(f.Addr)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, addr.HRP)
|
||||
require.NotNil(t, addr.Asp)
|
||||
require.NotNil(t, addr.Server)
|
||||
require.NotNil(t, addr.VtxoTapKey)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, f.ExpectedUserKey, hex.EncodeToString(addr.VtxoTapKey.SerializeCompressed()))
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, f.ExpectedAspKey, hex.EncodeToString(addr.Asp.SerializeCompressed()))
|
||||
require.Equal(t, f.ExpectedServerKey, hex.EncodeToString(addr.Server.SerializeCompressed()))
|
||||
|
||||
encoded, err := addr.Encode()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -30,7 +30,7 @@ func ComputeForfeitTxFee(
|
||||
feeRate chainfee.SatPerKVByte,
|
||||
tapscript *waddrmgr.Tapscript,
|
||||
witnessSize int,
|
||||
aspScriptClass txscript.ScriptClass,
|
||||
serverScriptClass txscript.ScriptClass,
|
||||
) (uint64, error) {
|
||||
txWeightEstimator := &input.TxWeightEstimator{}
|
||||
|
||||
@@ -40,7 +40,7 @@ func ComputeForfeitTxFee(
|
||||
tapscript,
|
||||
)
|
||||
|
||||
switch aspScriptClass {
|
||||
switch serverScriptClass {
|
||||
case txscript.PubKeyHashTy:
|
||||
txWeightEstimator.AddP2PKHOutput()
|
||||
case txscript.ScriptHashTy:
|
||||
@@ -52,7 +52,7 @@ func ComputeForfeitTxFee(
|
||||
case txscript.WitnessV1TaprootTy:
|
||||
txWeightEstimator.AddP2TROutput()
|
||||
default:
|
||||
return 0, fmt.Errorf("unknown asp script class: %v", aspScriptClass)
|
||||
return 0, fmt.Errorf("unknown server script class: %v", serverScriptClass)
|
||||
}
|
||||
|
||||
return uint64(feeRate.FeeForVSize(lntypes.VByte(txWeightEstimator.VSize())).ToUnit(btcutil.AmountSatoshi)), nil
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
{
|
||||
"addr": "tark1x0lm8hhr2wc6n6lyemtyh9rz8rg2ftpkfun46aca56kjg3ws0tsztfpuanaquxc6faedvjk3tax0575y6perapg3e95654pk8r4fjecs5fyd2",
|
||||
"expectedUserKey": "0225a43cecfa0e1b1a4f72d64ad15f4cfa7a84d0723e8511c969aa543638ea9967",
|
||||
"expectedAspKey": "0233ffb3dee353b1a9ebe4ced64b946238d0a4ac364f275d771da6ad2445d07ae0"
|
||||
"expectedServerKey": "0233ffb3dee353b1a9ebe4ced64b946238d0a4ac364f275d771da6ad2445d07ae0"
|
||||
}
|
||||
],
|
||||
"invalid": [
|
||||
|
||||
@@ -12,15 +12,15 @@ import (
|
||||
"github.com/vulpemventures/go-elements/taproot"
|
||||
)
|
||||
|
||||
func CraftCongestionTree(
|
||||
asset string, aspPubkey *secp256k1.PublicKey, receivers []VtxoLeaf,
|
||||
func BuildVtxoTree(
|
||||
asset string, serverPubkey *secp256k1.PublicKey, receivers []VtxoLeaf,
|
||||
feeSatsPerNode uint64, roundLifetime int64,
|
||||
) (
|
||||
buildCongestionTree TreeFactory,
|
||||
factoryFn TreeFactory,
|
||||
sharedOutputScript []byte, sharedOutputAmount uint64, err error,
|
||||
) {
|
||||
root, err := createPartialCongestionTree(
|
||||
asset, aspPubkey, receivers, feeSatsPerNode, roundLifetime,
|
||||
root, err := buildTreeNodes(
|
||||
asset, serverPubkey, receivers, feeSatsPerNode, roundLifetime,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -36,7 +36,7 @@ func CraftCongestionTree(
|
||||
return
|
||||
}
|
||||
sharedOutputAmount = root.getAmount() + root.feeSats
|
||||
buildCongestionTree = root.createFinalCongestionTree()
|
||||
factoryFn = root.buildVtxoTree()
|
||||
|
||||
return
|
||||
}
|
||||
@@ -321,16 +321,16 @@ func (n *node) getTx(
|
||||
return pset, nil
|
||||
}
|
||||
|
||||
func (n *node) createFinalCongestionTree() TreeFactory {
|
||||
return func(poolTxInput psetv2.InputArgs) (CongestionTree, error) {
|
||||
congestionTree := make(CongestionTree, 0)
|
||||
func (n *node) buildVtxoTree() TreeFactory {
|
||||
return func(roundTxInput psetv2.InputArgs) (VtxoTree, error) {
|
||||
vtxoTree := make(VtxoTree, 0)
|
||||
|
||||
_, taprootTree, err := n.getWitnessData()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ins := []psetv2.InputArgs{poolTxInput}
|
||||
ins := []psetv2.InputArgs{roundTxInput}
|
||||
inTrees := []*taproot.IndexedElementsTapScriptTree{taprootTree}
|
||||
nodes := []*node{n}
|
||||
|
||||
@@ -366,7 +366,7 @@ func (n *node) createFinalCongestionTree() TreeFactory {
|
||||
}
|
||||
}
|
||||
|
||||
congestionTree = append(congestionTree, treeLevel)
|
||||
vtxoTree = append(vtxoTree, treeLevel)
|
||||
nodes = append([]*node{}, nextNodes...)
|
||||
ins = append([]psetv2.InputArgs{}, nextInputsArgs...)
|
||||
inTrees = append(
|
||||
@@ -374,12 +374,12 @@ func (n *node) createFinalCongestionTree() TreeFactory {
|
||||
)
|
||||
}
|
||||
|
||||
return congestionTree, nil
|
||||
return vtxoTree, nil
|
||||
}
|
||||
}
|
||||
|
||||
func createPartialCongestionTree(
|
||||
asset string, aspPubkey *secp256k1.PublicKey, receivers []VtxoLeaf,
|
||||
func buildTreeNodes(
|
||||
asset string, serverPubkey *secp256k1.PublicKey, receivers []VtxoLeaf,
|
||||
feeSatsPerNode uint64, roundLifetime int64,
|
||||
) (root *node, err error) {
|
||||
if len(receivers) == 0 {
|
||||
@@ -388,7 +388,7 @@ func createPartialCongestionTree(
|
||||
|
||||
nodes := make([]*node, 0, len(receivers))
|
||||
for _, r := range receivers {
|
||||
pubkeyBytes, err := hex.DecodeString(r.Pubkey)
|
||||
pubkeyBytes, err := hex.DecodeString(r.PubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -399,7 +399,7 @@ func createPartialCongestionTree(
|
||||
}
|
||||
|
||||
leafNode := &node{
|
||||
sweepKey: aspPubkey,
|
||||
sweepKey: serverPubkey,
|
||||
receivers: []vtxoOutput{{pubkey, r.Amount}},
|
||||
asset: asset,
|
||||
feeSats: feeSatsPerNode,
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
// Node is a struct embedding the transaction and the parent txid of a congestion tree node
|
||||
// Node is a struct embedding the transaction and the parent txid of a vtxo tree node
|
||||
type Node struct {
|
||||
Txid string
|
||||
Tx string
|
||||
@@ -14,28 +14,28 @@ type Node struct {
|
||||
|
||||
var (
|
||||
ErrParentNotFound = errors.New("parent not found")
|
||||
ErrLeafNotFound = errors.New("leaf not found in congestion tree")
|
||||
ErrLeafNotFound = errors.New("leaf not found in vtxo tree")
|
||||
)
|
||||
|
||||
// CongestionTree is reprensented as a matrix of TreeNode struct
|
||||
// VtxoTree is reprensented as a matrix of TreeNode struct
|
||||
// the first level of the matrix is the root of the tree
|
||||
type CongestionTree [][]Node
|
||||
type VtxoTree [][]Node
|
||||
|
||||
// Root returns the root node of the congestion tree
|
||||
func (c CongestionTree) Root() (Node, error) {
|
||||
// Root returns the root node of the vtxo tree
|
||||
func (c VtxoTree) Root() (Node, error) {
|
||||
if len(c) <= 0 {
|
||||
return Node{}, errors.New("empty congestion tree")
|
||||
return Node{}, errors.New("empty vtxo tree")
|
||||
}
|
||||
|
||||
if len(c[0]) <= 0 {
|
||||
return Node{}, errors.New("empty congestion tree")
|
||||
return Node{}, errors.New("empty vtxo tree")
|
||||
}
|
||||
|
||||
return c[0][0], nil
|
||||
}
|
||||
|
||||
// Leaves returns the leaves of the congestion tree (the vtxos txs)
|
||||
func (c CongestionTree) Leaves() []Node {
|
||||
// Leaves returns the leaves of the vtxo tree
|
||||
func (c VtxoTree) Leaves() []Node {
|
||||
leaves := c[len(c)-1]
|
||||
for _, level := range c[:len(c)-1] {
|
||||
for _, node := range level {
|
||||
@@ -49,7 +49,7 @@ func (c CongestionTree) Leaves() []Node {
|
||||
}
|
||||
|
||||
// Children returns all the nodes that have the given node as parent
|
||||
func (c CongestionTree) Children(nodeTxid string) []Node {
|
||||
func (c VtxoTree) Children(nodeTxid string) []Node {
|
||||
var children []Node
|
||||
for _, level := range c {
|
||||
for _, node := range level {
|
||||
@@ -62,8 +62,8 @@ func (c CongestionTree) Children(nodeTxid string) []Node {
|
||||
return children
|
||||
}
|
||||
|
||||
// NumberOfNodes returns the total number of pset in the congestion tree
|
||||
func (c CongestionTree) NumberOfNodes() int {
|
||||
// NumberOfNodes returns the total number of pset in the vtxo tree
|
||||
func (c VtxoTree) NumberOfNodes() int {
|
||||
var count int
|
||||
for _, level := range c {
|
||||
count += len(level)
|
||||
@@ -71,8 +71,8 @@ func (c CongestionTree) NumberOfNodes() int {
|
||||
return count
|
||||
}
|
||||
|
||||
// Branch returns the branch of the given vtxo txid from root to leaf in the order of the congestion tree
|
||||
func (c CongestionTree) Branch(vtxoTxid string) ([]Node, error) {
|
||||
// Branch returns the branch of the given vtxo txid from root to leaf in the order of the vtxo tree
|
||||
func (c VtxoTree) Branch(vtxoTxid string) ([]Node, error) {
|
||||
branch := make([]Node, 0)
|
||||
|
||||
leaves := c.Leaves()
|
||||
@@ -102,7 +102,7 @@ func (c CongestionTree) Branch(vtxoTxid string) ([]Node, error) {
|
||||
return branch, nil
|
||||
}
|
||||
|
||||
func (n Node) findParent(tree CongestionTree) (Node, error) {
|
||||
func (n Node) findParent(tree VtxoTree) (Node, error) {
|
||||
for _, level := range tree {
|
||||
for _, node := range level {
|
||||
if node.Txid == n.ParentTxid {
|
||||
|
||||
@@ -8,13 +8,9 @@ import (
|
||||
)
|
||||
|
||||
func BuildForfeitTxs(
|
||||
connectorTx *psetv2.Pset,
|
||||
vtxoInput psetv2.InputArgs,
|
||||
vtxoAmount,
|
||||
connectorAmount,
|
||||
feeAmount uint64,
|
||||
vtxoScript,
|
||||
aspScript []byte,
|
||||
connectorTx *psetv2.Pset, vtxoInput psetv2.InputArgs,
|
||||
vtxoAmount, connectorAmount, feeAmount uint64,
|
||||
vtxoScript, serverScript []byte,
|
||||
) (forfeitTxs []*psetv2.Pset, err error) {
|
||||
connectors, prevouts := getConnectorInputs(connectorTx, connectorAmount)
|
||||
|
||||
@@ -63,7 +59,7 @@ func BuildForfeitTxs(
|
||||
{
|
||||
Asset: asset,
|
||||
Amount: vtxoAmount + connectorAmount - feeAmount,
|
||||
Script: aspScript,
|
||||
Script: serverScript,
|
||||
},
|
||||
{
|
||||
Asset: asset,
|
||||
|
||||
@@ -281,10 +281,10 @@ func (f *MultisigClosure) Witness(controlBlock []byte, signatures map[string][]b
|
||||
|
||||
// Add signatures in the reverse order as public keys
|
||||
for i := len(f.PubKeys) - 1; i >= 0; i-- {
|
||||
pubKey := f.PubKeys[i]
|
||||
sig, ok := signatures[hex.EncodeToString(schnorr.SerializePubKey(pubKey))]
|
||||
pubkey := f.PubKeys[i]
|
||||
sig, ok := signatures[hex.EncodeToString(schnorr.SerializePubKey(pubkey))]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("missing signature for public key %x", schnorr.SerializePubKey(pubKey))
|
||||
return nil, fmt.Errorf("missing signature for public key %x", schnorr.SerializePubKey(pubkey))
|
||||
}
|
||||
witness = append(witness, sig)
|
||||
}
|
||||
|
||||
@@ -36,17 +36,17 @@ func TestRoundTripCSV(t *testing.T) {
|
||||
|
||||
func TestMultisigClosure(t *testing.T) {
|
||||
// Generate some test keys
|
||||
privKey1, err := secp256k1.GeneratePrivateKey()
|
||||
prvkey1, err := secp256k1.GeneratePrivateKey()
|
||||
require.NoError(t, err)
|
||||
pubKey1 := privKey1.PubKey()
|
||||
pubkey1 := prvkey1.PubKey()
|
||||
|
||||
privKey2, err := secp256k1.GeneratePrivateKey()
|
||||
prvkey2, err := secp256k1.GeneratePrivateKey()
|
||||
require.NoError(t, err)
|
||||
pubKey2 := privKey2.PubKey()
|
||||
pubkey2 := prvkey2.PubKey()
|
||||
|
||||
t.Run("valid 2-of-2 multisig", func(t *testing.T) {
|
||||
closure := &tree.MultisigClosure{
|
||||
PubKeys: []*secp256k1.PublicKey{pubKey1, pubKey2},
|
||||
PubKeys: []*secp256k1.PublicKey{pubkey1, pubkey2},
|
||||
}
|
||||
|
||||
// Generate script
|
||||
@@ -62,18 +62,18 @@ func TestMultisigClosure(t *testing.T) {
|
||||
|
||||
// Compare serialized pubkeys
|
||||
require.Equal(t,
|
||||
schnorr.SerializePubKey(pubKey1),
|
||||
schnorr.SerializePubKey(pubkey1),
|
||||
schnorr.SerializePubKey(decodedClosure.PubKeys[0]),
|
||||
)
|
||||
require.Equal(t,
|
||||
schnorr.SerializePubKey(pubKey2),
|
||||
schnorr.SerializePubKey(pubkey2),
|
||||
schnorr.SerializePubKey(decodedClosure.PubKeys[1]),
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("valid single key multisig", func(t *testing.T) {
|
||||
closure := &tree.MultisigClosure{
|
||||
PubKeys: []*secp256k1.PublicKey{pubKey1},
|
||||
PubKeys: []*secp256k1.PublicKey{pubkey1},
|
||||
}
|
||||
|
||||
script, err := closure.Script()
|
||||
@@ -87,7 +87,7 @@ func TestMultisigClosure(t *testing.T) {
|
||||
|
||||
// Compare serialized pubkey
|
||||
require.Equal(t,
|
||||
schnorr.SerializePubKey(pubKey1),
|
||||
schnorr.SerializePubKey(pubkey1),
|
||||
schnorr.SerializePubKey(decodedClosure.PubKeys[0]),
|
||||
)
|
||||
})
|
||||
@@ -110,9 +110,9 @@ func TestMultisigClosure(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("invalid script - missing checksig", func(t *testing.T) {
|
||||
pubKeyBytes := schnorr.SerializePubKey(pubKey1)
|
||||
pubkeyBytes := schnorr.SerializePubKey(pubkey1)
|
||||
script := []byte{txscript.OP_DATA_32}
|
||||
script = append(script, pubKeyBytes...)
|
||||
script = append(script, pubkeyBytes...)
|
||||
// Missing OP_CHECKSIG
|
||||
|
||||
closure := &tree.MultisigClosure{}
|
||||
@@ -122,9 +122,9 @@ func TestMultisigClosure(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("invalid script - extra data after checksig", func(t *testing.T) {
|
||||
pubKeyBytes := schnorr.SerializePubKey(pubKey1)
|
||||
pubkeyBytes := schnorr.SerializePubKey(pubkey1)
|
||||
script := []byte{txscript.OP_DATA_32}
|
||||
script = append(script, pubKeyBytes...)
|
||||
script = append(script, pubkeyBytes...)
|
||||
script = append(script, txscript.OP_CHECKSIG)
|
||||
script = append(script, 0x00) // Extra unwanted byte
|
||||
|
||||
@@ -136,7 +136,7 @@ func TestMultisigClosure(t *testing.T) {
|
||||
|
||||
t.Run("witness size", func(t *testing.T) {
|
||||
closure := &tree.MultisigClosure{
|
||||
PubKeys: []*secp256k1.PublicKey{pubKey1, pubKey2},
|
||||
PubKeys: []*secp256k1.PublicKey{pubkey1, pubkey2},
|
||||
}
|
||||
|
||||
require.Equal(t, 128, closure.WitnessSize()) // 64 * 2 bytes
|
||||
@@ -144,15 +144,15 @@ func TestMultisigClosure(t *testing.T) {
|
||||
|
||||
t.Run("valid 12-of-12 multisig", func(t *testing.T) {
|
||||
// Generate 12 keys
|
||||
pubKeys := make([]*secp256k1.PublicKey, 12)
|
||||
pubkeys := make([]*secp256k1.PublicKey, 12)
|
||||
for i := 0; i < 12; i++ {
|
||||
privKey, err := secp256k1.GeneratePrivateKey()
|
||||
prvkey, err := secp256k1.GeneratePrivateKey()
|
||||
require.NoError(t, err)
|
||||
pubKeys[i] = privKey.PubKey()
|
||||
pubkeys[i] = prvkey.PubKey()
|
||||
}
|
||||
|
||||
closure := &tree.MultisigClosure{
|
||||
PubKeys: pubKeys,
|
||||
PubKeys: pubkeys,
|
||||
}
|
||||
|
||||
// Generate script
|
||||
@@ -169,7 +169,7 @@ func TestMultisigClosure(t *testing.T) {
|
||||
// Compare all serialized pubkeys
|
||||
for i := 0; i < 12; i++ {
|
||||
require.Equal(t,
|
||||
schnorr.SerializePubKey(pubKeys[i]),
|
||||
schnorr.SerializePubKey(pubkeys[i]),
|
||||
schnorr.SerializePubKey(decodedClosure.PubKeys[i]),
|
||||
)
|
||||
}
|
||||
@@ -181,18 +181,18 @@ func TestMultisigClosure(t *testing.T) {
|
||||
|
||||
func TestCSVSigClosure(t *testing.T) {
|
||||
// Generate test keys
|
||||
privKey1, err := secp256k1.GeneratePrivateKey()
|
||||
prvkey1, err := secp256k1.GeneratePrivateKey()
|
||||
require.NoError(t, err)
|
||||
pubKey1 := privKey1.PubKey()
|
||||
pubkey1 := prvkey1.PubKey()
|
||||
|
||||
privKey2, err := secp256k1.GeneratePrivateKey()
|
||||
prvkey2, err := secp256k1.GeneratePrivateKey()
|
||||
require.NoError(t, err)
|
||||
pubKey2 := privKey2.PubKey()
|
||||
pubkey2 := prvkey2.PubKey()
|
||||
|
||||
t.Run("valid single key CSV", func(t *testing.T) {
|
||||
csvSig := &tree.CSVSigClosure{
|
||||
MultisigClosure: tree.MultisigClosure{
|
||||
PubKeys: []*secp256k1.PublicKey{pubKey1},
|
||||
PubKeys: []*secp256k1.PublicKey{pubkey1},
|
||||
},
|
||||
Seconds: 1024,
|
||||
}
|
||||
@@ -207,7 +207,7 @@ func TestCSVSigClosure(t *testing.T) {
|
||||
require.Equal(t, uint32(1024), uint32(decodedCSV.Seconds))
|
||||
require.Equal(t, 1, len(decodedCSV.PubKeys))
|
||||
require.Equal(t,
|
||||
schnorr.SerializePubKey(pubKey1),
|
||||
schnorr.SerializePubKey(pubkey1),
|
||||
schnorr.SerializePubKey(decodedCSV.PubKeys[0]),
|
||||
)
|
||||
})
|
||||
@@ -215,7 +215,7 @@ func TestCSVSigClosure(t *testing.T) {
|
||||
t.Run("valid 2-of-2 CSV", func(t *testing.T) {
|
||||
csvSig := &tree.CSVSigClosure{
|
||||
MultisigClosure: tree.MultisigClosure{
|
||||
PubKeys: []*secp256k1.PublicKey{pubKey1, pubKey2},
|
||||
PubKeys: []*secp256k1.PublicKey{pubkey1, pubkey2},
|
||||
},
|
||||
Seconds: 2016, // ~2 weeks
|
||||
}
|
||||
@@ -230,11 +230,11 @@ func TestCSVSigClosure(t *testing.T) {
|
||||
require.Equal(t, uint32(2016), uint32(decodedCSV.Seconds))
|
||||
require.Equal(t, 2, len(decodedCSV.PubKeys))
|
||||
require.Equal(t,
|
||||
schnorr.SerializePubKey(pubKey1),
|
||||
schnorr.SerializePubKey(pubkey1),
|
||||
schnorr.SerializePubKey(decodedCSV.PubKeys[0]),
|
||||
)
|
||||
require.Equal(t,
|
||||
schnorr.SerializePubKey(pubKey2),
|
||||
schnorr.SerializePubKey(pubkey2),
|
||||
schnorr.SerializePubKey(decodedCSV.PubKeys[1]),
|
||||
)
|
||||
})
|
||||
@@ -248,9 +248,9 @@ func TestCSVSigClosure(t *testing.T) {
|
||||
|
||||
t.Run("invalid CSV value", func(t *testing.T) {
|
||||
// Create a script with invalid CSV value
|
||||
pubKeyBytes := schnorr.SerializePubKey(pubKey1)
|
||||
pubkeyBytes := schnorr.SerializePubKey(pubkey1)
|
||||
script := []byte{txscript.OP_DATA_32}
|
||||
script = append(script, pubKeyBytes...)
|
||||
script = append(script, pubkeyBytes...)
|
||||
script = append(script, txscript.OP_CHECKSIG)
|
||||
script = append(script, 0xFF) // Invalid CSV value
|
||||
|
||||
@@ -263,7 +263,7 @@ func TestCSVSigClosure(t *testing.T) {
|
||||
t.Run("witness size", func(t *testing.T) {
|
||||
csvSig := &tree.CSVSigClosure{
|
||||
MultisigClosure: tree.MultisigClosure{
|
||||
PubKeys: []*secp256k1.PublicKey{pubKey1, pubKey2},
|
||||
PubKeys: []*secp256k1.PublicKey{pubkey1, pubkey2},
|
||||
},
|
||||
Seconds: 1024,
|
||||
}
|
||||
@@ -274,7 +274,7 @@ func TestCSVSigClosure(t *testing.T) {
|
||||
t.Run("max timelock", func(t *testing.T) {
|
||||
csvSig := &tree.CSVSigClosure{
|
||||
MultisigClosure: tree.MultisigClosure{
|
||||
PubKeys: []*secp256k1.PublicKey{pubKey1},
|
||||
PubKeys: []*secp256k1.PublicKey{pubkey1},
|
||||
},
|
||||
Seconds: 65535, // Maximum allowed value
|
||||
}
|
||||
@@ -438,22 +438,22 @@ func TestCSVSigClosureWitness(t *testing.T) {
|
||||
|
||||
func TestDecodeChecksigAdd(t *testing.T) {
|
||||
// Generate some test public keys
|
||||
pubKey1, err := secp256k1.GeneratePrivateKey()
|
||||
pubkey1, err := secp256k1.GeneratePrivateKey()
|
||||
require.NoError(t, err)
|
||||
pubKey2, err := secp256k1.GeneratePrivateKey()
|
||||
pubkey2, err := secp256k1.GeneratePrivateKey()
|
||||
require.NoError(t, err)
|
||||
pubKey3, err := secp256k1.GeneratePrivateKey()
|
||||
pubkey3, err := secp256k1.GeneratePrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
pubKeys := []*secp256k1.PublicKey{pubKey1.PubKey(), pubKey2.PubKey(), pubKey3.PubKey()}
|
||||
pubkeys := []*secp256k1.PublicKey{pubkey1.PubKey(), pubkey2.PubKey(), pubkey3.PubKey()}
|
||||
|
||||
// Create a script for 3-of-3 multisig using CHECKSIGADD
|
||||
scriptBuilder := txscript.NewScriptBuilder().
|
||||
AddData(schnorr.SerializePubKey(pubKeys[0])).
|
||||
AddData(schnorr.SerializePubKey(pubkeys[0])).
|
||||
AddOp(txscript.OP_CHECKSIG).
|
||||
AddData(schnorr.SerializePubKey(pubKeys[1])).
|
||||
AddData(schnorr.SerializePubKey(pubkeys[1])).
|
||||
AddOp(txscript.OP_CHECKSIGADD).
|
||||
AddData(schnorr.SerializePubKey(pubKeys[2])).
|
||||
AddData(schnorr.SerializePubKey(pubkeys[2])).
|
||||
AddOp(txscript.OP_CHECKSIGADD).
|
||||
AddInt64(3).
|
||||
AddOp(txscript.OP_EQUAL)
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"github.com/vulpemventures/go-elements/psetv2"
|
||||
)
|
||||
|
||||
type TreeFactory func(outpoint psetv2.InputArgs) (CongestionTree, error)
|
||||
type TreeFactory func(outpoint psetv2.InputArgs) (VtxoTree, error)
|
||||
|
||||
type VtxoLeaf struct {
|
||||
Pubkey string
|
||||
PubKey string
|
||||
Amount uint64
|
||||
}
|
||||
|
||||
@@ -13,37 +13,37 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidPoolTransaction = errors.New("invalid pool transaction")
|
||||
ErrInvalidPoolTransactionOutputs = errors.New("invalid number of outputs in pool transaction")
|
||||
ErrEmptyTree = errors.New("empty congestion tree")
|
||||
ErrInvalidRootLevel = errors.New("root level must have only one node")
|
||||
ErrNoLeaves = errors.New("no leaves in the tree")
|
||||
ErrNodeTransactionEmpty = errors.New("node transaction is empty")
|
||||
ErrNodeTxidEmpty = errors.New("node txid is empty")
|
||||
ErrNodeParentTxidEmpty = errors.New("node parent txid is empty")
|
||||
ErrNodeTxidDifferent = errors.New("node txid differs from node transaction")
|
||||
ErrNumberOfInputs = errors.New("node transaction should have only one input")
|
||||
ErrNumberOfOutputs = errors.New("node transaction should have only three or two outputs")
|
||||
ErrParentTxidInput = errors.New("parent txid should be the input of the node transaction")
|
||||
ErrNumberOfChildren = errors.New("node branch transaction should have two children")
|
||||
ErrLeafChildren = errors.New("leaf node should have max 1 child")
|
||||
ErrInvalidChildTxid = errors.New("invalid child txid")
|
||||
ErrNumberOfTapscripts = errors.New("input should have two tapscripts leaves")
|
||||
ErrInternalKey = errors.New("taproot internal key is not unspendable")
|
||||
ErrInvalidTaprootScript = errors.New("invalid taproot script")
|
||||
ErrInvalidTaprootScriptLen = errors.New("invalid taproot script length (expected 32 bytes)")
|
||||
ErrInvalidLeafTaprootScript = errors.New("invalid leaf taproot script")
|
||||
ErrInvalidAmount = errors.New("children amount is different from parent amount")
|
||||
ErrInvalidRoundTx = fmt.Errorf("invalid round transaction")
|
||||
ErrInvalidRoundTxOutputs = fmt.Errorf("invalid number of outputs in round transaction")
|
||||
ErrEmptyTree = fmt.Errorf("empty vtxo tree")
|
||||
ErrInvalidRootLevel = fmt.Errorf("root level must have only one node")
|
||||
ErrNoLeaves = fmt.Errorf("no leaves in the tree")
|
||||
ErrNodeTxEmpty = fmt.Errorf("node transaction is empty")
|
||||
ErrNodeTxidEmpty = fmt.Errorf("node txid is empty")
|
||||
ErrNodeParentTxidEmpty = fmt.Errorf("node parent txid is empty")
|
||||
ErrNodeTxidDifferent = fmt.Errorf("node txid differs from node transaction")
|
||||
ErrNumberOfInputs = fmt.Errorf("node transaction should have only one input")
|
||||
ErrNumberOfOutputs = fmt.Errorf("node transaction should have only three or two outputs")
|
||||
ErrParentTxidInput = fmt.Errorf("parent txid should be the input of the node transaction")
|
||||
ErrNumberOfChildren = fmt.Errorf("node branch transaction should have two children")
|
||||
ErrLeafChildren = fmt.Errorf("leaf node should have max 1 child")
|
||||
ErrInvalidChildTxid = fmt.Errorf("invalid child txid")
|
||||
ErrNumberOfTapscripts = fmt.Errorf("input should have 1 tapscript leaf")
|
||||
ErrInternalKey = fmt.Errorf("invalid taproot internal key")
|
||||
ErrInvalidTaprootScript = fmt.Errorf("invalid taproot script")
|
||||
ErrInvalidTaprootScriptLen = fmt.Errorf("invalid taproot script length (expected 32 bytes)")
|
||||
ErrInvalidLeafTaprootScript = fmt.Errorf("invalid leaf taproot script")
|
||||
ErrInvalidAmount = fmt.Errorf("children amount is different from parent amount")
|
||||
ErrInvalidAsset = errors.New("invalid output asset")
|
||||
ErrInvalidSweepSequence = errors.New("invalid sweep sequence")
|
||||
ErrInvalidASP = errors.New("invalid ASP")
|
||||
ErrMissingFeeOutput = errors.New("missing fee output")
|
||||
ErrInvalidLeftOutput = errors.New("invalid left output")
|
||||
ErrInvalidRightOutput = errors.New("invalid right output")
|
||||
ErrMissingSweepTapscript = errors.New("missing sweep tapscript")
|
||||
ErrInvalidSweepSequence = fmt.Errorf("invalid sweep sequence")
|
||||
ErrInvalidServer = fmt.Errorf("invalid server")
|
||||
ErrMissingFeeOutput = fmt.Errorf("missing fee output")
|
||||
ErrInvalidLeftOutput = fmt.Errorf("invalid left output")
|
||||
ErrInvalidRightOutput = fmt.Errorf("invalid right output")
|
||||
ErrMissingSweepTapscript = fmt.Errorf("missing sweep tapscript")
|
||||
ErrMissingBranchTapscript = errors.New("missing branch tapscript")
|
||||
ErrInvalidLeaf = errors.New("leaf node shouldn't have children")
|
||||
ErrWrongPoolTxID = errors.New("root input should be the pool tx outpoint")
|
||||
ErrInvalidLeaf = fmt.Errorf("leaf node shouldn't have children")
|
||||
ErrWrongRoundTxid = fmt.Errorf("the input of the tree root is not the round tx's shared output")
|
||||
)
|
||||
|
||||
// 0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0
|
||||
@@ -61,36 +61,36 @@ func UnspendableKey() *secp256k1.PublicKey {
|
||||
return key
|
||||
}
|
||||
|
||||
// ValidateCongestionTree checks if the given congestion tree is valid
|
||||
// poolTxID & poolTxIndex & poolTxAmount are used to validate the root input outpoint
|
||||
// aspPublicKey & roundLifetime are used to validate the sweep tapscript leaves
|
||||
// ValidateVtxoTree checks if the given vtxo tree is valid
|
||||
// roundTxid & roundTxIndex & roundTxAmount are used to validate the root input outpoint
|
||||
// serverPubkey & roundLifetime are used to validate the sweep tapscript leaves
|
||||
// besides that, the function validates:
|
||||
// - the number of nodes
|
||||
// - the number of leaves
|
||||
// - children coherence with parent
|
||||
// - every control block and taproot output scripts
|
||||
// - input and output amounts
|
||||
func ValidateCongestionTree(
|
||||
tree CongestionTree, poolTx string, aspPublicKey *secp256k1.PublicKey,
|
||||
func ValidateVtxoTree(
|
||||
tree VtxoTree, roundTx string, serverPubkey *secp256k1.PublicKey,
|
||||
roundLifetime int64,
|
||||
) error {
|
||||
poolTransaction, err := psetv2.NewPsetFromBase64(poolTx)
|
||||
roundTransaction, err := psetv2.NewPsetFromBase64(roundTx)
|
||||
if err != nil {
|
||||
return ErrInvalidPoolTransaction
|
||||
return ErrInvalidRoundTx
|
||||
}
|
||||
|
||||
if len(poolTransaction.Outputs) < sharedOutputIndex+1 {
|
||||
return ErrInvalidPoolTransactionOutputs
|
||||
if len(roundTransaction.Outputs) < sharedOutputIndex+1 {
|
||||
return ErrInvalidRoundTxOutputs
|
||||
}
|
||||
|
||||
poolTxAmount := poolTransaction.Outputs[sharedOutputIndex].Value
|
||||
roundTxAmount := roundTransaction.Outputs[sharedOutputIndex].Value
|
||||
|
||||
utx, err := poolTransaction.UnsignedTx()
|
||||
utx, err := roundTransaction.UnsignedTx()
|
||||
if err != nil {
|
||||
return ErrInvalidPoolTransaction
|
||||
return ErrInvalidRoundTx
|
||||
}
|
||||
|
||||
poolTxID := utx.TxHash().String()
|
||||
roundTxid := utx.TxHash().String()
|
||||
|
||||
nbNodes := tree.NumberOfNodes()
|
||||
if nbNodes == 0 {
|
||||
@@ -101,7 +101,7 @@ func ValidateCongestionTree(
|
||||
return ErrInvalidRootLevel
|
||||
}
|
||||
|
||||
// check that root input is connected to the pool tx
|
||||
// check that root input is connected to the round tx
|
||||
rootPsetB64 := tree[0][0].Tx
|
||||
rootPset, err := psetv2.NewPsetFromBase64(rootPsetB64)
|
||||
if err != nil {
|
||||
@@ -113,9 +113,9 @@ func ValidateCongestionTree(
|
||||
}
|
||||
|
||||
rootInput := rootPset.Inputs[0]
|
||||
if chainhash.Hash(rootInput.PreviousTxid).String() != poolTxID ||
|
||||
if chainhash.Hash(rootInput.PreviousTxid).String() != roundTxid ||
|
||||
rootInput.PreviousTxIndex != sharedOutputIndex {
|
||||
return ErrWrongPoolTxID
|
||||
return ErrWrongRoundTxid
|
||||
}
|
||||
|
||||
sumRootValue := uint64(0)
|
||||
@@ -123,7 +123,7 @@ func ValidateCongestionTree(
|
||||
sumRootValue += output.Value
|
||||
}
|
||||
|
||||
if sumRootValue != poolTxAmount {
|
||||
if sumRootValue != roundTxAmount {
|
||||
return ErrInvalidAmount
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ func ValidateCongestionTree(
|
||||
for _, level := range tree {
|
||||
for _, node := range level {
|
||||
if err := validateNodeTransaction(
|
||||
node, tree, UnspendableKey(), aspPublicKey, roundLifetime,
|
||||
node, tree, UnspendableKey(), serverPubkey, roundLifetime,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -146,12 +146,12 @@ func ValidateCongestionTree(
|
||||
}
|
||||
|
||||
func validateNodeTransaction(
|
||||
node Node, tree CongestionTree,
|
||||
expectedInternalKey, expectedPublicKeyASP *secp256k1.PublicKey,
|
||||
node Node, tree VtxoTree,
|
||||
expectedInternalKey, expectedServerPubkey *secp256k1.PublicKey,
|
||||
expectedSequence int64,
|
||||
) error {
|
||||
if node.Tx == "" {
|
||||
return ErrNodeTransactionEmpty
|
||||
return ErrNodeTxEmpty
|
||||
}
|
||||
|
||||
if node.Txid == "" {
|
||||
@@ -238,21 +238,21 @@ func validateNodeTransaction(
|
||||
|
||||
switch c := closure.(type) {
|
||||
case *CSVSigClosure:
|
||||
isASP := len(c.MultisigClosure.PubKeys) == 1 && bytes.Equal(
|
||||
isServer := len(c.MultisigClosure.PubKeys) == 1 && bytes.Equal(
|
||||
schnorr.SerializePubKey(c.MultisigClosure.PubKeys[0]),
|
||||
schnorr.SerializePubKey(expectedPublicKeyASP),
|
||||
schnorr.SerializePubKey(expectedServerPubkey),
|
||||
)
|
||||
isSweepDelay := int64(c.Seconds) == expectedSequence
|
||||
|
||||
if isASP && !isSweepDelay {
|
||||
if isServer && !isSweepDelay {
|
||||
return ErrInvalidSweepSequence
|
||||
}
|
||||
|
||||
if isSweepDelay && !isASP {
|
||||
return ErrInvalidASP
|
||||
if isSweepDelay && !isServer {
|
||||
return ErrInvalidServer
|
||||
}
|
||||
|
||||
if isASP && isSweepDelay {
|
||||
if isServer && isSweepDelay {
|
||||
sweepLeafFound = true
|
||||
}
|
||||
case *UnrollClosure:
|
||||
|
||||
@@ -26,14 +26,14 @@ func ParseVtxoScript(scripts []string) (VtxoScript, error) {
|
||||
return v, err
|
||||
}
|
||||
|
||||
func NewDefaultVtxoScript(owner, asp *secp256k1.PublicKey, exitDelay uint) *TapscriptsVtxoScript {
|
||||
func NewDefaultVtxoScript(owner, server *secp256k1.PublicKey, exitDelay uint) *TapscriptsVtxoScript {
|
||||
return &TapscriptsVtxoScript{
|
||||
[]Closure{
|
||||
&CSVSigClosure{
|
||||
MultisigClosure: MultisigClosure{PubKeys: []*secp256k1.PublicKey{owner}},
|
||||
Seconds: exitDelay,
|
||||
},
|
||||
&MultisigClosure{PubKeys: []*secp256k1.PublicKey{owner, asp}},
|
||||
&MultisigClosure{PubKeys: []*secp256k1.PublicKey{owner, server}},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -73,19 +73,19 @@ func (v *TapscriptsVtxoScript) Decode(scripts []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *TapscriptsVtxoScript) Validate(asp *secp256k1.PublicKey, minExitDelay uint) error {
|
||||
aspXonly := schnorr.SerializePubKey(asp)
|
||||
func (v *TapscriptsVtxoScript) Validate(server *secp256k1.PublicKey, minExitDelay uint) error {
|
||||
serverXonly := schnorr.SerializePubKey(server)
|
||||
for _, forfeit := range v.ForfeitClosures() {
|
||||
// must contain asp pubkey
|
||||
// must contain server pubkey
|
||||
found := false
|
||||
for _, pubkey := range forfeit.PubKeys {
|
||||
if bytes.Equal(schnorr.SerializePubKey(pubkey), aspXonly) {
|
||||
if bytes.Equal(schnorr.SerializePubKey(pubkey), serverXonly) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return fmt.Errorf("invalid forfeit closure, ASP pubkey not found")
|
||||
return fmt.Errorf("invalid forfeit closure, server pubkey not found")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ type TaprootTree interface {
|
||||
}
|
||||
|
||||
/*
|
||||
A vtxo script is defined as a taproot contract with at least 1 forfeit closure (User && ASP) and 1 exit closure (A after t).
|
||||
A vtxo script is defined as a taproot contract with at least 1 forfeit closure (User && Server) and 1 exit closure (A after t).
|
||||
It may also contain others closures implementing specific use cases.
|
||||
|
||||
VtxoScript abstracts the taproot complexity behind vtxo contracts.
|
||||
|
||||
@@ -24,7 +24,6 @@ type ArkClient interface {
|
||||
CollaborativeRedeem(
|
||||
ctx context.Context, addr string, amount uint64, withExpiryCoinselect bool,
|
||||
) (string, error)
|
||||
SendAsync(ctx context.Context, withExpiryCoinselect bool, receivers []Receiver) (string, error)
|
||||
Settle(ctx context.Context) (string, error)
|
||||
ListVtxos(ctx context.Context) (spendable, spent []client.Vtxo, err error)
|
||||
Dump(ctx context.Context) (seed string, err error)
|
||||
|
||||
@@ -57,7 +57,7 @@ type arkClient struct {
|
||||
wallet wallet.WalletService
|
||||
store types.Store
|
||||
explorer explorer.Explorer
|
||||
client client.ASPClient
|
||||
client client.TransportClient
|
||||
|
||||
txStreamCtxCancel context.CancelFunc
|
||||
}
|
||||
@@ -119,7 +119,7 @@ func (a *arkClient) initWithWallet(
|
||||
}
|
||||
|
||||
clientSvc, err := getClient(
|
||||
supportedClients, args.ClientType, args.AspUrl,
|
||||
supportedClients, args.ClientType, args.ServerUrl,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to setup client: %s", err)
|
||||
@@ -127,7 +127,7 @@ func (a *arkClient) initWithWallet(
|
||||
|
||||
info, err := clientSvc.GetInfo(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to connect to asp: %s", err)
|
||||
return fmt.Errorf("failed to connect to server: %s", err)
|
||||
}
|
||||
|
||||
explorerSvc, err := getExplorer(args.ExplorerURL, info.Network)
|
||||
@@ -137,18 +137,18 @@ func (a *arkClient) initWithWallet(
|
||||
|
||||
network := utils.NetworkFromString(info.Network)
|
||||
|
||||
buf, err := hex.DecodeString(info.Pubkey)
|
||||
buf, err := hex.DecodeString(info.PubKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse asp pubkey: %s", err)
|
||||
return fmt.Errorf("failed to parse server pubkey: %s", err)
|
||||
}
|
||||
aspPubkey, err := secp256k1.ParsePubKey(buf)
|
||||
serverPubkey, err := secp256k1.ParsePubKey(buf)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse asp pubkey: %s", err)
|
||||
return fmt.Errorf("failed to parse server pubkey: %s", err)
|
||||
}
|
||||
|
||||
storeData := types.Config{
|
||||
AspUrl: args.AspUrl,
|
||||
AspPubkey: aspPubkey,
|
||||
ServerUrl: args.ServerUrl,
|
||||
ServerPubKey: serverPubkey,
|
||||
WalletType: args.Wallet.GetType(),
|
||||
ClientType: args.ClientType,
|
||||
Network: network,
|
||||
@@ -186,7 +186,7 @@ func (a *arkClient) init(
|
||||
}
|
||||
|
||||
clientSvc, err := getClient(
|
||||
supportedClients, args.ClientType, args.AspUrl,
|
||||
supportedClients, args.ClientType, args.ServerUrl,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to setup client: %s", err)
|
||||
@@ -194,7 +194,7 @@ func (a *arkClient) init(
|
||||
|
||||
info, err := clientSvc.GetInfo(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to connect to asp: %s", err)
|
||||
return fmt.Errorf("failed to connect to server: %s", err)
|
||||
}
|
||||
|
||||
explorerSvc, err := getExplorer(args.ExplorerURL, info.Network)
|
||||
@@ -204,18 +204,18 @@ func (a *arkClient) init(
|
||||
|
||||
network := utils.NetworkFromString(info.Network)
|
||||
|
||||
buf, err := hex.DecodeString(info.Pubkey)
|
||||
buf, err := hex.DecodeString(info.PubKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse asp pubkey: %s", err)
|
||||
return fmt.Errorf("failed to parse server pubkey: %s", err)
|
||||
}
|
||||
aspPubkey, err := secp256k1.ParsePubKey(buf)
|
||||
serverPubkey, err := secp256k1.ParsePubKey(buf)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse asp pubkey: %s", err)
|
||||
return fmt.Errorf("failed to parse server pubkey: %s", err)
|
||||
}
|
||||
|
||||
cfgData := types.Config{
|
||||
AspUrl: args.AspUrl,
|
||||
AspPubkey: aspPubkey,
|
||||
ServerUrl: args.ServerUrl,
|
||||
ServerPubKey: serverPubkey,
|
||||
WalletType: args.WalletType,
|
||||
ClientType: args.ClientType,
|
||||
Network: network,
|
||||
@@ -252,17 +252,17 @@ func (a *arkClient) init(
|
||||
}
|
||||
|
||||
func (a *arkClient) ping(
|
||||
ctx context.Context, paymentID string,
|
||||
ctx context.Context, requestID string,
|
||||
) func() {
|
||||
ticker := time.NewTicker(5 * time.Second)
|
||||
|
||||
go func(t *time.Ticker) {
|
||||
if err := a.client.Ping(ctx, paymentID); err != nil {
|
||||
logrus.Warnf("failed to ping asp: %s", err)
|
||||
if err := a.client.Ping(ctx, requestID); err != nil {
|
||||
logrus.Warnf("failed to ping server: %s", err)
|
||||
}
|
||||
for range t.C {
|
||||
if err := a.client.Ping(ctx, paymentID); err != nil {
|
||||
logrus.Warnf("failed to ping asp: %s", err)
|
||||
if err := a.client.Ping(ctx, requestID); err != nil {
|
||||
logrus.Warnf("failed to ping server: %s", err)
|
||||
}
|
||||
}
|
||||
}(ticker)
|
||||
@@ -292,10 +292,10 @@ func (a *arkClient) ListVtxos(
|
||||
}
|
||||
|
||||
func getClient(
|
||||
supportedClients utils.SupportedType[utils.ClientFactory], clientType, aspUrl string,
|
||||
) (client.ASPClient, error) {
|
||||
supportedClients utils.SupportedType[utils.ClientFactory], clientType, serverUrl string,
|
||||
) (client.TransportClient, error) {
|
||||
factory := supportedClients[clientType]
|
||||
return factory(aspUrl)
|
||||
return factory(serverUrl)
|
||||
}
|
||||
|
||||
func getExplorer(explorerURL, network string) (explorer.Explorer, error) {
|
||||
|
||||
@@ -22,7 +22,7 @@ type RoundEvent interface {
|
||||
isRoundEvent()
|
||||
}
|
||||
|
||||
type ASPClient interface {
|
||||
type TransportClient interface {
|
||||
GetInfo(ctx context.Context) (*Info, error)
|
||||
RegisterInputsForNextRound(
|
||||
ctx context.Context, inputs []Input, ephemeralKey string,
|
||||
@@ -31,7 +31,7 @@ type ASPClient interface {
|
||||
ctx context.Context, notes []string, ephemeralKey string,
|
||||
) (string, error)
|
||||
RegisterOutputsForNextRound(
|
||||
ctx context.Context, paymentID string, outputs []Output,
|
||||
ctx context.Context, requestID string, outputs []Output,
|
||||
) error
|
||||
SubmitTreeNonces(
|
||||
ctx context.Context, roundID, cosignerPubkey string, nonces bitcointree.TreeNonces,
|
||||
@@ -43,9 +43,9 @@ type ASPClient interface {
|
||||
ctx context.Context, signedForfeitTxs []string, signedRoundTx string,
|
||||
) error
|
||||
GetEventStream(
|
||||
ctx context.Context, paymentID string,
|
||||
ctx context.Context, requestID string,
|
||||
) (<-chan RoundEventChannel, func(), error)
|
||||
Ping(ctx context.Context, paymentID string) error
|
||||
Ping(ctx context.Context, requestID string) error
|
||||
SubmitRedeemTx(
|
||||
ctx context.Context, signedRedeemTx string,
|
||||
) (string, error)
|
||||
@@ -59,7 +59,7 @@ type ASPClient interface {
|
||||
}
|
||||
|
||||
type Info struct {
|
||||
Pubkey string
|
||||
PubKey string
|
||||
RoundLifetime int64
|
||||
UnilateralExitDelay int64
|
||||
RoundInterval int64
|
||||
@@ -90,7 +90,7 @@ type Input struct {
|
||||
|
||||
type Vtxo struct {
|
||||
Outpoint
|
||||
Pubkey string
|
||||
PubKey string
|
||||
Amount uint64
|
||||
RoundTxid string
|
||||
ExpiresAt time.Time
|
||||
@@ -100,8 +100,8 @@ type Vtxo struct {
|
||||
SpentBy string
|
||||
}
|
||||
|
||||
func (v Vtxo) Address(asp *secp256k1.PublicKey, net common.Network) (string, error) {
|
||||
pubkeyBytes, err := hex.DecodeString(v.Pubkey)
|
||||
func (v Vtxo) Address(server *secp256k1.PublicKey, net common.Network) (string, error) {
|
||||
pubkeyBytes, err := hex.DecodeString(v.PubKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -113,7 +113,7 @@ func (v Vtxo) Address(asp *secp256k1.PublicKey, net common.Network) (string, err
|
||||
|
||||
a := &common.Address{
|
||||
HRP: net.Addr,
|
||||
Asp: asp,
|
||||
Server: server,
|
||||
VtxoTapKey: pubkey,
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ type Round struct {
|
||||
StartedAt *time.Time
|
||||
EndedAt *time.Time
|
||||
Tx string
|
||||
Tree tree.CongestionTree
|
||||
Tree tree.VtxoTree
|
||||
ForfeitTxs []string
|
||||
Connectors []string
|
||||
Stage RoundStage
|
||||
@@ -169,7 +169,7 @@ type Round struct {
|
||||
type RoundFinalizationEvent struct {
|
||||
ID string
|
||||
Tx string
|
||||
Tree tree.CongestionTree
|
||||
Tree tree.VtxoTree
|
||||
Connectors []string
|
||||
MinRelayFeeRate chainfee.SatPerKVByte
|
||||
}
|
||||
@@ -192,8 +192,8 @@ func (e RoundFailedEvent) isRoundEvent() {}
|
||||
|
||||
type RoundSigningStartedEvent struct {
|
||||
ID string
|
||||
UnsignedTree tree.CongestionTree
|
||||
CosignersPublicKeys []*secp256k1.PublicKey
|
||||
UnsignedTree tree.VtxoTree
|
||||
CosignersPubKeys []*secp256k1.PublicKey
|
||||
UnsignedRoundTx string
|
||||
}
|
||||
|
||||
|
||||
@@ -23,31 +23,31 @@ import (
|
||||
type grpcClient struct {
|
||||
conn *grpc.ClientConn
|
||||
svc arkv1.ArkServiceClient
|
||||
treeCache *utils.Cache[tree.CongestionTree]
|
||||
treeCache *utils.Cache[tree.VtxoTree]
|
||||
}
|
||||
|
||||
func NewClient(aspUrl string) (client.ASPClient, error) {
|
||||
if len(aspUrl) <= 0 {
|
||||
return nil, fmt.Errorf("missing asp url")
|
||||
func NewClient(serverUrl string) (client.TransportClient, error) {
|
||||
if len(serverUrl) <= 0 {
|
||||
return nil, fmt.Errorf("missing server url")
|
||||
}
|
||||
|
||||
creds := insecure.NewCredentials()
|
||||
port := 80
|
||||
if strings.HasPrefix(aspUrl, "https://") {
|
||||
aspUrl = strings.TrimPrefix(aspUrl, "https://")
|
||||
if strings.HasPrefix(serverUrl, "https://") {
|
||||
serverUrl = strings.TrimPrefix(serverUrl, "https://")
|
||||
creds = credentials.NewTLS(nil)
|
||||
port = 443
|
||||
}
|
||||
if !strings.Contains(aspUrl, ":") {
|
||||
aspUrl = fmt.Sprintf("%s:%d", aspUrl, port)
|
||||
if !strings.Contains(serverUrl, ":") {
|
||||
serverUrl = fmt.Sprintf("%s:%d", serverUrl, port)
|
||||
}
|
||||
conn, err := grpc.NewClient(aspUrl, grpc.WithTransportCredentials(creds))
|
||||
conn, err := grpc.NewClient(serverUrl, grpc.WithTransportCredentials(creds))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
svc := arkv1.NewArkServiceClient(conn)
|
||||
treeCache := utils.NewCache[tree.CongestionTree]()
|
||||
treeCache := utils.NewCache[tree.VtxoTree]()
|
||||
|
||||
return &grpcClient{conn, svc, treeCache}, nil
|
||||
}
|
||||
@@ -59,7 +59,7 @@ func (a *grpcClient) GetInfo(ctx context.Context) (*client.Info, error) {
|
||||
return nil, err
|
||||
}
|
||||
return &client.Info{
|
||||
Pubkey: resp.GetPubkey(),
|
||||
PubKey: resp.GetPubkey(),
|
||||
RoundLifetime: resp.GetRoundLifetime(),
|
||||
UnilateralExitDelay: resp.GetUnilateralExitDelay(),
|
||||
RoundInterval: resp.GetRoundInterval(),
|
||||
@@ -84,20 +84,20 @@ func (a *grpcClient) GetBoardingAddress(
|
||||
}
|
||||
|
||||
func (a *grpcClient) RegisterInputsForNextRound(
|
||||
ctx context.Context, inputs []client.Input, ephemeralPublicKey string,
|
||||
ctx context.Context, inputs []client.Input, ephemeralPubkey string,
|
||||
) (string, error) {
|
||||
req := &arkv1.RegisterInputsForNextRoundRequest{
|
||||
Inputs: ins(inputs).toProto(),
|
||||
}
|
||||
if len(ephemeralPublicKey) > 0 {
|
||||
req.EphemeralPubkey = &ephemeralPublicKey
|
||||
if len(ephemeralPubkey) > 0 {
|
||||
req.EphemeralPubkey = &ephemeralPubkey
|
||||
}
|
||||
|
||||
resp, err := a.svc.RegisterInputsForNextRound(ctx, req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return resp.GetId(), nil
|
||||
return resp.GetRequestId(), nil
|
||||
}
|
||||
|
||||
func (a *grpcClient) RegisterNotesForNextRound(
|
||||
@@ -113,14 +113,14 @@ func (a *grpcClient) RegisterNotesForNextRound(
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return resp.GetId(), nil
|
||||
return resp.GetRequestId(), nil
|
||||
}
|
||||
|
||||
func (a *grpcClient) RegisterOutputsForNextRound(
|
||||
ctx context.Context, paymentID string, outputs []client.Output,
|
||||
ctx context.Context, requestID string, outputs []client.Output,
|
||||
) error {
|
||||
req := &arkv1.RegisterOutputsForNextRoundRequest{
|
||||
Id: paymentID,
|
||||
RequestId: requestID,
|
||||
Outputs: outs(outputs).toProto(),
|
||||
}
|
||||
_, err := a.svc.RegisterOutputsForNextRound(ctx, req)
|
||||
@@ -191,7 +191,7 @@ func (a *grpcClient) SubmitSignedForfeitTxs(
|
||||
}
|
||||
|
||||
func (a *grpcClient) GetEventStream(
|
||||
ctx context.Context, paymentID string,
|
||||
ctx context.Context, requestID string,
|
||||
) (<-chan client.RoundEventChannel, func(), error) {
|
||||
req := &arkv1.GetEventStreamRequest{}
|
||||
stream, err := a.svc.GetEventStream(ctx, req)
|
||||
@@ -236,10 +236,10 @@ func (a *grpcClient) GetEventStream(
|
||||
}
|
||||
|
||||
func (a *grpcClient) Ping(
|
||||
ctx context.Context, paymentID string,
|
||||
ctx context.Context, requestID string,
|
||||
) error {
|
||||
req := &arkv1.PingRequest{
|
||||
PaymentId: paymentID,
|
||||
RequestId: requestID,
|
||||
}
|
||||
_, err := a.svc.Ping(ctx, req)
|
||||
return err
|
||||
|
||||
@@ -88,7 +88,7 @@ func (e event) toRoundEvent() (client.RoundEvent, error) {
|
||||
return client.RoundSigningStartedEvent{
|
||||
ID: ee.GetId(),
|
||||
UnsignedTree: treeFromProto{ee.GetUnsignedVtxoTree()}.parse(),
|
||||
CosignersPublicKeys: pubkeys,
|
||||
CosignersPubKeys: pubkeys,
|
||||
UnsignedRoundTx: ee.GetUnsignedRoundTx(),
|
||||
}, nil
|
||||
}
|
||||
@@ -123,7 +123,7 @@ func (v vtxo) toVtxo() client.Vtxo {
|
||||
IsPending: v.GetIsPending(),
|
||||
RedeemTx: v.GetRedeemTx(),
|
||||
SpentBy: v.GetSpentBy(),
|
||||
Pubkey: v.GetPubkey(),
|
||||
PubKey: v.GetPubkey(),
|
||||
CreatedAt: time.Unix(v.GetCreatedAt(), 0),
|
||||
}
|
||||
}
|
||||
@@ -166,8 +166,8 @@ type treeFromProto struct {
|
||||
*arkv1.Tree
|
||||
}
|
||||
|
||||
func (t treeFromProto) parse() tree.CongestionTree {
|
||||
levels := make(tree.CongestionTree, 0, len(t.GetLevels()))
|
||||
func (t treeFromProto) parse() tree.VtxoTree {
|
||||
levels := make(tree.VtxoTree, 0, len(t.GetLevels()))
|
||||
|
||||
for _, level := range t.GetLevels() {
|
||||
nodes := make([]tree.Node, 0, len(level.Nodes))
|
||||
|
||||
@@ -32,12 +32,12 @@ type restClient struct {
|
||||
serverURL string
|
||||
svc ark_service.ClientService
|
||||
requestTimeout time.Duration
|
||||
treeCache *utils.Cache[tree.CongestionTree]
|
||||
treeCache *utils.Cache[tree.VtxoTree]
|
||||
}
|
||||
|
||||
func NewClient(serverURL string) (client.ASPClient, error) {
|
||||
func NewClient(serverURL string) (client.TransportClient, error) {
|
||||
if len(serverURL) <= 0 {
|
||||
return nil, fmt.Errorf("missing asp url")
|
||||
return nil, fmt.Errorf("missing server url")
|
||||
}
|
||||
svc, err := newRestClient(serverURL)
|
||||
if err != nil {
|
||||
@@ -45,7 +45,7 @@ func NewClient(serverURL string) (client.ASPClient, error) {
|
||||
}
|
||||
// TODO: use twice the round interval.
|
||||
reqTimeout := 15 * time.Second
|
||||
treeCache := utils.NewCache[tree.CongestionTree]()
|
||||
treeCache := utils.NewCache[tree.VtxoTree]()
|
||||
|
||||
return &restClient{serverURL, svc, reqTimeout, treeCache}, nil
|
||||
}
|
||||
@@ -79,7 +79,7 @@ func (a *restClient) GetInfo(
|
||||
}
|
||||
|
||||
return &client.Info{
|
||||
Pubkey: resp.Payload.Pubkey,
|
||||
PubKey: resp.Payload.Pubkey,
|
||||
RoundLifetime: int64(roundLifetime),
|
||||
UnilateralExitDelay: int64(unilateralExitDelay),
|
||||
RoundInterval: int64(roundInterval),
|
||||
@@ -108,7 +108,7 @@ func (a *restClient) GetBoardingAddress(
|
||||
}
|
||||
|
||||
func (a *restClient) RegisterInputsForNextRound(
|
||||
ctx context.Context, inputs []client.Input, ephemeralPublicKey string,
|
||||
ctx context.Context, inputs []client.Input, ephemeralPubkey string,
|
||||
) (string, error) {
|
||||
ins := make([]*models.V1Input, 0, len(inputs))
|
||||
for _, i := range inputs {
|
||||
@@ -125,8 +125,8 @@ func (a *restClient) RegisterInputsForNextRound(
|
||||
body := &models.V1RegisterInputsForNextRoundRequest{
|
||||
Inputs: ins,
|
||||
}
|
||||
if len(ephemeralPublicKey) > 0 {
|
||||
body.EphemeralPubkey = ephemeralPublicKey
|
||||
if len(ephemeralPubkey) > 0 {
|
||||
body.EphemeralPubkey = ephemeralPubkey
|
||||
}
|
||||
|
||||
resp, err := a.svc.ArkServiceRegisterInputsForNextRound(
|
||||
@@ -136,7 +136,7 @@ func (a *restClient) RegisterInputsForNextRound(
|
||||
return "", err
|
||||
}
|
||||
|
||||
return resp.Payload.ID, nil
|
||||
return resp.Payload.RequestID, nil
|
||||
}
|
||||
|
||||
func (a *restClient) RegisterNotesForNextRound(
|
||||
@@ -154,11 +154,11 @@ func (a *restClient) RegisterNotesForNextRound(
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return resp.Payload.ID, nil
|
||||
return resp.Payload.RequestID, nil
|
||||
}
|
||||
|
||||
func (a *restClient) RegisterOutputsForNextRound(
|
||||
ctx context.Context, paymentID string, outputs []client.Output,
|
||||
ctx context.Context, requestID string, outputs []client.Output,
|
||||
) error {
|
||||
outs := make([]*models.V1Output, 0, len(outputs))
|
||||
for _, o := range outputs {
|
||||
@@ -168,7 +168,7 @@ func (a *restClient) RegisterOutputsForNextRound(
|
||||
})
|
||||
}
|
||||
body := models.V1RegisterOutputsForNextRoundRequest{
|
||||
ID: paymentID,
|
||||
RequestID: requestID,
|
||||
Outputs: outs,
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ func (a *restClient) SubmitSignedForfeitTxs(
|
||||
}
|
||||
|
||||
func (c *restClient) GetEventStream(
|
||||
ctx context.Context, paymentID string,
|
||||
ctx context.Context, requestID string,
|
||||
) (<-chan client.RoundEventChannel, func(), error) {
|
||||
eventsCh := make(chan client.RoundEventChannel)
|
||||
|
||||
@@ -356,7 +356,7 @@ func (c *restClient) GetEventStream(
|
||||
event = client.RoundSigningStartedEvent{
|
||||
ID: e.ID,
|
||||
UnsignedTree: treeFromProto{e.UnsignedVtxoTree}.parse(),
|
||||
CosignersPublicKeys: pubkeys,
|
||||
CosignersPubKeys: pubkeys,
|
||||
UnsignedRoundTx: e.UnsignedRoundTx,
|
||||
}
|
||||
case resp.Result.RoundSigningNoncesGenerated != nil:
|
||||
@@ -384,10 +384,10 @@ func (c *restClient) GetEventStream(
|
||||
}
|
||||
|
||||
func (a *restClient) Ping(
|
||||
ctx context.Context, paymentID string,
|
||||
ctx context.Context, requestID string,
|
||||
) error {
|
||||
r := ark_service.NewArkServicePingParams()
|
||||
r.SetPaymentID(paymentID)
|
||||
r.SetRequestID(requestID)
|
||||
_, err := a.svc.ArkServicePing(r)
|
||||
return err
|
||||
}
|
||||
@@ -573,8 +573,8 @@ type treeFromProto struct {
|
||||
*models.V1Tree
|
||||
}
|
||||
|
||||
func (t treeFromProto) parse() tree.CongestionTree {
|
||||
congestionTree := make(tree.CongestionTree, 0, len(t.Levels))
|
||||
func (t treeFromProto) parse() tree.VtxoTree {
|
||||
vtxoTree := make(tree.VtxoTree, 0, len(t.Levels))
|
||||
for _, l := range t.Levels {
|
||||
level := make([]tree.Node, 0, len(l.Nodes))
|
||||
for _, n := range l.Nodes {
|
||||
@@ -584,13 +584,13 @@ func (t treeFromProto) parse() tree.CongestionTree {
|
||||
ParentTxid: n.ParentTxid,
|
||||
})
|
||||
}
|
||||
congestionTree = append(congestionTree, level)
|
||||
vtxoTree = append(vtxoTree, level)
|
||||
}
|
||||
|
||||
for j, treeLvl := range congestionTree {
|
||||
for j, treeLvl := range vtxoTree {
|
||||
for i, node := range treeLvl {
|
||||
if len(congestionTree.Children(node.Txid)) == 0 {
|
||||
congestionTree[j][i] = tree.Node{
|
||||
if len(vtxoTree.Children(node.Txid)) == 0 {
|
||||
vtxoTree[j][i] = tree.Node{
|
||||
Txid: node.Txid,
|
||||
Tx: node.Tx,
|
||||
ParentTxid: node.ParentTxid,
|
||||
@@ -600,7 +600,7 @@ func (t treeFromProto) parse() tree.CongestionTree {
|
||||
}
|
||||
}
|
||||
|
||||
return congestionTree
|
||||
return vtxoTree
|
||||
}
|
||||
|
||||
func (c *restClient) GetTransactionsStream(ctx context.Context) (<-chan client.TransactionEvent, func(), error) {
|
||||
@@ -725,7 +725,7 @@ func vtxosFromRest(restVtxos []*models.V1Vtxo) []client.Vtxo {
|
||||
Txid: v.Outpoint.Txid,
|
||||
VOut: uint32(v.Outpoint.Vout),
|
||||
},
|
||||
Pubkey: v.Pubkey,
|
||||
PubKey: v.Pubkey,
|
||||
Amount: uint64(amount),
|
||||
RoundTxid: v.RoundTxid,
|
||||
ExpiresAt: expiresAt,
|
||||
|
||||
@@ -396,7 +396,7 @@ func (a *Client) ArkServicePing(params *ArkServicePingParams, opts ...ClientOpti
|
||||
op := &runtime.ClientOperation{
|
||||
ID: "ArkService_Ping",
|
||||
Method: "GET",
|
||||
PathPattern: "/v1/round/ping/{paymentId}",
|
||||
PathPattern: "/v1/round/ping/{requestId}",
|
||||
ProducesMediaTypes: []string{"application/json"},
|
||||
ConsumesMediaTypes: []string{"application/json"},
|
||||
Schemes: []string{"http"},
|
||||
|
||||
@@ -61,8 +61,11 @@ ArkServicePingParams contains all the parameters to send to the API endpoint
|
||||
*/
|
||||
type ArkServicePingParams struct {
|
||||
|
||||
// PaymentID.
|
||||
PaymentID string
|
||||
/* RequestID.
|
||||
|
||||
The id used to register inputs and ouptuts.
|
||||
*/
|
||||
RequestID string
|
||||
|
||||
timeout time.Duration
|
||||
Context context.Context
|
||||
@@ -117,15 +120,15 @@ func (o *ArkServicePingParams) SetHTTPClient(client *http.Client) {
|
||||
o.HTTPClient = client
|
||||
}
|
||||
|
||||
// WithPaymentID adds the paymentID to the ark service ping params
|
||||
func (o *ArkServicePingParams) WithPaymentID(paymentID string) *ArkServicePingParams {
|
||||
o.SetPaymentID(paymentID)
|
||||
// WithRequestID adds the requestID to the ark service ping params
|
||||
func (o *ArkServicePingParams) WithRequestID(requestID string) *ArkServicePingParams {
|
||||
o.SetRequestID(requestID)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPaymentID adds the paymentId to the ark service ping params
|
||||
func (o *ArkServicePingParams) SetPaymentID(paymentID string) {
|
||||
o.PaymentID = paymentID
|
||||
// SetRequestID adds the requestId to the ark service ping params
|
||||
func (o *ArkServicePingParams) SetRequestID(requestID string) {
|
||||
o.RequestID = requestID
|
||||
}
|
||||
|
||||
// WriteToRequest writes these params to a swagger request
|
||||
@@ -136,8 +139,8 @@ func (o *ArkServicePingParams) WriteToRequest(r runtime.ClientRequest, reg strfm
|
||||
}
|
||||
var res []error
|
||||
|
||||
// path param paymentId
|
||||
if err := r.SetPathParam("paymentId", o.PaymentID); err != nil {
|
||||
// path param requestId
|
||||
if err := r.SetPathParam("requestId", o.RequestID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -88,12 +88,12 @@ func (o *ArkServicePingOK) Code() int {
|
||||
|
||||
func (o *ArkServicePingOK) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /v1/round/ping/{paymentId}][%d] arkServicePingOK %s", 200, payload)
|
||||
return fmt.Sprintf("[GET /v1/round/ping/{requestId}][%d] arkServicePingOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *ArkServicePingOK) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /v1/round/ping/{paymentId}][%d] arkServicePingOK %s", 200, payload)
|
||||
return fmt.Sprintf("[GET /v1/round/ping/{requestId}][%d] arkServicePingOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *ArkServicePingOK) GetPayload() models.V1PingResponse {
|
||||
@@ -160,12 +160,12 @@ func (o *ArkServicePingDefault) Code() int {
|
||||
|
||||
func (o *ArkServicePingDefault) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /v1/round/ping/{paymentId}][%d] ArkService_Ping default %s", o._statusCode, payload)
|
||||
return fmt.Sprintf("[GET /v1/round/ping/{requestId}][%d] ArkService_Ping default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *ArkServicePingDefault) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /v1/round/ping/{paymentId}][%d] ArkService_Ping default %s", o._statusCode, payload)
|
||||
return fmt.Sprintf("[GET /v1/round/ping/{requestId}][%d] ArkService_Ping default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *ArkServicePingDefault) GetPayload() *models.RPCStatus {
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// V1OwnershipProof This message is used to prove to the ASP that the user controls the vtxo without revealing the whole VTXO taproot tree.
|
||||
// V1OwnershipProof This message is used to prove to the server that the user controls the vtxo without revealing the whole VTXO taproot tree.
|
||||
//
|
||||
// swagger:model v1OwnershipProof
|
||||
type V1OwnershipProof struct {
|
||||
|
||||
@@ -17,8 +17,8 @@ import (
|
||||
// swagger:model v1RegisterInputsForNextRoundResponse
|
||||
type V1RegisterInputsForNextRoundResponse struct {
|
||||
|
||||
// Mocks wabisabi's blinded credentials.
|
||||
ID string `json:"id,omitempty"`
|
||||
// request Id
|
||||
RequestID string `json:"requestId,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this v1 register inputs for next round response
|
||||
|
||||
@@ -19,11 +19,11 @@ import (
|
||||
// swagger:model v1RegisterOutputsForNextRoundRequest
|
||||
type V1RegisterOutputsForNextRoundRequest struct {
|
||||
|
||||
// Mocks wabisabi's blinded credentials.
|
||||
ID string `json:"id,omitempty"`
|
||||
|
||||
// List of receivers for a registered payment.
|
||||
// List of receivers for to convert to leaves in the next VTXO tree.
|
||||
Outputs []*V1Output `json:"outputs"`
|
||||
|
||||
// request Id
|
||||
RequestID string `json:"requestId,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this v1 register outputs for next round request
|
||||
|
||||
@@ -20,7 +20,7 @@ type V1SubmitSignedForfeitTxsRequest struct {
|
||||
// Forfeit txs signed by the user.
|
||||
SignedForfeitTxs []string `json:"signedForfeitTxs"`
|
||||
|
||||
// If payment has boarding input, the user must sign the associated inputs.
|
||||
// The user has to sign also the round tx if he registerd a boarding UTXO.
|
||||
SignedRoundTx string `json:"signedRoundTx,omitempty"`
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ func LoadCovenantClient(sdkStore types.Store) (ArkClient, error) {
|
||||
}
|
||||
|
||||
clientSvc, err := getClient(
|
||||
supportedClients, cfgData.ClientType, cfgData.AspUrl,
|
||||
supportedClients, cfgData.ClientType, cfgData.ServerUrl,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to setup transport client: %s", err)
|
||||
@@ -147,7 +147,7 @@ func LoadCovenantClientWithWallet(
|
||||
}
|
||||
|
||||
clientSvc, err := getClient(
|
||||
supportedClients, cfgData.ClientType, cfgData.AspUrl,
|
||||
supportedClients, cfgData.ClientType, cfgData.ServerUrl,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to setup transport client: %s", err)
|
||||
@@ -243,19 +243,19 @@ func (a *covenantArkClient) listenForTxStream(ctx context.Context) {
|
||||
func (a *covenantArkClient) processTransactionEvent(
|
||||
event client.TransactionEvent,
|
||||
) {
|
||||
// TODO considering current covenant state where all payments happening in round
|
||||
//and that this is going to change we leave this unimplemented until asnc payments are implemented
|
||||
//also with current state it is not possible to cover some edge cases like when in a round there
|
||||
//are multiple boarding inputs + spent vtxo with change in spendable + received in the same round
|
||||
// TODO: considering current covenant state where all transactions happening in round
|
||||
// and that this is going to change we leave this unimplemented for now.
|
||||
// Also, with current state it is not possible to cover some edge cases like when in a round there
|
||||
// are multiple boarding inputs + spent vtxo with change in spendable + received in the same round
|
||||
}
|
||||
|
||||
func (a *covenantArkClient) listenForBoardingUtxos(
|
||||
ctx context.Context,
|
||||
) {
|
||||
// TODO considering current covenant state where all payments happening in round
|
||||
//and that this is going to change we leave this unimplemented until asnc payments are implemented
|
||||
//also with current state it is not possible to cover some edge cases like when in a round there
|
||||
//are multiple boarding inputs + spent vtxo with change in spendable + received in the same round
|
||||
// TODO considering current covenant state where all transactions happening in round
|
||||
// and that this is going to change we leave this unimplemented for now.
|
||||
// Also, with current state it is not possible to cover some edge cases like when in a round there
|
||||
// are multiple boarding inputs + spent vtxo with change in spendable + received in the same round
|
||||
}
|
||||
|
||||
func (a *covenantArkClient) Balance(
|
||||
@@ -525,7 +525,7 @@ func (a *covenantArkClient) CollaborativeRedeem(
|
||||
|
||||
for _, offchainAddr := range offchainAddrs {
|
||||
for _, v := range spendableVtxos {
|
||||
vtxoAddr, err := v.Address(a.AspPubkey, a.Network)
|
||||
vtxoAddr, err := v.Address(a.ServerPubKey, a.Network)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -584,16 +584,16 @@ func (a *covenantArkClient) CollaborativeRedeem(
|
||||
})
|
||||
}
|
||||
|
||||
paymentID, err := a.client.RegisterInputsForNextRound(ctx, inputs, "")
|
||||
requestID, err := a.client.RegisterInputsForNextRound(ctx, inputs, "")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := a.client.RegisterOutputsForNextRound(ctx, paymentID, receivers); err != nil {
|
||||
if err := a.client.RegisterOutputsForNextRound(ctx, requestID, receivers); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
roundTxID, err := a.handleRoundStream(ctx, paymentID, selectedCoins, selectedBoardingUtxos, receivers)
|
||||
roundTxID, err := a.handleRoundStream(ctx, requestID, selectedCoins, selectedBoardingUtxos, receivers)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -601,13 +601,6 @@ func (a *covenantArkClient) CollaborativeRedeem(
|
||||
return roundTxID, nil
|
||||
}
|
||||
|
||||
func (a *covenantArkClient) SendAsync(
|
||||
ctx context.Context,
|
||||
withExpiryCoinselect bool, receivers []Receiver,
|
||||
) (string, error) {
|
||||
return "", fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
func (a *covenantArkClient) Settle(
|
||||
ctx context.Context,
|
||||
) (string, error) {
|
||||
@@ -889,7 +882,7 @@ func (a *covenantArkClient) sendOffchain(
|
||||
return "", fmt.Errorf("wallet is locked")
|
||||
}
|
||||
|
||||
expectedAspPubKey := schnorr.SerializePubKey(a.AspPubkey)
|
||||
expectedServerPubkey := schnorr.SerializePubKey(a.ServerPubKey)
|
||||
outputs := make([]client.Output, 0)
|
||||
sumOfReceivers := uint64(0)
|
||||
|
||||
@@ -900,10 +893,10 @@ func (a *covenantArkClient) sendOffchain(
|
||||
return "", fmt.Errorf("invalid receiver address: %s", err)
|
||||
}
|
||||
|
||||
rcvAspPubKey := schnorr.SerializePubKey(rcvAddr.Asp)
|
||||
rcvServerPubKkey := schnorr.SerializePubKey(rcvAddr.Server)
|
||||
|
||||
if !bytes.Equal(expectedAspPubKey, rcvAspPubKey) {
|
||||
return "", fmt.Errorf("invalid receiver address '%s': expected ASP %s, got %s", receiver.To(), hex.EncodeToString(expectedAspPubKey), hex.EncodeToString(rcvAspPubKey))
|
||||
if !bytes.Equal(expectedServerPubkey, rcvServerPubKkey) {
|
||||
return "", fmt.Errorf("invalid receiver address '%s': expected server %s, got %s", receiver.To(), hex.EncodeToString(expectedServerPubkey), hex.EncodeToString(rcvServerPubKkey))
|
||||
}
|
||||
|
||||
if receiver.Amount() < a.Dust {
|
||||
@@ -934,7 +927,7 @@ func (a *covenantArkClient) sendOffchain(
|
||||
|
||||
for _, offchainAddr := range offchainAddrs {
|
||||
for _, v := range spendableVtxos {
|
||||
vtxoAddr, err := v.Address(a.AspPubkey, a.Network)
|
||||
vtxoAddr, err := v.Address(a.ServerPubKey, a.Network)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -1018,21 +1011,21 @@ func (a *covenantArkClient) sendOffchain(
|
||||
})
|
||||
}
|
||||
|
||||
paymentID, err := a.client.RegisterInputsForNextRound(ctx, inputs, "")
|
||||
requestID, err := a.client.RegisterInputsForNextRound(ctx, inputs, "")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := a.client.RegisterOutputsForNextRound(
|
||||
ctx, paymentID, outputs,
|
||||
ctx, requestID, outputs,
|
||||
); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
log.Infof("payment registered with id: %s", paymentID)
|
||||
log.Infof("payout registered with id: %s", requestID)
|
||||
|
||||
roundTxID, err := a.handleRoundStream(
|
||||
ctx, paymentID, selectedCoins, boardingUtxos, outputs,
|
||||
ctx, requestID, selectedCoins, boardingUtxos, outputs,
|
||||
)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -1116,19 +1109,19 @@ func (a *covenantArkClient) addInputs(
|
||||
|
||||
func (a *covenantArkClient) handleRoundStream(
|
||||
ctx context.Context,
|
||||
paymentID string,
|
||||
requestID string,
|
||||
vtxosToSign []client.TapscriptsVtxo,
|
||||
boardingUtxos []types.Utxo,
|
||||
receivers []client.Output,
|
||||
) (string, error) {
|
||||
eventsCh, close, err := a.client.GetEventStream(ctx, paymentID)
|
||||
eventsCh, close, err := a.client.GetEventStream(ctx, requestID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var pingStop func()
|
||||
for pingStop == nil {
|
||||
pingStop = a.ping(ctx, paymentID)
|
||||
pingStop = a.ping(ctx, requestID)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
@@ -1166,7 +1159,7 @@ func (a *covenantArkClient) handleRoundStream(
|
||||
continue
|
||||
}
|
||||
|
||||
log.Info("finalizing payment... ")
|
||||
log.Info("submitting forfeit transactions... ")
|
||||
if err := a.client.SubmitSignedForfeitTxs(ctx, signedForfeitTxs, signedRoundTx); err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -1185,7 +1178,7 @@ func (a *covenantArkClient) handleRoundFinalization(
|
||||
boardingUtxos []types.Utxo,
|
||||
receivers []client.Output,
|
||||
) (signedForfeits []string, signedRoundTx string, err error) {
|
||||
if err = a.validateCongestionTree(event, receivers); err != nil {
|
||||
if err = a.validateVtxoTree(event, receivers); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1270,11 +1263,11 @@ func (a *covenantArkClient) handleRoundFinalization(
|
||||
return signedForfeits, signedRoundTx, nil
|
||||
}
|
||||
|
||||
func (a *covenantArkClient) validateCongestionTree(
|
||||
func (a *covenantArkClient) validateVtxoTree(
|
||||
event client.RoundFinalizationEvent, receivers []client.Output,
|
||||
) error {
|
||||
poolTx := event.Tx
|
||||
ptx, err := psetv2.NewPsetFromBase64(poolTx)
|
||||
roundTx := event.Tx
|
||||
ptx, err := psetv2.NewPsetFromBase64(roundTx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1282,14 +1275,14 @@ func (a *covenantArkClient) validateCongestionTree(
|
||||
connectors := event.Connectors
|
||||
|
||||
if !utils.IsOnchainOnly(receivers) {
|
||||
if err := tree.ValidateCongestionTree(
|
||||
event.Tree, poolTx, a.Config.AspPubkey, a.RoundLifetime,
|
||||
if err := tree.ValidateVtxoTree(
|
||||
event.Tree, roundTx, a.Config.ServerPubKey, a.RoundLifetime,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := common.ValidateConnectors(poolTx, connectors); err != nil {
|
||||
if err := common.ValidateConnectors(roundTx, connectors); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1299,15 +1292,13 @@ func (a *covenantArkClient) validateCongestionTree(
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infoln("congestion tree validated")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *covenantArkClient) validateReceivers(
|
||||
ptx *psetv2.Pset,
|
||||
receivers []client.Output,
|
||||
congestionTree tree.CongestionTree,
|
||||
vtxoTree tree.VtxoTree,
|
||||
) error {
|
||||
for _, receiver := range receivers {
|
||||
isOnChain, onchainScript, err := utils.ParseLiquidAddress(
|
||||
@@ -1323,7 +1314,7 @@ func (a *covenantArkClient) validateReceivers(
|
||||
}
|
||||
} else {
|
||||
if err := a.validateOffChainReceiver(
|
||||
congestionTree, receiver,
|
||||
vtxoTree, receiver,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1357,7 +1348,7 @@ func (a *covenantArkClient) validateOnChainReceiver(
|
||||
}
|
||||
|
||||
func (a *covenantArkClient) validateOffChainReceiver(
|
||||
congestionTree tree.CongestionTree,
|
||||
vtxoTree tree.VtxoTree,
|
||||
receiver client.Output,
|
||||
) error {
|
||||
found := false
|
||||
@@ -1369,7 +1360,7 @@ func (a *covenantArkClient) validateOffChainReceiver(
|
||||
|
||||
vtxoTapKey := schnorr.SerializePubKey(addr.VtxoTapKey)
|
||||
|
||||
leaves := congestionTree.Leaves()
|
||||
leaves := vtxoTree.Leaves()
|
||||
for _, leaf := range leaves {
|
||||
tx, err := psetv2.NewPsetFromBase64(leaf.Tx)
|
||||
if err != nil {
|
||||
@@ -1614,22 +1605,22 @@ func (a *covenantArkClient) coinSelectOnchain(
|
||||
func (a *covenantArkClient) getRedeemBranches(
|
||||
ctx context.Context, vtxos []client.Vtxo,
|
||||
) (map[string]*redemption.CovenantRedeemBranch, error) {
|
||||
congestionTrees := make(map[string]tree.CongestionTree, 0)
|
||||
vtxoTrees := make(map[string]tree.VtxoTree, 0)
|
||||
redeemBranches := make(map[string]*redemption.CovenantRedeemBranch, 0)
|
||||
|
||||
for i := range vtxos {
|
||||
vtxo := vtxos[i]
|
||||
if _, ok := congestionTrees[vtxo.RoundTxid]; !ok {
|
||||
if _, ok := vtxoTrees[vtxo.RoundTxid]; !ok {
|
||||
round, err := a.client.GetRound(ctx, vtxo.RoundTxid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
congestionTrees[vtxo.RoundTxid] = round.Tree
|
||||
vtxoTrees[vtxo.RoundTxid] = round.Tree
|
||||
}
|
||||
|
||||
redeemBranch, err := redemption.NewCovenantRedeemBranch(
|
||||
a.explorer, congestionTrees[vtxo.RoundTxid], vtxo,
|
||||
a.explorer, vtxoTrees[vtxo.RoundTxid], vtxo,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -91,7 +91,7 @@ func LoadCovenantlessClient(sdkStore types.Store) (ArkClient, error) {
|
||||
}
|
||||
|
||||
clientSvc, err := getClient(
|
||||
supportedClients, cfgData.ClientType, cfgData.AspUrl,
|
||||
supportedClients, cfgData.ClientType, cfgData.ServerUrl,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to setup transport client: %s", err)
|
||||
@@ -151,7 +151,7 @@ func LoadCovenantlessClientWithWallet(
|
||||
}
|
||||
|
||||
clientSvc, err := getClient(
|
||||
supportedClients, cfgData.ClientType, cfgData.AspUrl,
|
||||
supportedClients, cfgData.ClientType, cfgData.ServerUrl,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to setup transport client: %s", err)
|
||||
@@ -395,7 +395,7 @@ func (a *covenantlessArkClient) processTransactionEvent(
|
||||
vtxosToInsert := make([]types.Vtxo, 0)
|
||||
txsToInsert := make([]types.Transaction, 0)
|
||||
for _, v := range event.Round.SpendableVtxos {
|
||||
if v.Pubkey == pubkey {
|
||||
if v.PubKey == pubkey {
|
||||
vtxosToInsert = append(vtxosToInsert, types.Vtxo{
|
||||
VtxoKey: types.VtxoKey{
|
||||
Txid: v.Txid,
|
||||
@@ -474,7 +474,7 @@ func (a *covenantlessArkClient) processTransactionEvent(
|
||||
|
||||
outputAmount := uint64(0)
|
||||
for _, v := range event.Redeem.SpendableVtxos {
|
||||
if v.Pubkey == pubkey {
|
||||
if v.PubKey == pubkey {
|
||||
vtxosToInsert = append(vtxosToInsert, types.Vtxo{
|
||||
VtxoKey: types.VtxoKey{
|
||||
Txid: v.Txid,
|
||||
@@ -507,7 +507,7 @@ func (a *covenantlessArkClient) processTransactionEvent(
|
||||
}
|
||||
} else {
|
||||
for _, v := range event.Redeem.SpendableVtxos {
|
||||
if v.Pubkey == pubkey {
|
||||
if v.PubKey == pubkey {
|
||||
vtxosToInsert = append(vtxosToInsert, types.Vtxo{
|
||||
VtxoKey: types.VtxoKey{
|
||||
Txid: v.Txid,
|
||||
@@ -708,13 +708,126 @@ func (a *covenantlessArkClient) SendOffChain(
|
||||
ctx context.Context,
|
||||
withExpiryCoinselect bool, receivers []Receiver,
|
||||
) (string, error) {
|
||||
if len(receivers) <= 0 {
|
||||
return "", fmt.Errorf("missing receivers")
|
||||
}
|
||||
|
||||
netParams := utils.ToBitcoinNetwork(a.Network)
|
||||
for _, receiver := range receivers {
|
||||
if receiver.IsOnchain() {
|
||||
return "", fmt.Errorf("invalid receiver address '%s': must be offchain", receiver.To())
|
||||
isOnchain, _, err := utils.ParseBitcoinAddress(receiver.To(), netParams)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if isOnchain {
|
||||
return "", fmt.Errorf("all receiver addresses must be offchain addresses")
|
||||
}
|
||||
}
|
||||
|
||||
return a.sendOffchain(ctx, withExpiryCoinselect, receivers)
|
||||
offchainAddrs, _, _, err := a.wallet.GetAddresses(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
expectedServerPubkey := schnorr.SerializePubKey(a.ServerPubKey)
|
||||
|
||||
sumOfReceivers := uint64(0)
|
||||
|
||||
for _, receiver := range receivers {
|
||||
rcvAddr, err := common.DecodeAddress(receiver.To())
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("invalid receiver address: %s", err)
|
||||
}
|
||||
|
||||
rcvServerPubkey := schnorr.SerializePubKey(rcvAddr.Server)
|
||||
|
||||
if !bytes.Equal(expectedServerPubkey, rcvServerPubkey) {
|
||||
return "", fmt.Errorf("invalid receiver address '%s': expected server %s, got %s", receiver.To(), hex.EncodeToString(expectedServerPubkey), hex.EncodeToString(rcvServerPubkey))
|
||||
}
|
||||
|
||||
if receiver.Amount() < a.Dust {
|
||||
return "", fmt.Errorf("invalid amount (%d), must be greater than dust %d", receiver.Amount(), a.Dust)
|
||||
}
|
||||
|
||||
sumOfReceivers += receiver.Amount()
|
||||
}
|
||||
|
||||
vtxos := make([]client.TapscriptsVtxo, 0)
|
||||
opts := &CoinSelectOptions{
|
||||
WithExpirySorting: withExpiryCoinselect,
|
||||
}
|
||||
spendableVtxos, err := a.getVtxos(ctx, opts)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
for _, offchainAddr := range offchainAddrs {
|
||||
for _, v := range spendableVtxos {
|
||||
vtxoAddr, err := v.Address(a.ServerPubKey, a.Network)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if vtxoAddr == offchainAddr.Address {
|
||||
vtxos = append(vtxos, client.TapscriptsVtxo{
|
||||
Vtxo: v,
|
||||
Tapscripts: offchainAddr.Tapscripts,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do not include boarding utxos
|
||||
_, selectedCoins, changeAmount, err := utils.CoinSelect(
|
||||
nil, vtxos, sumOfReceivers, a.Dust, withExpiryCoinselect,
|
||||
)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if changeAmount > 0 {
|
||||
receivers = append(receivers, NewBitcoinReceiver(offchainAddrs[0].Address, changeAmount))
|
||||
}
|
||||
|
||||
inputs := make([]redeemTxInput, 0, len(selectedCoins))
|
||||
|
||||
for _, coin := range selectedCoins {
|
||||
vtxoScript, err := bitcointree.ParseVtxoScript(coin.Tapscripts)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
forfeitClosure := vtxoScript.ForfeitClosures()[0]
|
||||
|
||||
forfeitScript, err := forfeitClosure.Script()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
forfeitLeaf := txscript.NewBaseTapLeaf(forfeitScript)
|
||||
|
||||
inputs = append(inputs, redeemTxInput{
|
||||
coin,
|
||||
forfeitLeaf.TapHash(),
|
||||
})
|
||||
}
|
||||
|
||||
feeRate := chainfee.FeePerKwFloor
|
||||
redeemTx, err := buildRedeemTx(inputs, receivers, feeRate.FeePerVByte())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
signedRedeemTx, err := a.wallet.SignTransaction(ctx, a.explorer, redeemTx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
signedRedeemTx, err = a.client.SubmitRedeemTx(ctx, signedRedeemTx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return signedRedeemTx, nil
|
||||
}
|
||||
|
||||
func (a *covenantlessArkClient) RedeemNotes(ctx context.Context, notes []string) (string, error) {
|
||||
@@ -741,7 +854,7 @@ func (a *covenantlessArkClient) RedeemNotes(ctx context.Context, notes []string)
|
||||
return "", err
|
||||
}
|
||||
|
||||
paymentID, err := a.client.RegisterNotesForNextRound(
|
||||
requestID, err := a.client.RegisterNotesForNextRound(
|
||||
ctx, notes, hex.EncodeToString(roundEphemeralKey.PubKey().SerializeCompressed()),
|
||||
)
|
||||
if err != nil {
|
||||
@@ -756,15 +869,15 @@ func (a *covenantlessArkClient) RedeemNotes(ctx context.Context, notes []string)
|
||||
receiversOutput := []client.Output{output}
|
||||
|
||||
if err := a.client.RegisterOutputsForNextRound(
|
||||
ctx, paymentID, receiversOutput,
|
||||
ctx, requestID, receiversOutput,
|
||||
); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
log.Infof("payment registered with id: %s", paymentID)
|
||||
log.Infof("payout registered with id: %s", requestID)
|
||||
|
||||
roundTxID, err := a.handleRoundStream(
|
||||
ctx, paymentID, nil, nil, receiversOutput, roundEphemeralKey,
|
||||
ctx, requestID, nil, nil, receiversOutput, roundEphemeralKey,
|
||||
)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -865,7 +978,7 @@ func (a *covenantlessArkClient) CollaborativeRedeem(
|
||||
|
||||
for _, offchainAddr := range offchainAddrs {
|
||||
for _, v := range spendableVtxos {
|
||||
vtxoAddr, err := v.Address(a.AspPubkey, a.Network)
|
||||
vtxoAddr, err := v.Address(a.ServerPubKey, a.Network)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -929,7 +1042,7 @@ func (a *covenantlessArkClient) CollaborativeRedeem(
|
||||
return "", err
|
||||
}
|
||||
|
||||
paymentID, err := a.client.RegisterInputsForNextRound(
|
||||
requestID, err := a.client.RegisterInputsForNextRound(
|
||||
ctx,
|
||||
inputs,
|
||||
hex.EncodeToString(roundEphemeralKey.PubKey().SerializeCompressed()),
|
||||
@@ -938,12 +1051,12 @@ func (a *covenantlessArkClient) CollaborativeRedeem(
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := a.client.RegisterOutputsForNextRound(ctx, paymentID, receivers); err != nil {
|
||||
if err := a.client.RegisterOutputsForNextRound(ctx, requestID, receivers); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
roundTxID, err := a.handleRoundStream(
|
||||
ctx, paymentID, selectedCoins, selectedBoardingCoins, receivers, roundEphemeralKey,
|
||||
ctx, requestID, selectedCoins, selectedBoardingCoins, receivers, roundEphemeralKey,
|
||||
)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -952,132 +1065,6 @@ func (a *covenantlessArkClient) CollaborativeRedeem(
|
||||
return roundTxID, nil
|
||||
}
|
||||
|
||||
func (a *covenantlessArkClient) SendAsync(
|
||||
ctx context.Context,
|
||||
withExpiryCoinselect bool, receivers []Receiver,
|
||||
) (string, error) {
|
||||
if len(receivers) <= 0 {
|
||||
return "", fmt.Errorf("missing receivers")
|
||||
}
|
||||
|
||||
netParams := utils.ToBitcoinNetwork(a.Network)
|
||||
for _, receiver := range receivers {
|
||||
isOnchain, _, err := utils.ParseBitcoinAddress(receiver.To(), netParams)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if isOnchain {
|
||||
return "", fmt.Errorf("all receiver addresses must be offchain addresses")
|
||||
}
|
||||
}
|
||||
|
||||
offchainAddrs, _, _, err := a.wallet.GetAddresses(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
expectedAspPubKey := schnorr.SerializePubKey(a.AspPubkey)
|
||||
|
||||
sumOfReceivers := uint64(0)
|
||||
|
||||
for _, receiver := range receivers {
|
||||
rcvAddr, err := common.DecodeAddress(receiver.To())
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("invalid receiver address: %s", err)
|
||||
}
|
||||
|
||||
rcvAspPubKey := schnorr.SerializePubKey(rcvAddr.Asp)
|
||||
|
||||
if !bytes.Equal(expectedAspPubKey, rcvAspPubKey) {
|
||||
return "", fmt.Errorf("invalid receiver address '%s': expected ASP %s, got %s", receiver.To(), hex.EncodeToString(expectedAspPubKey), hex.EncodeToString(rcvAspPubKey))
|
||||
}
|
||||
|
||||
if receiver.Amount() < a.Dust {
|
||||
return "", fmt.Errorf("invalid amount (%d), must be greater than dust %d", receiver.Amount(), a.Dust)
|
||||
}
|
||||
|
||||
sumOfReceivers += receiver.Amount()
|
||||
}
|
||||
|
||||
vtxos := make([]client.TapscriptsVtxo, 0)
|
||||
opts := &CoinSelectOptions{
|
||||
WithExpirySorting: withExpiryCoinselect,
|
||||
}
|
||||
spendableVtxos, err := a.getVtxos(ctx, opts)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
for _, offchainAddr := range offchainAddrs {
|
||||
for _, v := range spendableVtxos {
|
||||
vtxoAddr, err := v.Address(a.AspPubkey, a.Network)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if vtxoAddr == offchainAddr.Address {
|
||||
vtxos = append(vtxos, client.TapscriptsVtxo{
|
||||
Vtxo: v,
|
||||
Tapscripts: offchainAddr.Tapscripts,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do not include boarding utxos
|
||||
_, selectedCoins, changeAmount, err := utils.CoinSelect(
|
||||
nil, vtxos, sumOfReceivers, a.Dust, withExpiryCoinselect,
|
||||
)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if changeAmount > 0 {
|
||||
receivers = append(receivers, NewBitcoinReceiver(offchainAddrs[0].Address, changeAmount))
|
||||
}
|
||||
|
||||
inputs := make([]redeemTxInput, 0, len(selectedCoins))
|
||||
|
||||
for _, coin := range selectedCoins {
|
||||
vtxoScript, err := bitcointree.ParseVtxoScript(coin.Tapscripts)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
forfeitClosure := vtxoScript.ForfeitClosures()[0]
|
||||
|
||||
forfeitScript, err := forfeitClosure.Script()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
forfeitLeaf := txscript.NewBaseTapLeaf(forfeitScript)
|
||||
|
||||
inputs = append(inputs, redeemTxInput{
|
||||
coin,
|
||||
forfeitLeaf.TapHash(),
|
||||
})
|
||||
}
|
||||
|
||||
feeRate := chainfee.FeePerKwFloor
|
||||
redeemTx, err := buildRedeemTx(inputs, receivers, feeRate.FeePerVByte())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
signedRedeemTx, err := a.wallet.SignTransaction(ctx, a.explorer, redeemTx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
signedRedeemTx, err = a.client.SubmitRedeemTx(ctx, signedRedeemTx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return signedRedeemTx, nil
|
||||
}
|
||||
|
||||
func (a *covenantlessArkClient) Settle(ctx context.Context) (string, error) {
|
||||
return a.sendOffchain(ctx, false, nil)
|
||||
}
|
||||
@@ -1136,7 +1123,7 @@ func (a *covenantlessArkClient) SetNostrNotificationRecipient(ctx context.Contex
|
||||
descriptorVtxos := make([]client.TapscriptsVtxo, 0)
|
||||
for _, offchainAddr := range offchainAddrs {
|
||||
for _, vtxo := range spendableVtxos {
|
||||
vtxoAddr, err := vtxo.Address(a.AspPubkey, a.Network)
|
||||
vtxoAddr, err := vtxo.Address(a.ServerPubKey, a.Network)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1362,7 +1349,7 @@ func (a *covenantlessArkClient) sendOffchain(
|
||||
return "", fmt.Errorf("wallet is locked")
|
||||
}
|
||||
|
||||
expectedAspPubKey := schnorr.SerializePubKey(a.AspPubkey)
|
||||
expectedServerPubkey := schnorr.SerializePubKey(a.ServerPubKey)
|
||||
outputs := make([]client.Output, 0)
|
||||
sumOfReceivers := uint64(0)
|
||||
|
||||
@@ -1373,10 +1360,10 @@ func (a *covenantlessArkClient) sendOffchain(
|
||||
return "", fmt.Errorf("invalid receiver address: %s", err)
|
||||
}
|
||||
|
||||
rcvAspPubKey := schnorr.SerializePubKey(rcvAddr.Asp)
|
||||
rcvServerPubkey := schnorr.SerializePubKey(rcvAddr.Server)
|
||||
|
||||
if !bytes.Equal(expectedAspPubKey, rcvAspPubKey) {
|
||||
return "", fmt.Errorf("invalid receiver address '%s': expected ASP %s, got %s", receiver.To(), hex.EncodeToString(expectedAspPubKey), hex.EncodeToString(rcvAspPubKey))
|
||||
if !bytes.Equal(expectedServerPubkey, rcvServerPubkey) {
|
||||
return "", fmt.Errorf("invalid receiver address '%s': expected server %s, got %s", receiver.To(), hex.EncodeToString(expectedServerPubkey), hex.EncodeToString(rcvServerPubkey))
|
||||
}
|
||||
|
||||
if receiver.Amount() < a.Dust {
|
||||
@@ -1408,7 +1395,7 @@ func (a *covenantlessArkClient) sendOffchain(
|
||||
|
||||
for _, offchainAddr := range offchainAddrs {
|
||||
for _, v := range spendableVtxos {
|
||||
vtxoAddr, err := v.Address(a.AspPubkey, a.Network)
|
||||
vtxoAddr, err := v.Address(a.ServerPubKey, a.Network)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -1495,7 +1482,7 @@ func (a *covenantlessArkClient) sendOffchain(
|
||||
return "", err
|
||||
}
|
||||
|
||||
paymentID, err := a.client.RegisterInputsForNextRound(
|
||||
requestID, err := a.client.RegisterInputsForNextRound(
|
||||
ctx, inputs, hex.EncodeToString(roundEphemeralKey.PubKey().SerializeCompressed()),
|
||||
)
|
||||
if err != nil {
|
||||
@@ -1503,15 +1490,15 @@ func (a *covenantlessArkClient) sendOffchain(
|
||||
}
|
||||
|
||||
if err := a.client.RegisterOutputsForNextRound(
|
||||
ctx, paymentID, outputs,
|
||||
ctx, requestID, outputs,
|
||||
); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
log.Infof("payment registered with id: %s", paymentID)
|
||||
log.Infof("registered inputs and outputs with request id: %s", requestID)
|
||||
|
||||
roundTxID, err := a.handleRoundStream(
|
||||
ctx, paymentID, selectedCoins, selectedBoardingCoins, outputs, roundEphemeralKey,
|
||||
ctx, requestID, selectedCoins, selectedBoardingCoins, outputs, roundEphemeralKey,
|
||||
)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -1594,7 +1581,7 @@ func (a *covenantlessArkClient) addInputs(
|
||||
|
||||
func (a *covenantlessArkClient) handleRoundStream(
|
||||
ctx context.Context,
|
||||
paymentID string,
|
||||
requestID string,
|
||||
vtxosToSign []client.TapscriptsVtxo,
|
||||
boardingUtxos []types.Utxo,
|
||||
receivers []client.Output,
|
||||
@@ -1605,14 +1592,14 @@ func (a *covenantlessArkClient) handleRoundStream(
|
||||
return "", err
|
||||
}
|
||||
|
||||
eventsCh, close, err := a.client.GetEventStream(ctx, paymentID)
|
||||
eventsCh, close, err := a.client.GetEventStream(ctx, requestID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var pingStop func()
|
||||
for pingStop == nil {
|
||||
pingStop = a.ping(ctx, paymentID)
|
||||
pingStop = a.ping(ctx, requestID)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
@@ -1697,7 +1684,7 @@ func (a *covenantlessArkClient) handleRoundStream(
|
||||
continue
|
||||
}
|
||||
|
||||
log.Info("finalizing payment... ")
|
||||
log.Info("submitting forfeit transactions... ")
|
||||
if err := a.client.SubmitSignedForfeitTxs(ctx, signedForfeitTxs, signedRoundTx); err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -1715,7 +1702,7 @@ func (a *covenantlessArkClient) handleRoundSigningStarted(
|
||||
ctx context.Context, ephemeralKey *secp256k1.PrivateKey, event client.RoundSigningStartedEvent,
|
||||
) (signerSession bitcointree.SignerSession, err error) {
|
||||
sweepClosure := tree.CSVSigClosure{
|
||||
MultisigClosure: tree.MultisigClosure{PubKeys: []*secp256k1.PublicKey{a.AspPubkey}},
|
||||
MultisigClosure: tree.MultisigClosure{PubKeys: []*secp256k1.PublicKey{a.ServerPubKey}},
|
||||
Seconds: uint(a.RoundLifetime),
|
||||
}
|
||||
|
||||
@@ -1740,7 +1727,7 @@ func (a *covenantlessArkClient) handleRoundSigningStarted(
|
||||
ephemeralKey, sharedOutputValue, event.UnsignedTree, root.CloneBytes(),
|
||||
)
|
||||
|
||||
if err = signerSession.SetKeys(event.CosignersPublicKeys); err != nil {
|
||||
if err = signerSession.SetKeys(event.CosignersPubKeys); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1749,9 +1736,9 @@ func (a *covenantlessArkClient) handleRoundSigningStarted(
|
||||
return
|
||||
}
|
||||
|
||||
myPubKey := hex.EncodeToString(ephemeralKey.PubKey().SerializeCompressed())
|
||||
myPubkey := hex.EncodeToString(ephemeralKey.PubKey().SerializeCompressed())
|
||||
|
||||
err = a.arkClient.client.SubmitTreeNonces(ctx, event.ID, myPubKey, nonces)
|
||||
err = a.arkClient.client.SubmitTreeNonces(ctx, event.ID, myPubkey, nonces)
|
||||
|
||||
return
|
||||
}
|
||||
@@ -1794,8 +1781,8 @@ func (a *covenantlessArkClient) handleRoundFinalization(
|
||||
boardingUtxos []types.Utxo,
|
||||
receivers []client.Output,
|
||||
) ([]string, string, error) {
|
||||
if err := a.validateCongestionTree(event, receivers); err != nil {
|
||||
return nil, "", fmt.Errorf("failed to verify congestion tree: %s", err)
|
||||
if err := a.validateVtxoTree(event, receivers); err != nil {
|
||||
return nil, "", fmt.Errorf("failed to verify vtxo tree: %s", err)
|
||||
}
|
||||
|
||||
var forfeits []string
|
||||
@@ -1880,24 +1867,25 @@ func (a *covenantlessArkClient) handleRoundFinalization(
|
||||
return forfeits, signedRoundTx, nil
|
||||
}
|
||||
|
||||
func (a *covenantlessArkClient) validateCongestionTree(
|
||||
func (a *covenantlessArkClient) validateVtxoTree(
|
||||
event client.RoundFinalizationEvent, receivers []client.Output,
|
||||
) error {
|
||||
poolTx := event.Tx
|
||||
ptx, err := psbt.NewFromRawBytes(strings.NewReader(poolTx), true)
|
||||
roundTx := event.Tx
|
||||
ptx, err := psbt.NewFromRawBytes(strings.NewReader(roundTx), true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !utils.IsOnchainOnly(receivers) {
|
||||
if err := bitcointree.ValidateCongestionTree(
|
||||
event.Tree, poolTx, a.Config.AspPubkey, a.RoundLifetime,
|
||||
if err := bitcointree.ValidateVtxoTree(
|
||||
event.Tree, roundTx, a.Config.ServerPubKey, a.RoundLifetime,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// if err := common.ValidateConnectors(poolTx, event.Connectors); err != nil {
|
||||
// TODO: common.ValidateConnectors is for covenant version (liquid), add covenantless (bitcoin) version
|
||||
// if err := common.ValidateConnectors(roundTx, event.Connectors); err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
@@ -1907,15 +1895,13 @@ func (a *covenantlessArkClient) validateCongestionTree(
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info("congestion tree validated")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *covenantlessArkClient) validateReceivers(
|
||||
ptx *psbt.Packet,
|
||||
receivers []client.Output,
|
||||
congestionTree tree.CongestionTree,
|
||||
vtxoTree tree.VtxoTree,
|
||||
) error {
|
||||
netParams := utils.ToBitcoinNetwork(a.Network)
|
||||
for _, receiver := range receivers {
|
||||
@@ -1932,7 +1918,7 @@ func (a *covenantlessArkClient) validateReceivers(
|
||||
}
|
||||
} else {
|
||||
if err := a.validateOffChainReceiver(
|
||||
congestionTree, receiver,
|
||||
vtxoTree, receiver,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1966,7 +1952,7 @@ func (a *covenantlessArkClient) validateOnChainReceiver(
|
||||
}
|
||||
|
||||
func (a *covenantlessArkClient) validateOffChainReceiver(
|
||||
congestionTree tree.CongestionTree,
|
||||
vtxoTree tree.VtxoTree,
|
||||
receiver client.Output,
|
||||
) error {
|
||||
found := false
|
||||
@@ -1978,7 +1964,7 @@ func (a *covenantlessArkClient) validateOffChainReceiver(
|
||||
|
||||
vtxoTapKey := schnorr.SerializePubKey(rcvAddr.VtxoTapKey)
|
||||
|
||||
leaves := congestionTree.Leaves()
|
||||
leaves := vtxoTree.Leaves()
|
||||
for _, leaf := range leaves {
|
||||
tx, err := psbt.NewFromRawBytes(strings.NewReader(leaf.Tx), true)
|
||||
if err != nil {
|
||||
@@ -2247,7 +2233,7 @@ func (a *covenantlessArkClient) coinSelectOnchain(
|
||||
func (a *covenantlessArkClient) getRedeemBranches(
|
||||
ctx context.Context, vtxos []client.Vtxo,
|
||||
) (map[string]*redemption.CovenantlessRedeemBranch, error) {
|
||||
congestionTrees := make(map[string]tree.CongestionTree, 0)
|
||||
vtxoTrees := make(map[string]tree.VtxoTree, 0)
|
||||
redeemBranches := make(map[string]*redemption.CovenantlessRedeemBranch, 0)
|
||||
|
||||
for i := range vtxos {
|
||||
@@ -2258,17 +2244,17 @@ func (a *covenantlessArkClient) getRedeemBranches(
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := congestionTrees[vtxo.RoundTxid]; !ok {
|
||||
if _, ok := vtxoTrees[vtxo.RoundTxid]; !ok {
|
||||
round, err := a.client.GetRound(ctx, vtxo.RoundTxid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
congestionTrees[vtxo.RoundTxid] = round.Tree
|
||||
vtxoTrees[vtxo.RoundTxid] = round.Tree
|
||||
}
|
||||
|
||||
redeemBranch, err := redemption.NewCovenantlessRedeemBranch(
|
||||
a.explorer, congestionTrees[vtxo.RoundTxid], vtxo,
|
||||
a.explorer, vtxoTrees[vtxo.RoundTxid], vtxo,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
aspUrl = "localhost:6060"
|
||||
serverUrl = "localhost:6060"
|
||||
clientType = arksdk.GrpcClient
|
||||
password = "password"
|
||||
walletType = arksdk.SingleKeyWallet
|
||||
@@ -110,7 +110,7 @@ func main() {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Infof("payment completed in round tx: %s", txid)
|
||||
log.Infof("transaction completed in round: %s", txid)
|
||||
|
||||
if err := generateBlock(); err != nil {
|
||||
log.Fatal(err)
|
||||
@@ -155,7 +155,7 @@ func setupArkClient(wallet string) (arksdk.ArkClient, error) {
|
||||
if err := client.Init(context.Background(), arksdk.InitArgs{
|
||||
WalletType: walletType,
|
||||
ClientType: clientType,
|
||||
AspUrl: aspUrl,
|
||||
ServerUrl: serverUrl,
|
||||
Password: password,
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("failed to initialize wallet: %s", err)
|
||||
|
||||
@@ -28,13 +28,13 @@
|
||||
logMessage("Init error: password is required");
|
||||
return;
|
||||
}
|
||||
const aspUrl = document.getElementById("aspUrl").value;
|
||||
if (!aspUrl) {
|
||||
logMessage("Init error: asp url is required");
|
||||
const serverUrl = document.getElementById("serverUrl").value;
|
||||
if (!serverUrl) {
|
||||
logMessage("Init error: server url is required");
|
||||
return;
|
||||
}
|
||||
await init(walletType, clientType, aspUrl, privateKey, password, chain, explorerUrl);
|
||||
logMessage("wallet initialized and connected to ASP");
|
||||
await init(walletType, clientType, serverUrl, privateKey, password, chain, explorerUrl);
|
||||
logMessage("wallet initialized and connected to server");
|
||||
await config();
|
||||
} catch (err) {
|
||||
logMessage("Init error: " + err.message);
|
||||
@@ -91,11 +91,11 @@
|
||||
|
||||
async function config() {
|
||||
try {
|
||||
const aspUrl = await getAspUrl();
|
||||
logMessage("ASP URL: " + aspUrl);
|
||||
const serverUrl = await getServerUrl();
|
||||
logMessage("Server URL: " + serverUrl);
|
||||
|
||||
const aspPubKeyHex = await getAspPubKeyHex();
|
||||
logMessage("ASP PubKey: " + aspPubKeyHex);
|
||||
const serverPubkeyHex = await getServerPubkeyHex();
|
||||
logMessage("Server PubKey: " + serverPubkeyHex);
|
||||
|
||||
const walletType = await getWalletType();
|
||||
logMessage("Wallet Type: " + walletType);
|
||||
@@ -145,7 +145,7 @@
|
||||
<h2>Wallet</h2>
|
||||
<div>
|
||||
<button onclick="initWallet()">Init</button>
|
||||
<input type="text" id="aspUrl" placeholder="http://localhost:6060">
|
||||
<input type="text" id="serverUrl" placeholder="http://localhost:6060">
|
||||
<input type="password" id="i_password" placeholder="password">
|
||||
<input type="text" id="prvkey" placeholder="Optional: privkey (hex)">
|
||||
</div>
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
aspUrl = "localhost:7070"
|
||||
serverUrl = "localhost:7070"
|
||||
clientType = arksdk.GrpcClient
|
||||
password = "password"
|
||||
walletType = arksdk.SingleKeyWallet
|
||||
@@ -128,11 +128,11 @@ func main() {
|
||||
fmt.Println("")
|
||||
log.Infof("alice is sending %d sats to bob offchain...", amount)
|
||||
|
||||
if _, err = aliceArkClient.SendAsync(ctx, false, receivers); err != nil {
|
||||
if _, err = aliceArkClient.SendOffChain(ctx, false, receivers); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Info("payment completed out of round")
|
||||
log.Info("transaction completed out of round")
|
||||
|
||||
if err := generateBlock(); err != nil {
|
||||
log.Fatal(err)
|
||||
@@ -188,7 +188,7 @@ func setupArkClient(wallet string) (arksdk.ArkClient, error) {
|
||||
if err := client.Init(context.Background(), arksdk.InitArgs{
|
||||
WalletType: walletType,
|
||||
ClientType: clientType,
|
||||
AspUrl: aspUrl,
|
||||
ServerUrl: serverUrl,
|
||||
Password: password,
|
||||
WithTransactionFeed: true,
|
||||
}); err != nil {
|
||||
|
||||
@@ -28,13 +28,13 @@
|
||||
logMessage("Init error: password is required");
|
||||
return;
|
||||
}
|
||||
const aspUrl = document.getElementById("aspUrl").value;
|
||||
if (!aspUrl) {
|
||||
logMessage("Init error: asp url is required");
|
||||
const serverUrl = document.getElementById("serverUrl").value;
|
||||
if (!serverUrl) {
|
||||
logMessage("Init error: server url is required");
|
||||
return;
|
||||
}
|
||||
await init(walletType, clientType, aspUrl, privateKey, password, chain, explorerUrl);
|
||||
logMessage("wallet initialized and connected to ASP");
|
||||
await init(walletType, clientType, serverUrl, privateKey, password, chain, explorerUrl);
|
||||
logMessage("wallet initialized and connected to server");
|
||||
await config();
|
||||
} catch (err) {
|
||||
logMessage("Init error: " + err.message);
|
||||
@@ -119,11 +119,11 @@
|
||||
|
||||
async function config() {
|
||||
try {
|
||||
const aspUrl = await getAspUrl();
|
||||
logMessage("ASP URL: " + aspUrl);
|
||||
const serverUrl = await getServerUrl();
|
||||
logMessage("Server URL: " + serverUrl);
|
||||
|
||||
const aspPubKeyHex = await getAspPubKeyHex();
|
||||
logMessage("ASP PubKey: " + aspPubKeyHex);
|
||||
const serverPubkeyHex = await getServerPubkeyHex();
|
||||
logMessage("Server Pubkey: " + serverPubkeyHex);
|
||||
|
||||
const walletType = await getWalletType();
|
||||
logMessage("Wallet Type: " + walletType);
|
||||
@@ -149,7 +149,7 @@
|
||||
<h2>Wallet</h2>
|
||||
<div>
|
||||
<button onclick="initWallet()">Init</button>
|
||||
<input type="text" id="aspUrl" placeholder="http://localhost:7070">
|
||||
<input type="text" id="serverUrl" placeholder="http://localhost:7070">
|
||||
<input type="password" id="i_password" placeholder="password">
|
||||
<input type="text" id="prvkey" placeholder="Optional: privkey (hex)">
|
||||
</div>
|
||||
|
||||
@@ -22,7 +22,7 @@ func (t SupportedType[V]) Supports(typeStr string) bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
type ClientFactory func(string) (client.ASPClient, error)
|
||||
type ClientFactory func(string) (client.TransportClient, error)
|
||||
|
||||
type Cache[V any] struct {
|
||||
mapping map[string]V
|
||||
|
||||
@@ -173,11 +173,11 @@ func ToBitcoinNetwork(net common.Network) chaincfg.Params {
|
||||
}
|
||||
|
||||
func GenerateRandomPrivateKey() (*secp256k1.PrivateKey, error) {
|
||||
privKey, err := btcec.NewPrivateKey()
|
||||
prvkey, err := btcec.NewPrivateKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return privKey, nil
|
||||
return prvkey, nil
|
||||
}
|
||||
|
||||
func HashPassword(password []byte) []byte {
|
||||
|
||||
@@ -24,9 +24,9 @@ type CovenantRedeemBranch struct {
|
||||
|
||||
func NewCovenantRedeemBranch(
|
||||
explorer explorer.Explorer,
|
||||
congestionTree tree.CongestionTree, vtxo client.Vtxo,
|
||||
vtxoTree tree.VtxoTree, vtxo client.Vtxo,
|
||||
) (*CovenantRedeemBranch, error) {
|
||||
sweepClosure, seconds, err := findCovenantSweepClosure(congestionTree)
|
||||
sweepClosure, seconds, err := findCovenantSweepClosure(vtxoTree)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -36,7 +36,7 @@ func NewCovenantRedeemBranch(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodes, err := congestionTree.Branch(vtxo.Txid)
|
||||
nodes, err := vtxoTree.Branch(vtxo.Txid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -182,9 +182,9 @@ func (r *CovenantRedeemBranch) offchainPath() ([]*psetv2.Pset, error) {
|
||||
}
|
||||
|
||||
func findCovenantSweepClosure(
|
||||
congestionTree tree.CongestionTree,
|
||||
vtxoTree tree.VtxoTree,
|
||||
) (*taproot.TapElementsLeaf, uint, error) {
|
||||
root, err := congestionTree.Root()
|
||||
root, err := vtxoTree.Root()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
@@ -23,9 +23,9 @@ type CovenantlessRedeemBranch struct {
|
||||
|
||||
func NewCovenantlessRedeemBranch(
|
||||
explorer explorer.Explorer,
|
||||
congestionTree tree.CongestionTree, vtxo client.Vtxo,
|
||||
vtxoTree tree.VtxoTree, vtxo client.Vtxo,
|
||||
) (*CovenantlessRedeemBranch, error) {
|
||||
_, seconds, err := findCovenantlessSweepClosure(congestionTree)
|
||||
_, seconds, err := findCovenantlessSweepClosure(vtxoTree)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -35,7 +35,7 @@ func NewCovenantlessRedeemBranch(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nodes, err := congestionTree.Branch(vtxo.Txid)
|
||||
nodes, err := vtxoTree.Branch(vtxo.Txid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -155,9 +155,9 @@ func (r *CovenantlessRedeemBranch) OffchainPath() ([]*psbt.Packet, error) {
|
||||
}
|
||||
|
||||
func findCovenantlessSweepClosure(
|
||||
congestionTree tree.CongestionTree,
|
||||
vtxoTree tree.VtxoTree,
|
||||
) (*txscript.TapLeaf, uint, error) {
|
||||
root, err := congestionTree.Root()
|
||||
root, err := vtxoTree.Root()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
@@ -52,8 +52,8 @@ func (s *configStore) GetDatadir() string {
|
||||
|
||||
func (s *configStore) AddData(ctx context.Context, data types.Config) error {
|
||||
sd := &storeData{
|
||||
AspUrl: data.AspUrl,
|
||||
AspPubkey: hex.EncodeToString(data.AspPubkey.SerializeCompressed()),
|
||||
ServerUrl: data.ServerUrl,
|
||||
ServerPubKey: hex.EncodeToString(data.ServerPubKey.SerializeCompressed()),
|
||||
WalletType: data.WalletType,
|
||||
ClientType: data.ClientType,
|
||||
Network: data.Network.Name,
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
)
|
||||
|
||||
type storeData struct {
|
||||
AspUrl string `json:"asp_url"`
|
||||
AspPubkey string `json:"asp_pubkey"`
|
||||
ServerUrl string `json:"server_url"`
|
||||
ServerPubKey string `json:"server_pubkey"`
|
||||
WalletType string `json:"wallet_type"`
|
||||
ClientType string `json:"client_type"`
|
||||
Network string `json:"network"`
|
||||
@@ -26,8 +26,8 @@ type storeData struct {
|
||||
}
|
||||
|
||||
func (d storeData) isEmpty() bool {
|
||||
if d.AspUrl == "" &&
|
||||
d.AspPubkey == "" {
|
||||
if d.ServerUrl == "" &&
|
||||
d.ServerPubKey == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -41,12 +41,12 @@ func (d storeData) decode() types.Config {
|
||||
unilateralExitDelay, _ := strconv.Atoi(d.UnilateralExitDelay)
|
||||
withTransactionFeed, _ := strconv.ParseBool(d.WithTransactionFeed)
|
||||
dust, _ := strconv.Atoi(d.Dust)
|
||||
buf, _ := hex.DecodeString(d.AspPubkey)
|
||||
aspPubkey, _ := secp256k1.ParsePubKey(buf)
|
||||
buf, _ := hex.DecodeString(d.ServerPubKey)
|
||||
serverPubkey, _ := secp256k1.ParsePubKey(buf)
|
||||
explorerURL := d.ExplorerURL
|
||||
return types.Config{
|
||||
AspUrl: d.AspUrl,
|
||||
AspPubkey: aspPubkey,
|
||||
ServerUrl: d.ServerUrl,
|
||||
ServerPubKey: serverPubkey,
|
||||
WalletType: d.WalletType,
|
||||
ClientType: d.ClientType,
|
||||
Network: network,
|
||||
@@ -63,8 +63,8 @@ func (d storeData) decode() types.Config {
|
||||
|
||||
func (d storeData) asMap() map[string]string {
|
||||
return map[string]string{
|
||||
"asp_url": d.AspUrl,
|
||||
"asp_pubkey": d.AspPubkey,
|
||||
"server_url": d.ServerUrl,
|
||||
"server_pubkey": d.ServerPubKey,
|
||||
"wallet_type": d.WalletType,
|
||||
"client_type": d.ClientType,
|
||||
"network": d.Network,
|
||||
|
||||
@@ -21,8 +21,8 @@ func TestStore(t *testing.T) {
|
||||
key, _ := btcec.NewPrivateKey()
|
||||
ctx := context.Background()
|
||||
testStoreData := sdktypes.Config{
|
||||
AspUrl: "localhost:7070",
|
||||
AspPubkey: key.PubKey(),
|
||||
ServerUrl: "localhost:7070",
|
||||
ServerPubKey: key.PubKey(),
|
||||
WalletType: wallet.SingleKeyWallet,
|
||||
ClientType: client.GrpcClient,
|
||||
Network: common.LiquidRegTest,
|
||||
|
||||
@@ -4,10 +4,6 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
utils "github.com/ark-network/ark/server/test/e2e"
|
||||
"github.com/playwright-community/playwright-go"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -18,6 +14,11 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
utils "github.com/ark-network/ark/server/test/e2e"
|
||||
"github.com/playwright-community/playwright-go"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/shirou/gopsutil/net"
|
||||
)
|
||||
|
||||
@@ -51,7 +52,7 @@ func TestMain(m *testing.M) {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
_, err = runClarkCommand("init", "--asp-url", "localhost:7070", "--password", utils.Password, "--network", "regtest", "--explorer", "http://chopsticks:3000")
|
||||
_, err = runClarkCommand("init", "--server-url", "localhost:7070", "--password", utils.Password, "--network", "regtest", "--explorer", "http://chopsticks:3000")
|
||||
if err != nil {
|
||||
fmt.Printf("error initializing ark config: %s", err)
|
||||
os.Exit(1)
|
||||
@@ -139,9 +140,9 @@ func TestWasm(t *testing.T) {
|
||||
|
||||
amount := 1000
|
||||
t.Logf("Alice is sending %d sats to Bob offchain...", amount)
|
||||
require.NoError(t, sendAsync(alicePage, bobAddr.OffchainAddr, amount))
|
||||
require.NoError(t, sendOffChain(alicePage, bobAddr.OffchainAddr, amount))
|
||||
|
||||
t.Log("Payment completed out of round")
|
||||
t.Log("Transaction completed out of round")
|
||||
|
||||
t.Logf("Bob settling the received funds...")
|
||||
txID, err = settle(bobPage)
|
||||
@@ -231,8 +232,8 @@ func initWallet(page playwright.Page) error {
|
||||
const privateKey = "";
|
||||
const password = "pass";
|
||||
const explorerUrl = "";
|
||||
const aspUrl = "http://localhost:7070";
|
||||
return await init(walletType, clientType, aspUrl, privateKey, password, chain, explorerUrl);
|
||||
const serverUrl = "http://localhost:7070";
|
||||
return await init(walletType, clientType, serverUrl, privateKey, password, chain, explorerUrl);
|
||||
} catch (err) {
|
||||
console.error("Init error:", err);
|
||||
throw err;
|
||||
@@ -336,10 +337,10 @@ func settle(page playwright.Page) (string, error) {
|
||||
return fmt.Sprint(result), nil
|
||||
}
|
||||
|
||||
func sendAsync(page playwright.Page, addr string, amount int) error {
|
||||
func sendOffChain(page playwright.Page, addr string, amount int) error {
|
||||
_, err := page.Evaluate(fmt.Sprintf(`async () => {
|
||||
try {
|
||||
return await sendAsync(false, [{To:"%s", Amount:%d}]);
|
||||
return await sendOffChain(false, [{To:"%s", Amount:%d}]);
|
||||
} catch (err) {
|
||||
console.error("Error:", err);
|
||||
throw err;
|
||||
|
||||
@@ -23,7 +23,7 @@ var (
|
||||
type InitArgs struct {
|
||||
ClientType string
|
||||
WalletType string
|
||||
AspUrl string
|
||||
ServerUrl string
|
||||
Seed string
|
||||
Password string
|
||||
ExplorerURL string
|
||||
@@ -51,8 +51,8 @@ func (a InitArgs) validate() error {
|
||||
)
|
||||
}
|
||||
|
||||
if len(a.AspUrl) <= 0 {
|
||||
return fmt.Errorf("missing asp url")
|
||||
if len(a.ServerUrl) <= 0 {
|
||||
return fmt.Errorf("missing server url")
|
||||
}
|
||||
if len(a.Password) <= 0 {
|
||||
return fmt.Errorf("missing password")
|
||||
@@ -63,7 +63,7 @@ func (a InitArgs) validate() error {
|
||||
type InitWithWalletArgs struct {
|
||||
ClientType string
|
||||
Wallet wallet.WalletService
|
||||
AspUrl string
|
||||
ServerUrl string
|
||||
Seed string
|
||||
Password string
|
||||
ExplorerURL string
|
||||
@@ -82,8 +82,8 @@ func (a InitWithWalletArgs) validate() error {
|
||||
return fmt.Errorf("client type not supported, please select one of: %s", supportedClients)
|
||||
}
|
||||
|
||||
if len(a.AspUrl) <= 0 {
|
||||
return fmt.Errorf("missing asp url")
|
||||
if len(a.ServerUrl) <= 0 {
|
||||
return fmt.Errorf("missing server url")
|
||||
}
|
||||
if len(a.Password) <= 0 {
|
||||
return fmt.Errorf("missing password")
|
||||
|
||||
@@ -16,8 +16,8 @@ const (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
AspUrl string
|
||||
AspPubkey *secp256k1.PublicKey
|
||||
ServerUrl string
|
||||
ServerPubKey *secp256k1.PublicKey
|
||||
WalletType string
|
||||
ClientType string
|
||||
Network common.Network
|
||||
|
||||
@@ -193,7 +193,7 @@ func (s *bitcoinWallet) SignTransaction(
|
||||
)
|
||||
|
||||
txsighashes := txscript.NewTxSigHashes(updater.Upsbt.UnsignedTx, prevoutFetcher)
|
||||
myPubkey := schnorr.SerializePubKey(s.walletData.Pubkey)
|
||||
myPubkey := schnorr.SerializePubKey(s.walletData.PubKey)
|
||||
|
||||
for i, input := range ptx.Inputs {
|
||||
if len(input.TaprootLeafScript) > 0 {
|
||||
@@ -246,7 +246,7 @@ func (s *bitcoinWallet) SignTransaction(
|
||||
return "", err
|
||||
}
|
||||
|
||||
if !sig.Verify(preimage, s.walletData.Pubkey) {
|
||||
if !sig.Verify(preimage, s.walletData.PubKey) {
|
||||
return "", fmt.Errorf("signature verification failed")
|
||||
}
|
||||
|
||||
@@ -308,8 +308,8 @@ func (w *bitcoinWallet) getAddress(
|
||||
netParams := utils.ToBitcoinNetwork(data.Network)
|
||||
|
||||
defaultVtxoScript := bitcointree.NewDefaultVtxoScript(
|
||||
w.walletData.Pubkey,
|
||||
data.AspPubkey,
|
||||
w.walletData.PubKey,
|
||||
data.ServerPubKey,
|
||||
uint(data.UnilateralExitDelay),
|
||||
)
|
||||
|
||||
@@ -320,13 +320,13 @@ func (w *bitcoinWallet) getAddress(
|
||||
|
||||
offchainAddress := &common.Address{
|
||||
HRP: data.Network.Addr,
|
||||
Asp: data.AspPubkey,
|
||||
Server: data.ServerPubKey,
|
||||
VtxoTapKey: vtxoTapKey,
|
||||
}
|
||||
|
||||
boardingVtxoScript := bitcointree.NewDefaultVtxoScript(
|
||||
w.walletData.Pubkey,
|
||||
data.AspPubkey,
|
||||
w.walletData.PubKey,
|
||||
data.ServerPubKey,
|
||||
uint(data.UnilateralExitDelay*2),
|
||||
)
|
||||
|
||||
|
||||
@@ -211,7 +211,7 @@ func (s *liquidWallet) SignTransaction(
|
||||
prevoutsAssets = append(prevoutsAssets, input.WitnessUtxo.Asset)
|
||||
}
|
||||
|
||||
myPubkey := schnorr.SerializePubKey(s.walletData.Pubkey)
|
||||
myPubkey := schnorr.SerializePubKey(s.walletData.PubKey)
|
||||
|
||||
for i, input := range pset.Inputs {
|
||||
if len(input.TapLeafScript) > 0 {
|
||||
@@ -265,7 +265,7 @@ func (s *liquidWallet) SignTransaction(
|
||||
|
||||
tapScriptSig := psetv2.TapScriptSig{
|
||||
PartialSig: psetv2.PartialSig{
|
||||
PubKey: schnorr.SerializePubKey(s.walletData.Pubkey),
|
||||
PubKey: schnorr.SerializePubKey(s.walletData.PubKey),
|
||||
Signature: sig.Serialize(),
|
||||
},
|
||||
LeafHash: hash.CloneBytes(),
|
||||
@@ -330,8 +330,8 @@ func (w *liquidWallet) getAddress(
|
||||
liquidNet := utils.ToElementsNetwork(data.Network)
|
||||
|
||||
vtxoScript := tree.NewDefaultVtxoScript(
|
||||
w.walletData.Pubkey,
|
||||
data.AspPubkey,
|
||||
w.walletData.PubKey,
|
||||
data.ServerPubKey,
|
||||
uint(data.UnilateralExitDelay),
|
||||
)
|
||||
|
||||
@@ -342,13 +342,13 @@ func (w *liquidWallet) getAddress(
|
||||
|
||||
offchainAddr := &common.Address{
|
||||
HRP: data.Network.Addr,
|
||||
Asp: data.AspPubkey,
|
||||
Server: data.ServerPubKey,
|
||||
VtxoTapKey: vtxoTapKey,
|
||||
}
|
||||
|
||||
boardingVtxoScript := tree.NewDefaultVtxoScript(
|
||||
w.walletData.Pubkey,
|
||||
data.AspPubkey,
|
||||
w.walletData.PubKey,
|
||||
data.ServerPubKey,
|
||||
uint(data.UnilateralExitDelay*2),
|
||||
)
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ const (
|
||||
type walletData struct {
|
||||
EncryptedPrvkey string `json:"encrypted_private_key"`
|
||||
PasswordHash string `json:"password_hash"`
|
||||
Pubkey string `json:"pubkey"`
|
||||
PubKey string `json:"pubkey"`
|
||||
}
|
||||
|
||||
func (d walletData) isEmpty() bool {
|
||||
@@ -30,12 +30,12 @@ func (d walletData) isEmpty() bool {
|
||||
func (d walletData) decode() walletstore.WalletData {
|
||||
encryptedPrvkey, _ := hex.DecodeString(d.EncryptedPrvkey)
|
||||
passwordHash, _ := hex.DecodeString(d.PasswordHash)
|
||||
buf, _ := hex.DecodeString(d.Pubkey)
|
||||
buf, _ := hex.DecodeString(d.PubKey)
|
||||
pubkey, _ := secp256k1.ParsePubKey(buf)
|
||||
return walletstore.WalletData{
|
||||
EncryptedPrvkey: encryptedPrvkey,
|
||||
PasswordHash: passwordHash,
|
||||
Pubkey: pubkey,
|
||||
PubKey: pubkey,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ func (d walletData) asMap() map[string]string {
|
||||
return map[string]string{
|
||||
"encrypted_private_key": d.EncryptedPrvkey,
|
||||
"password_hash": d.PasswordHash,
|
||||
"pubkey": d.Pubkey,
|
||||
"pubkey": d.PubKey,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ func (s *fileStore) AddWallet(data walletstore.WalletData) error {
|
||||
wd := &walletData{
|
||||
EncryptedPrvkey: hex.EncodeToString(data.EncryptedPrvkey),
|
||||
PasswordHash: hex.EncodeToString(data.PasswordHash),
|
||||
Pubkey: hex.EncodeToString(data.Pubkey.SerializeCompressed()),
|
||||
PubKey: hex.EncodeToString(data.PubKey.SerializeCompressed()),
|
||||
}
|
||||
|
||||
if err := s.write(wd); err != nil {
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
type WalletData struct {
|
||||
EncryptedPrvkey []byte
|
||||
PasswordHash []byte
|
||||
Pubkey *secp256k1.PublicKey
|
||||
PubKey *secp256k1.PublicKey
|
||||
}
|
||||
|
||||
type WalletStore interface {
|
||||
|
||||
@@ -16,7 +16,7 @@ func TestWalletStore(t *testing.T) {
|
||||
testWalletData := walletstore.WalletData{
|
||||
EncryptedPrvkey: make([]byte, 32),
|
||||
PasswordHash: make([]byte, 32),
|
||||
Pubkey: key.PubKey(),
|
||||
PubKey: key.PubKey(),
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
|
||||
@@ -29,18 +29,18 @@ func (w *singlekeyWallet) Create(
|
||||
) (string, error) {
|
||||
var privateKey *secp256k1.PrivateKey
|
||||
if len(seed) <= 0 {
|
||||
privKey, err := utils.GenerateRandomPrivateKey()
|
||||
prvkey, err := utils.GenerateRandomPrivateKey()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
privateKey = privKey
|
||||
privateKey = prvkey
|
||||
} else {
|
||||
privKeyBytes, err := hex.DecodeString(seed)
|
||||
prvkeyBytes, err := hex.DecodeString(seed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
privateKey = secp256k1.PrivKeyFromBytes(privKeyBytes)
|
||||
privateKey = secp256k1.PrivKeyFromBytes(prvkeyBytes)
|
||||
}
|
||||
|
||||
pwd := []byte(password)
|
||||
@@ -55,7 +55,7 @@ func (w *singlekeyWallet) Create(
|
||||
walletData := walletstore.WalletData{
|
||||
EncryptedPrvkey: encryptedPrivateKey,
|
||||
PasswordHash: passwordHash,
|
||||
Pubkey: pubkey,
|
||||
PubKey: pubkey,
|
||||
}
|
||||
if err := w.walletStore.AddWallet(walletData); err != nil {
|
||||
return "", err
|
||||
|
||||
@@ -21,8 +21,8 @@ func TestWallet(t *testing.T) {
|
||||
key, _ := btcec.NewPrivateKey()
|
||||
password := "password"
|
||||
testStoreData := sdktypes.Config{
|
||||
AspUrl: "localhost:7070",
|
||||
AspPubkey: key.PubKey(),
|
||||
ServerUrl: "localhost:7070",
|
||||
ServerPubKey: key.PubKey(),
|
||||
WalletType: wallet.SingleKeyWallet,
|
||||
ClientType: client.GrpcClient,
|
||||
Network: common.LiquidRegTest,
|
||||
|
||||
@@ -21,8 +21,8 @@ const (
|
||||
)
|
||||
|
||||
type storeData struct {
|
||||
AspUrl string `json:"asp_url"`
|
||||
AspPubkey string `json:"asp_pubkey"`
|
||||
ServerUrl string `json:"server_url"`
|
||||
ServerPubKey string `json:"server_pubkey"`
|
||||
WalletType string `json:"wallet_type"`
|
||||
ClientType string `json:"client_type"`
|
||||
ExplorerURL string `json:"explorer_url"`
|
||||
@@ -54,8 +54,8 @@ func (s *configStore) GetDatadir() string {
|
||||
|
||||
func (s *configStore) AddData(ctx context.Context, data types.Config) error {
|
||||
sd := &storeData{
|
||||
AspUrl: data.AspUrl,
|
||||
AspPubkey: hex.EncodeToString(data.AspPubkey.SerializeCompressed()),
|
||||
ServerUrl: data.ServerUrl,
|
||||
ServerPubKey: hex.EncodeToString(data.ServerPubKey.SerializeCompressed()),
|
||||
WalletType: data.WalletType,
|
||||
ClientType: data.ClientType,
|
||||
Network: data.Network.Name,
|
||||
@@ -71,7 +71,7 @@ func (s *configStore) AddData(ctx context.Context, data types.Config) error {
|
||||
}
|
||||
|
||||
func (s *configStore) GetData(ctx context.Context) (*types.Config, error) {
|
||||
key := s.store.Call("getItem", "asp_pubkey")
|
||||
key := s.store.Call("getItem", "server_pubkey")
|
||||
if key.IsNull() || key.IsUndefined() {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -83,7 +83,7 @@ func (s *configStore) GetData(ctx context.Context) (*types.Config, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
aspPubkey, err := secp256k1.ParsePubKey(buf)
|
||||
serverPubkey, err := secp256k1.ParsePubKey(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -95,8 +95,8 @@ func (s *configStore) GetData(ctx context.Context) (*types.Config, error) {
|
||||
withTxFeed, _ := strconv.ParseBool(s.store.Call("getItem", "with_transaction_feed").String())
|
||||
|
||||
return &types.Config{
|
||||
AspUrl: s.store.Call("getItem", "asp_url").String(),
|
||||
AspPubkey: aspPubkey,
|
||||
ServerUrl: s.store.Call("getItem", "server_url").String(),
|
||||
ServerPubKey: serverPubkey,
|
||||
WalletType: s.store.Call("getItem", "wallet_type").String(),
|
||||
ClientType: s.store.Call("getItem", "client_type").String(),
|
||||
Network: network,
|
||||
|
||||
@@ -30,7 +30,6 @@ func init() {
|
||||
js.Global().Set("receive", ReceiveWrapper())
|
||||
js.Global().Set("sendOnChain", SendOnChainWrapper())
|
||||
js.Global().Set("sendOffChain", SendOffChainWrapper())
|
||||
js.Global().Set("sendAsync", SendAsyncWrapper())
|
||||
js.Global().Set("settle", SettleWrapper())
|
||||
js.Global().Set("unilateralRedeem", UnilateralRedeemWrapper())
|
||||
js.Global().Set("collaborativeRedeem", CollaborativeRedeemWrapper())
|
||||
@@ -41,8 +40,8 @@ func init() {
|
||||
js.Global().Set("setNostrNotificationRecipient", SetNostrNotificationRecipientWrapper())
|
||||
js.Global().Set("listVtxos", ListVtxosWrapper())
|
||||
|
||||
js.Global().Set("getAspUrl", GetAspUrlWrapper())
|
||||
js.Global().Set("getAspPubKeyHex", GetAspPubkeyWrapper())
|
||||
js.Global().Set("getServerUrl", GetServerUrlWrapper())
|
||||
js.Global().Set("getServerPubkeyHex", GetServerPubkeyWrapper())
|
||||
js.Global().Set("getWalletType", GetWalletTypeWrapper())
|
||||
js.Global().Set("getClientType", GetClientTypeWrapper())
|
||||
js.Global().Set("getNetwork", GetNetworkWrapper())
|
||||
|
||||
@@ -16,18 +16,18 @@ import (
|
||||
type walletData struct {
|
||||
EncryptedPrvkey string `json:"encrypted_private_key"`
|
||||
PasswordHash string `json:"password_hash"`
|
||||
Pubkey string `json:"pubkey"`
|
||||
PubKey string `json:"pubkey"`
|
||||
}
|
||||
|
||||
func (d walletData) decode() *walletstore.WalletData {
|
||||
encryptedPrvkey, _ := hex.DecodeString(d.EncryptedPrvkey)
|
||||
passwordHash, _ := hex.DecodeString(d.PasswordHash)
|
||||
buf, _ := hex.DecodeString(d.Pubkey)
|
||||
buf, _ := hex.DecodeString(d.PubKey)
|
||||
pubkey, _ := secp256k1.ParsePubKey(buf)
|
||||
return &walletstore.WalletData{
|
||||
EncryptedPrvkey: encryptedPrvkey,
|
||||
PasswordHash: passwordHash,
|
||||
Pubkey: pubkey,
|
||||
PubKey: pubkey,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ func (s *walletStore) AddWallet(data walletstore.WalletData) error {
|
||||
wd := &walletData{
|
||||
EncryptedPrvkey: hex.EncodeToString(data.EncryptedPrvkey),
|
||||
PasswordHash: hex.EncodeToString(data.PasswordHash),
|
||||
Pubkey: hex.EncodeToString(data.Pubkey.SerializeCompressed()),
|
||||
PubKey: hex.EncodeToString(data.PubKey.SerializeCompressed()),
|
||||
}
|
||||
|
||||
if err := s.writeData(wd); err != nil {
|
||||
@@ -57,7 +57,7 @@ func (s *walletStore) GetWallet() (*walletstore.WalletData, error) {
|
||||
data := walletData{
|
||||
EncryptedPrvkey: s.store.Call("getItem", "encrypted_private_key").String(),
|
||||
PasswordHash: s.store.Call("getItem", "password_hash").String(),
|
||||
Pubkey: s.store.Call("getItem", "pubkey").String(),
|
||||
PubKey: s.store.Call("getItem", "pubkey").String(),
|
||||
}
|
||||
return data.decode(), nil
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ func InitWrapper() js.Func {
|
||||
err := arkSdkClient.InitWithWallet(context.Background(), arksdk.InitWithWalletArgs{
|
||||
ClientType: args[1].String(),
|
||||
Wallet: walletSvc,
|
||||
AspUrl: args[2].String(),
|
||||
ServerUrl: args[2].String(),
|
||||
Seed: args[3].String(),
|
||||
Password: args[4].String(),
|
||||
ExplorerURL: args[6].String(),
|
||||
@@ -227,28 +227,6 @@ func SendOnChainWrapper() js.Func {
|
||||
}
|
||||
|
||||
func SendOffChainWrapper() js.Func {
|
||||
return JSPromise(func(args []js.Value) (interface{}, error) {
|
||||
if len(args) != 2 {
|
||||
return nil, errors.New("invalid number of args")
|
||||
}
|
||||
|
||||
withExpiryCoinselect := args[0].Bool()
|
||||
receivers, err := parseReceivers(args[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txID, err := arkSdkClient.SendOffChain(
|
||||
context.Background(), withExpiryCoinselect, receivers,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return js.ValueOf(txID), nil
|
||||
})
|
||||
}
|
||||
|
||||
func SendAsyncWrapper() js.Func {
|
||||
return JSPromise(func(args []js.Value) (interface{}, error) {
|
||||
if len(args) != 2 {
|
||||
return nil, errors.New("invalid number of args")
|
||||
@@ -260,11 +238,7 @@ func SendAsyncWrapper() js.Func {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if receivers == nil || len(receivers) == 0 {
|
||||
return nil, errors.New("no receivers specified")
|
||||
}
|
||||
|
||||
txID, err := arkSdkClient.SendAsync(
|
||||
txID, err := arkSdkClient.SendOffChain(
|
||||
context.Background(), withExpiryCoinselect, receivers,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -340,25 +314,25 @@ func GetTransactionHistoryWrapper() js.Func {
|
||||
})
|
||||
}
|
||||
|
||||
func GetAspUrlWrapper() js.Func {
|
||||
func GetServerUrlWrapper() js.Func {
|
||||
return js.FuncOf(func(this js.Value, p []js.Value) interface{} {
|
||||
data, _ := arkSdkClient.GetConfigData(context.Background())
|
||||
var url string
|
||||
if data != nil {
|
||||
url = data.AspUrl
|
||||
url = data.ServerUrl
|
||||
}
|
||||
return js.ValueOf(url)
|
||||
})
|
||||
}
|
||||
|
||||
func GetAspPubkeyWrapper() js.Func {
|
||||
func GetServerPubkeyWrapper() js.Func {
|
||||
return js.FuncOf(func(this js.Value, p []js.Value) interface{} {
|
||||
data, _ := arkSdkClient.GetConfigData(context.Background())
|
||||
var aspPubkey string
|
||||
var serverPubkey string
|
||||
if data != nil {
|
||||
aspPubkey = hex.EncodeToString(data.AspPubkey.SerializeCompressed())
|
||||
serverPubkey = hex.EncodeToString(data.ServerPubKey.SerializeCompressed())
|
||||
}
|
||||
return js.ValueOf(aspPubkey)
|
||||
return js.ValueOf(serverPubkey)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Ark Server
|
||||
The Ark Server is a Go implementation of an Ark Service Provider (ASP). An ASP it's an always-on server that provides bitcoin liquidity in the Ark layer-two protocol. It supports Bitcoin and Liquid (with more experimantal features using covenants).
|
||||
This is a Go implementation of the Ark server. An Ark server it's an always-on server that provides bitcoin liquidity in the Ark layer-two protocol. It supports Bitcoin and Liquid (with more experimantal features using covenants).
|
||||
|
||||
**ALPHA STAGE SOFTWARE: USE AT YOUR OWN RISK!**
|
||||
|
||||
|
||||
@@ -89,11 +89,11 @@ func (a *adminService) GetRoundDetails(ctx context.Context, roundId string) (*Ro
|
||||
OutputsVtxos: []string{},
|
||||
}
|
||||
|
||||
for _, payment := range round.Payments {
|
||||
for _, request := range round.TxRequests {
|
||||
// TODO: Add fees amount
|
||||
roundDetails.ForfeitedAmount += payment.TotalInputAmount()
|
||||
roundDetails.ForfeitedAmount += request.TotalInputAmount()
|
||||
|
||||
for _, receiver := range payment.Receivers {
|
||||
for _, receiver := range request.Receivers {
|
||||
if receiver.IsOnchain() {
|
||||
roundDetails.TotalExitAmount += receiver.Amount
|
||||
roundDetails.ExitAddresses = append(roundDetails.ExitAddresses, receiver.OnchainAddress)
|
||||
@@ -103,7 +103,7 @@ func (a *adminService) GetRoundDetails(ctx context.Context, roundId string) (*Ro
|
||||
roundDetails.TotalVtxosAmount += receiver.Amount
|
||||
}
|
||||
|
||||
for _, input := range payment.Inputs {
|
||||
for _, input := range request.Inputs {
|
||||
roundDetails.InputsVtxos = append(roundDetails.InputsVtxos, input.Txid)
|
||||
}
|
||||
}
|
||||
@@ -134,7 +134,7 @@ func (a *adminService) GetScheduledSweeps(ctx context.Context) ([]ScheduledSweep
|
||||
|
||||
for _, round := range sweepableRounds {
|
||||
sweepable, err := findSweepableOutputs(
|
||||
ctx, a.walletSvc, a.txBuilder, a.sweeperTimeUnit, round.CongestionTree,
|
||||
ctx, a.walletSvc, a.txBuilder, a.sweeperTimeUnit, round.VtxoTree,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -44,7 +44,7 @@ type covenantService struct {
|
||||
scanner ports.BlockchainScanner
|
||||
sweeper *sweeper
|
||||
|
||||
paymentRequests *paymentsMap
|
||||
txRequests *txRequestsQueue
|
||||
forfeitTxs *forfeitTxsMap
|
||||
|
||||
eventsCh chan domain.RoundEvent
|
||||
@@ -94,7 +94,7 @@ func NewCovenantService(
|
||||
builder: builder,
|
||||
scanner: scanner,
|
||||
sweeper: newSweeper(walletSvc, repoManager, builder, scheduler, notificationPrefix),
|
||||
paymentRequests: newPaymentsMap(),
|
||||
txRequests: newTxRequestsQueue(),
|
||||
forfeitTxs: newForfeitTxsMap(builder),
|
||||
eventsCh: make(chan domain.RoundEvent),
|
||||
transactionEventsCh: make(chan TransactionEvent),
|
||||
@@ -287,14 +287,14 @@ func (s *covenantService) SpendVtxos(ctx context.Context, inputs []ports.Input)
|
||||
vtxosInputs = append(vtxosInputs, vtxo)
|
||||
}
|
||||
|
||||
payment, err := domain.NewPayment(vtxosInputs)
|
||||
request, err := domain.NewTxRequest(vtxosInputs)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := s.paymentRequests.push(*payment, boardingInputs); err != nil {
|
||||
if err := s.txRequests.push(*request, boardingInputs); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return payment.Id, nil
|
||||
return request.Id, nil
|
||||
}
|
||||
|
||||
func (s *covenantService) newBoardingInput(tx *transaction.Transaction, input ports.Input) (*ports.BoardingInput, error) {
|
||||
@@ -344,7 +344,7 @@ func (s *covenantService) newBoardingInput(tx *transaction.Transaction, input po
|
||||
|
||||
func (s *covenantService) ClaimVtxos(ctx context.Context, creds string, receivers []domain.Receiver) error {
|
||||
// Check credentials
|
||||
payment, ok := s.paymentRequests.view(creds)
|
||||
request, ok := s.txRequests.view(creds)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid credentials")
|
||||
}
|
||||
@@ -360,14 +360,14 @@ func (s *covenantService) ClaimVtxos(ctx context.Context, creds string, receiver
|
||||
}
|
||||
}
|
||||
|
||||
if err := payment.AddReceivers(receivers); err != nil {
|
||||
if err := request.AddReceivers(receivers); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.paymentRequests.update(*payment)
|
||||
return s.txRequests.update(*request)
|
||||
}
|
||||
|
||||
func (s *covenantService) UpdatePaymentStatus(_ context.Context, id string) error {
|
||||
return s.paymentRequests.updatePingTimestamp(id)
|
||||
func (s *covenantService) UpdateTxRequestStatus(_ context.Context, id string) error {
|
||||
return s.txRequests.updatePingTimestamp(id)
|
||||
}
|
||||
|
||||
func (s *covenantService) SubmitRedeemTx(context.Context, string) (string, error) {
|
||||
@@ -397,7 +397,7 @@ func (s *covenantService) ListVtxos(ctx context.Context, address string) ([]doma
|
||||
return nil, nil, fmt.Errorf("failed to decode address: %s", err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(schnorr.SerializePubKey(decodedAddress.Asp), schnorr.SerializePubKey(s.pubkey)) {
|
||||
if !bytes.Equal(schnorr.SerializePubKey(decodedAddress.Server), schnorr.SerializePubKey(s.pubkey)) {
|
||||
return nil, nil, fmt.Errorf("address does not match server pubkey")
|
||||
}
|
||||
|
||||
@@ -414,8 +414,8 @@ func (s *covenantService) GetTransactionEventsChannel(ctx context.Context) <-cha
|
||||
return s.transactionEventsCh
|
||||
}
|
||||
|
||||
func (s *covenantService) GetRoundByTxid(ctx context.Context, poolTxid string) (*domain.Round, error) {
|
||||
return s.repoManager.Rounds().GetRoundWithTxid(ctx, poolTxid)
|
||||
func (s *covenantService) GetRoundByTxid(ctx context.Context, roundTxid string) (*domain.Round, error) {
|
||||
return s.repoManager.Rounds().GetRoundWithTxid(ctx, roundTxid)
|
||||
}
|
||||
|
||||
func (s *covenantService) GetCurrentRound(ctx context.Context) (*domain.Round, error) {
|
||||
@@ -472,11 +472,11 @@ func (s *covenantService) GetInfo(ctx context.Context) (*ServiceInfo, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *covenantService) RegisterCosignerPubkey(ctx context.Context, paymentId string, _ string) error {
|
||||
func (s *covenantService) RegisterCosignerPubkey(ctx context.Context, requestID string, _ string) error {
|
||||
// if the user sends an ephemeral pubkey, something is going wrong client-side
|
||||
// we should delete the associated payment
|
||||
if err := s.paymentRequests.delete(paymentId); err != nil {
|
||||
log.WithError(err).Warn("failed to delete payment")
|
||||
// we should delete the associated tx request
|
||||
if err := s.txRequests.delete(requestID); err != nil {
|
||||
log.WithError(err).Warnf("failed to delete tx request %s", requestID)
|
||||
}
|
||||
|
||||
return ErrTreeSigningNotRequired
|
||||
@@ -554,22 +554,22 @@ func (s *covenantService) startFinalization() {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: understand how many payments must be popped from the queue and actually registered for the round
|
||||
num := s.paymentRequests.len()
|
||||
// TODO: understand how many tx requests must be popped from the queue and actually registered for the round
|
||||
num := s.txRequests.len()
|
||||
if num == 0 {
|
||||
roundAborted = true
|
||||
err := fmt.Errorf("no payments registered")
|
||||
err := fmt.Errorf("no tx requests registered")
|
||||
round.Fail(fmt.Errorf("round aborted: %s", err))
|
||||
log.WithError(err).Debugf("round %s aborted", round.Id)
|
||||
return
|
||||
}
|
||||
if num > paymentsThreshold {
|
||||
num = paymentsThreshold
|
||||
if num > txRequestsThreshold {
|
||||
num = txRequestsThreshold
|
||||
}
|
||||
payments, boardingInputs, _, _ := s.paymentRequests.pop(num)
|
||||
if _, err := round.RegisterPayments(payments); err != nil {
|
||||
round.Fail(fmt.Errorf("failed to register payments: %s", err))
|
||||
log.WithError(err).Warn("failed to register payments")
|
||||
requests, boardingInputs, _, _ := s.txRequests.pop(num)
|
||||
if _, err := round.RegisterTxRequests(requests); err != nil {
|
||||
round.Fail(fmt.Errorf("failed to register tx requests: %s", err))
|
||||
log.WithError(err).Warn("failed to register tx requests")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -580,18 +580,18 @@ func (s *covenantService) startFinalization() {
|
||||
return
|
||||
}
|
||||
|
||||
unsignedPoolTx, tree, connectorAddress, connectors, err := s.builder.BuildRoundTx(s.pubkey, payments, boardingInputs, sweptRounds)
|
||||
unsignedRoundTx, tree, connectorAddress, connectors, err := s.builder.BuildRoundTx(s.pubkey, requests, boardingInputs, sweptRounds)
|
||||
if err != nil {
|
||||
round.Fail(fmt.Errorf("failed to create pool tx: %s", err))
|
||||
log.WithError(err).Warn("failed to create pool tx")
|
||||
round.Fail(fmt.Errorf("failed to create round tx: %s", err))
|
||||
log.WithError(err).Warn("failed to create round tx")
|
||||
return
|
||||
}
|
||||
log.Debugf("pool tx created for round %s", round.Id)
|
||||
log.Debugf("round tx created for round %s", round.Id)
|
||||
|
||||
s.forfeitTxs.init(connectors, payments)
|
||||
s.forfeitTxs.init(connectors, requests)
|
||||
|
||||
if _, err := round.StartFinalization(
|
||||
connectorAddress, connectors, tree, unsignedPoolTx,
|
||||
connectorAddress, connectors, tree, unsignedRoundTx,
|
||||
); err != nil {
|
||||
round.Fail(fmt.Errorf("failed to start finalization: %s", err))
|
||||
log.WithError(err).Warn("failed to start finalization")
|
||||
@@ -670,8 +670,8 @@ func (s *covenantService) finalizeRound() {
|
||||
txid, err := s.wallet.BroadcastTransaction(ctx, signedRoundTx)
|
||||
if err != nil {
|
||||
log.Debugf("failed to broadcast round tx: %s", signedRoundTx)
|
||||
changes = round.Fail(fmt.Errorf("failed to broadcast pool tx: %s", err))
|
||||
log.WithError(err).Warn("failed to broadcast pool tx")
|
||||
changes = round.Fail(fmt.Errorf("failed to broadcast round tx: %s", err))
|
||||
log.WithError(err).Warn("failed to broadcast round tx")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -682,7 +682,7 @@ func (s *covenantService) finalizeRound() {
|
||||
return
|
||||
}
|
||||
|
||||
log.Debugf("finalized round %s with pool tx %s", round.Id, round.Txid)
|
||||
log.Debugf("finalized round %s with round tx %s", round.Id, round.Txid)
|
||||
}
|
||||
|
||||
func (s *covenantService) listenToScannerNotifications() {
|
||||
@@ -906,7 +906,7 @@ func (s *covenantService) updateVtxoSet(round *domain.Round) {
|
||||
|
||||
ctx := context.Background()
|
||||
repo := s.repoManager.Vtxos()
|
||||
spentVtxos := getSpentVtxos(round.Payments)
|
||||
spentVtxos := getSpentVtxos(round.TxRequests)
|
||||
if len(spentVtxos) > 0 {
|
||||
for {
|
||||
if err := repo.SpendVtxos(ctx, spentVtxos, round.Txid); err != nil {
|
||||
@@ -970,8 +970,8 @@ func (s *covenantService) updateVtxoSet(round *domain.Round) {
|
||||
}
|
||||
}
|
||||
s.transactionEventsCh <- RoundTransactionEvent{
|
||||
RoundTxID: round.Txid,
|
||||
SpentVtxos: getSpentVtxos(round.Payments),
|
||||
RoundTxid: round.Txid,
|
||||
SpentVtxos: getSpentVtxos(round.TxRequests),
|
||||
SpendableVtxos: s.getNewVtxos(round),
|
||||
ClaimedBoardingInputs: boardingInputs,
|
||||
}
|
||||
@@ -984,7 +984,7 @@ func (s *covenantService) propagateEvents(round *domain.Round) {
|
||||
case domain.RoundFinalizationStarted:
|
||||
ev := domain.RoundFinalizationStarted{
|
||||
Id: e.Id,
|
||||
CongestionTree: e.CongestionTree,
|
||||
VtxoTree: e.VtxoTree,
|
||||
Connectors: e.Connectors,
|
||||
RoundTx: e.RoundTx,
|
||||
MinRelayFeeRate: int64(s.wallet.MinRelayFeeRate(context.Background())),
|
||||
@@ -1006,20 +1006,20 @@ func (s *covenantService) scheduleSweepVtxosForRound(round *domain.Round) {
|
||||
expirationTime := s.sweeper.scheduler.AddNow(s.roundLifetime)
|
||||
|
||||
if err := s.sweeper.schedule(
|
||||
expirationTime, round.Txid, round.CongestionTree,
|
||||
expirationTime, round.Txid, round.VtxoTree,
|
||||
); err != nil {
|
||||
log.WithError(err).Warn("failed to schedule sweep tx")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *covenantService) getNewVtxos(round *domain.Round) []domain.Vtxo {
|
||||
if len(round.CongestionTree) <= 0 {
|
||||
if len(round.VtxoTree) <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
createdAt := time.Now().Unix()
|
||||
|
||||
leaves := round.CongestionTree.Leaves()
|
||||
leaves := round.VtxoTree.Leaves()
|
||||
vtxos := make([]domain.Vtxo, 0)
|
||||
for _, node := range leaves {
|
||||
tx, _ := psetv2.NewPsetFromBase64(node.Tx)
|
||||
@@ -1038,7 +1038,7 @@ func (s *covenantService) getNewVtxos(round *domain.Round) []domain.Vtxo {
|
||||
|
||||
vtxos = append(vtxos, domain.Vtxo{
|
||||
VtxoKey: domain.VtxoKey{Txid: node.Txid, VOut: uint32(i)},
|
||||
Pubkey: vtxoPubkey,
|
||||
PubKey: vtxoPubkey,
|
||||
Amount: uint64(out.Value),
|
||||
RoundTxid: round.Txid,
|
||||
CreatedAt: createdAt,
|
||||
@@ -1113,7 +1113,7 @@ func (s *covenantService) restoreWatchingVtxos() error {
|
||||
func (s *covenantService) extractVtxosScripts(vtxos []domain.Vtxo) ([]string, error) {
|
||||
indexedScripts := make(map[string]struct{})
|
||||
for _, vtxo := range vtxos {
|
||||
vtxoTapKeyBytes, err := hex.DecodeString(vtxo.Pubkey)
|
||||
vtxoTapKeyBytes, err := hex.DecodeString(vtxo.PubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ type covenantlessService struct {
|
||||
scanner ports.BlockchainScanner
|
||||
sweeper *sweeper
|
||||
|
||||
paymentRequests *paymentsMap
|
||||
txRequests *txRequestsQueue
|
||||
forfeitTxs *forfeitTxsMap
|
||||
|
||||
eventsCh chan domain.RoundEvent
|
||||
@@ -99,7 +99,7 @@ func NewCovenantlessService(
|
||||
builder: builder,
|
||||
scanner: scanner,
|
||||
sweeper: newSweeper(walletSvc, repoManager, builder, scheduler, noteUriPrefix),
|
||||
paymentRequests: newPaymentsMap(),
|
||||
txRequests: newTxRequestsQueue(),
|
||||
forfeitTxs: newForfeitTxsMap(builder),
|
||||
eventsCh: make(chan domain.RoundEvent),
|
||||
transactionEventsCh: make(chan TransactionEvent),
|
||||
@@ -260,37 +260,37 @@ func (s *covenantlessService) SubmitRedeemTx(
|
||||
}
|
||||
|
||||
// verify that the user signs a forfeit closure
|
||||
var userPubKey *secp256k1.PublicKey
|
||||
var userPubkey *secp256k1.PublicKey
|
||||
|
||||
aspXOnlyPubKey := schnorr.SerializePubKey(s.pubkey)
|
||||
serverXOnlyPubkey := schnorr.SerializePubKey(s.pubkey)
|
||||
|
||||
for _, sig := range input.TaprootScriptSpendSig {
|
||||
if !bytes.Equal(sig.XOnlyPubKey, aspXOnlyPubKey) {
|
||||
if !bytes.Equal(sig.XOnlyPubKey, serverXOnlyPubkey) {
|
||||
parsed, err := schnorr.ParsePubKey(sig.XOnlyPubKey)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to parse pubkey: %s", err)
|
||||
}
|
||||
userPubKey = parsed
|
||||
userPubkey = parsed
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if userPubKey == nil {
|
||||
if userPubkey == nil {
|
||||
return "", fmt.Errorf("redeem transaction is not signed")
|
||||
}
|
||||
|
||||
vtxoPublicKeyBytes, err := hex.DecodeString(vtxo.Pubkey)
|
||||
vtxoPubkeyBuf, err := hex.DecodeString(vtxo.PubKey)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to decode vtxo pubkey: %s", err)
|
||||
}
|
||||
|
||||
vtxoTapKey, err := schnorr.ParsePubKey(vtxoPublicKeyBytes)
|
||||
vtxoPubkey, err := schnorr.ParsePubKey(vtxoPubkeyBuf)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to parse vtxo pubkey: %s", err)
|
||||
}
|
||||
|
||||
// verify witness utxo
|
||||
pkscript, err := common.P2TRScript(vtxoTapKey)
|
||||
pkscript, err := common.P2TRScript(vtxoPubkey)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get pkscript: %s", err)
|
||||
}
|
||||
@@ -378,8 +378,15 @@ func (s *covenantlessService) SubmitRedeemTx(
|
||||
return "", fmt.Errorf("no valid vtxo found")
|
||||
}
|
||||
|
||||
newVtxos := make([]domain.Vtxo, 0, len(redeemPtx.UnsignedTx.TxOut))
|
||||
// sign the redeem tx
|
||||
|
||||
signedRedeemTx, err := s.wallet.SignTransactionTapscript(ctx, redeemTx, nil)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to sign redeem tx: %s", err)
|
||||
}
|
||||
|
||||
// Create new vtxos, update spent vtxos state
|
||||
newVtxos := make([]domain.Vtxo, 0, len(redeemPtx.UnsignedTx.TxOut))
|
||||
for outIndex, out := range outputs {
|
||||
vtxoTapKey, err := schnorr.ParsePubKey(out.PkScript[2:])
|
||||
if err != nil {
|
||||
@@ -393,24 +400,15 @@ func (s *covenantlessService) SubmitRedeemTx(
|
||||
Txid: redeemTxid,
|
||||
VOut: uint32(outIndex),
|
||||
},
|
||||
Pubkey: vtxoPubkey,
|
||||
PubKey: vtxoPubkey,
|
||||
Amount: uint64(out.Value),
|
||||
ExpireAt: expiration,
|
||||
RoundTxid: roundTxid,
|
||||
RedeemTx: redeemTx,
|
||||
RedeemTx: signedRedeemTx,
|
||||
CreatedAt: time.Now().Unix(),
|
||||
})
|
||||
}
|
||||
|
||||
// sign the redeem tx
|
||||
|
||||
signedRedeemTx, err := s.wallet.SignTransactionTapscript(ctx, redeemTx, nil)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to sign redeem tx: %s", err)
|
||||
}
|
||||
|
||||
// create new vtxos, update spent vtxos state
|
||||
|
||||
if err := s.repoManager.Vtxos().AddVtxos(ctx, newVtxos); err != nil {
|
||||
return "", fmt.Errorf("failed to add vtxos: %s", err)
|
||||
}
|
||||
@@ -429,7 +427,7 @@ func (s *covenantlessService) SubmitRedeemTx(
|
||||
|
||||
go func() {
|
||||
s.transactionEventsCh <- RedeemTransactionEvent{
|
||||
AsyncTxID: redeemTxid,
|
||||
RedeemTxid: redeemTxid,
|
||||
SpentVtxos: spentVtxoKeys,
|
||||
SpendableVtxos: newVtxos,
|
||||
}
|
||||
@@ -492,16 +490,16 @@ func (s *covenantlessService) SpendNotes(ctx context.Context, notes []note.Note)
|
||||
}
|
||||
}
|
||||
|
||||
payment, err := domain.NewPayment(make([]domain.Vtxo, 0))
|
||||
request, err := domain.NewTxRequest(make([]domain.Vtxo, 0))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create payment: %s", err)
|
||||
return "", fmt.Errorf("failed to create tx request: %s", err)
|
||||
}
|
||||
|
||||
if err := s.paymentRequests.pushWithNotes(*payment, notes); err != nil {
|
||||
return "", fmt.Errorf("failed to push payment: %s", err)
|
||||
if err := s.txRequests.pushWithNotes(*request, notes); err != nil {
|
||||
return "", fmt.Errorf("failed to push tx requests: %s", err)
|
||||
}
|
||||
|
||||
return payment.Id, nil
|
||||
return request.Id, nil
|
||||
}
|
||||
|
||||
func (s *covenantlessService) SpendVtxos(ctx context.Context, inputs []ports.Input) (string, error) {
|
||||
@@ -600,14 +598,14 @@ func (s *covenantlessService) SpendVtxos(ctx context.Context, inputs []ports.Inp
|
||||
vtxosInputs = append(vtxosInputs, vtxo)
|
||||
}
|
||||
|
||||
payment, err := domain.NewPayment(vtxosInputs)
|
||||
request, err := domain.NewTxRequest(vtxosInputs)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := s.paymentRequests.push(*payment, boardingInputs); err != nil {
|
||||
if err := s.txRequests.push(*request, boardingInputs); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return payment.Id, nil
|
||||
return request.Id, nil
|
||||
}
|
||||
|
||||
func (s *covenantlessService) newBoardingInput(tx wire.MsgTx, input ports.Input) (*ports.BoardingInput, error) {
|
||||
@@ -627,12 +625,12 @@ func (s *covenantlessService) newBoardingInput(tx wire.MsgTx, input ports.Input)
|
||||
return nil, fmt.Errorf("failed to get taproot key: %s", err)
|
||||
}
|
||||
|
||||
expectedScriptPubKey, err := common.P2TRScript(tapKey)
|
||||
expectedScriptPubkey, err := common.P2TRScript(tapKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get script pubkey: %s", err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(output.PkScript, expectedScriptPubKey) {
|
||||
if !bytes.Equal(output.PkScript, expectedScriptPubkey) {
|
||||
return nil, fmt.Errorf("descriptor does not match script in transaction output")
|
||||
}
|
||||
|
||||
@@ -648,7 +646,7 @@ func (s *covenantlessService) newBoardingInput(tx wire.MsgTx, input ports.Input)
|
||||
|
||||
func (s *covenantlessService) ClaimVtxos(ctx context.Context, creds string, receivers []domain.Receiver) error {
|
||||
// Check credentials
|
||||
payment, ok := s.paymentRequests.view(creds)
|
||||
request, ok := s.txRequests.view(creds)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid credentials")
|
||||
}
|
||||
@@ -664,14 +662,14 @@ func (s *covenantlessService) ClaimVtxos(ctx context.Context, creds string, rece
|
||||
}
|
||||
}
|
||||
|
||||
if err := payment.AddReceivers(receivers); err != nil {
|
||||
if err := request.AddReceivers(receivers); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.paymentRequests.update(*payment)
|
||||
return s.txRequests.update(*request)
|
||||
}
|
||||
|
||||
func (s *covenantlessService) UpdatePaymentStatus(_ context.Context, id string) error {
|
||||
return s.paymentRequests.updatePingTimestamp(id)
|
||||
func (s *covenantlessService) UpdateTxRequestStatus(_ context.Context, id string) error {
|
||||
return s.txRequests.updatePingTimestamp(id)
|
||||
}
|
||||
|
||||
func (s *covenantlessService) SignVtxos(ctx context.Context, forfeitTxs []string) error {
|
||||
@@ -697,7 +695,7 @@ func (s *covenantlessService) ListVtxos(ctx context.Context, address string) ([]
|
||||
return nil, nil, fmt.Errorf("failed to decode address: %s", err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(schnorr.SerializePubKey(decodedAddress.Asp), schnorr.SerializePubKey(s.pubkey)) {
|
||||
if !bytes.Equal(schnorr.SerializePubKey(decodedAddress.Server), schnorr.SerializePubKey(s.pubkey)) {
|
||||
return nil, nil, fmt.Errorf("address does not match server pubkey")
|
||||
}
|
||||
|
||||
@@ -818,18 +816,18 @@ func calcNextMarketHour(marketHourStartTime, marketHourEndTime time.Time, period
|
||||
}
|
||||
}
|
||||
|
||||
func (s *covenantlessService) RegisterCosignerPubkey(ctx context.Context, paymentId string, pubkey string) error {
|
||||
func (s *covenantlessService) RegisterCosignerPubkey(ctx context.Context, requestID string, pubkey string) error {
|
||||
pubkeyBytes, err := hex.DecodeString(pubkey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to decode hex pubkey: %s", err)
|
||||
}
|
||||
|
||||
ephemeralPublicKey, err := secp256k1.ParsePubKey(pubkeyBytes)
|
||||
ephemeralPubkey, err := secp256k1.ParsePubKey(pubkeyBytes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse pubkey: %s", err)
|
||||
}
|
||||
|
||||
return s.paymentRequests.pushEphemeralKey(paymentId, ephemeralPublicKey)
|
||||
return s.txRequests.pushEphemeralKey(requestID, ephemeralPubkey)
|
||||
}
|
||||
|
||||
func (s *covenantlessService) RegisterCosignerNonces(
|
||||
@@ -853,7 +851,7 @@ func (s *covenantlessService) RegisterCosignerNonces(
|
||||
|
||||
session.nonces[pubkey] = nonces
|
||||
|
||||
if len(session.nonces) == session.nbCosigners-1 { // exclude the ASP
|
||||
if len(session.nonces) == session.nbCosigners-1 { // exclude the server
|
||||
go func() {
|
||||
session.nonceDoneC <- struct{}{}
|
||||
}()
|
||||
@@ -884,7 +882,7 @@ func (s *covenantlessService) RegisterCosignerSignatures(
|
||||
|
||||
session.signatures[pubkey] = signatures
|
||||
|
||||
if len(session.signatures) == session.nbCosigners-1 { // exclude the ASP
|
||||
if len(session.signatures) == session.nbCosigners-1 { // exclude the server
|
||||
go func() {
|
||||
session.sigDoneC <- struct{}{}
|
||||
}()
|
||||
@@ -992,31 +990,31 @@ func (s *covenantlessService) startFinalization() {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: understand how many payments must be popped from the queue and actually registered for the round
|
||||
num := s.paymentRequests.len()
|
||||
// TODO: understand how many tx requests must be popped from the queue and actually registered for the round
|
||||
num := s.txRequests.len()
|
||||
if num == 0 {
|
||||
roundAborted = true
|
||||
err := fmt.Errorf("no payments registered")
|
||||
err := fmt.Errorf("no tx requests registered")
|
||||
round.Fail(fmt.Errorf("round aborted: %s", err))
|
||||
log.WithError(err).Debugf("round %s aborted", round.Id)
|
||||
return
|
||||
}
|
||||
if num > paymentsThreshold {
|
||||
num = paymentsThreshold
|
||||
if num > txRequestsThreshold {
|
||||
num = txRequestsThreshold
|
||||
}
|
||||
payments, boardingInputs, cosigners, paymentsNotes := s.paymentRequests.pop(num)
|
||||
if len(payments) > len(cosigners) {
|
||||
err := fmt.Errorf("missing ephemeral key for payments")
|
||||
requests, boardingInputs, cosigners, redeeemedNotes := s.txRequests.pop(num)
|
||||
if len(requests) > len(cosigners) {
|
||||
err := fmt.Errorf("missing ephemeral key for tx requests")
|
||||
round.Fail(fmt.Errorf("round aborted: %s", err))
|
||||
log.WithError(err).Debugf("round %s aborted", round.Id)
|
||||
return
|
||||
}
|
||||
|
||||
notes = paymentsNotes
|
||||
notes = redeeemedNotes
|
||||
|
||||
if _, err := round.RegisterPayments(payments); err != nil {
|
||||
round.Fail(fmt.Errorf("failed to register payments: %s", err))
|
||||
log.WithError(err).Warn("failed to register payments")
|
||||
if _, err := round.RegisterTxRequests(requests); err != nil {
|
||||
round.Fail(fmt.Errorf("failed to register tx requests: %s", err))
|
||||
log.WithError(err).Warn("failed to register tx requests")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1038,7 +1036,7 @@ func (s *covenantlessService) startFinalization() {
|
||||
|
||||
unsignedRoundTx, vtxoTree, connectorAddress, connectors, err := s.builder.BuildRoundTx(
|
||||
s.pubkey,
|
||||
payments,
|
||||
requests,
|
||||
boardingInputs,
|
||||
sweptRounds,
|
||||
cosigners...,
|
||||
@@ -1050,10 +1048,10 @@ func (s *covenantlessService) startFinalization() {
|
||||
}
|
||||
log.Debugf("round tx created for round %s", round.Id)
|
||||
|
||||
s.forfeitTxs.init(connectors, payments)
|
||||
s.forfeitTxs.init(connectors, requests)
|
||||
|
||||
if len(vtxoTree) > 0 {
|
||||
log.Debugf("signing congestion tree for round %s", round.Id)
|
||||
log.Debugf("signing vtxo tree for round %s", round.Id)
|
||||
|
||||
signingSession := newMusigSigningSession(len(cosigners))
|
||||
s.treeSigningSessions[round.Id] = signingSession
|
||||
@@ -1094,11 +1092,11 @@ func (s *covenantlessService) startFinalization() {
|
||||
return
|
||||
}
|
||||
|
||||
aspSignerSession := bitcointree.NewTreeSignerSession(
|
||||
serverSignerSession := bitcointree.NewTreeSignerSession(
|
||||
ephemeralKey, sharedOutputAmount, vtxoTree, root.CloneBytes(),
|
||||
)
|
||||
|
||||
nonces, err := aspSignerSession.GetNonces()
|
||||
nonces, err := serverSignerSession.GetNonces()
|
||||
if err != nil {
|
||||
round.Fail(fmt.Errorf("failed to get nonces: %s", err))
|
||||
log.WithError(err).Warn("failed to get nonces")
|
||||
@@ -1142,33 +1140,33 @@ func (s *covenantlessService) startFinalization() {
|
||||
|
||||
s.propagateRoundSigningNoncesGeneratedEvent(aggragatedNonces)
|
||||
|
||||
if err := aspSignerSession.SetKeys(cosigners); err != nil {
|
||||
if err := serverSignerSession.SetKeys(cosigners); err != nil {
|
||||
round.Fail(fmt.Errorf("failed to set keys: %s", err))
|
||||
log.WithError(err).Warn("failed to set keys")
|
||||
return
|
||||
}
|
||||
|
||||
if err := aspSignerSession.SetAggregatedNonces(aggragatedNonces); err != nil {
|
||||
if err := serverSignerSession.SetAggregatedNonces(aggragatedNonces); err != nil {
|
||||
round.Fail(fmt.Errorf("failed to set aggregated nonces: %s", err))
|
||||
log.WithError(err).Warn("failed to set aggregated nonces")
|
||||
return
|
||||
}
|
||||
|
||||
// sign the tree as ASP
|
||||
aspTreeSigs, err := aspSignerSession.Sign()
|
||||
// sign the tree as server
|
||||
serverTreeSigs, err := serverSignerSession.Sign()
|
||||
if err != nil {
|
||||
round.Fail(fmt.Errorf("failed to sign tree: %s", err))
|
||||
log.WithError(err).Warn("failed to sign tree")
|
||||
return
|
||||
}
|
||||
|
||||
if err := coordinator.AddSig(ephemeralKey.PubKey(), aspTreeSigs); err != nil {
|
||||
if err := coordinator.AddSig(ephemeralKey.PubKey(), serverTreeSigs); err != nil {
|
||||
round.Fail(fmt.Errorf("failed to add signature: %s", err))
|
||||
log.WithError(err).Warn("failed to add signature")
|
||||
return
|
||||
}
|
||||
|
||||
log.Debugf("ASP tree signed for round %s", round.Id)
|
||||
log.Debugf("tree signed by us for round %s", round.Id)
|
||||
|
||||
signaturesTimer := time.NewTimer(thirdOfRemainingDuration)
|
||||
|
||||
@@ -1199,7 +1197,7 @@ func (s *covenantlessService) startFinalization() {
|
||||
return
|
||||
}
|
||||
|
||||
log.Debugf("congestion tree signed for round %s", round.Id)
|
||||
log.Debugf("vtxo tree signed for round %s", round.Id)
|
||||
|
||||
vtxoTree = signedTree
|
||||
}
|
||||
@@ -1216,11 +1214,11 @@ func (s *covenantlessService) startFinalization() {
|
||||
}
|
||||
|
||||
func (s *covenantlessService) propagateRoundSigningStartedEvent(
|
||||
unsignedCongestionTree tree.CongestionTree, cosigners []*secp256k1.PublicKey,
|
||||
unsignedVtxoTree tree.VtxoTree, cosigners []*secp256k1.PublicKey,
|
||||
) {
|
||||
ev := RoundSigningStarted{
|
||||
Id: s.currentRound.Id,
|
||||
UnsignedVtxoTree: unsignedCongestionTree,
|
||||
UnsignedVtxoTree: unsignedVtxoTree,
|
||||
Cosigners: cosigners,
|
||||
UnsignedRoundTx: s.currentRound.UnsignedTx,
|
||||
}
|
||||
@@ -1311,7 +1309,7 @@ func (s *covenantlessService) finalizeRound(notes []note.Note) {
|
||||
|
||||
txid, err := s.wallet.BroadcastTransaction(ctx, signedRoundTx)
|
||||
if err != nil {
|
||||
changes = round.Fail(fmt.Errorf("failed to broadcast pool tx: %s", err))
|
||||
changes = round.Fail(fmt.Errorf("failed to broadcast round tx: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1331,14 +1329,14 @@ func (s *covenantlessService) finalizeRound(notes []note.Note) {
|
||||
|
||||
go func() {
|
||||
s.transactionEventsCh <- RoundTransactionEvent{
|
||||
RoundTxID: round.Txid,
|
||||
SpentVtxos: getSpentVtxos(round.Payments),
|
||||
RoundTxid: round.Txid,
|
||||
SpentVtxos: getSpentVtxos(round.TxRequests),
|
||||
SpendableVtxos: s.getNewVtxos(round),
|
||||
ClaimedBoardingInputs: boardingInputs,
|
||||
}
|
||||
}()
|
||||
|
||||
log.Debugf("finalized round %s with pool tx %s", round.Id, round.Txid)
|
||||
log.Debugf("finalized round %s with round tx %s", round.Id, round.Txid)
|
||||
}
|
||||
|
||||
func (s *covenantlessService) listenToScannerNotifications() {
|
||||
@@ -1491,7 +1489,7 @@ func (s *covenantlessService) updateVtxoSet(round *domain.Round) {
|
||||
|
||||
ctx := context.Background()
|
||||
repo := s.repoManager.Vtxos()
|
||||
spentVtxos := getSpentVtxos(round.Payments)
|
||||
spentVtxos := getSpentVtxos(round.TxRequests)
|
||||
if len(spentVtxos) > 0 {
|
||||
for {
|
||||
if err := repo.SpendVtxos(ctx, spentVtxos, round.Txid); err != nil {
|
||||
@@ -1544,7 +1542,7 @@ func (s *covenantlessService) propagateEvents(round *domain.Round) {
|
||||
case domain.RoundFinalizationStarted:
|
||||
ev := domain.RoundFinalizationStarted{
|
||||
Id: e.Id,
|
||||
CongestionTree: e.CongestionTree,
|
||||
VtxoTree: e.VtxoTree,
|
||||
Connectors: e.Connectors,
|
||||
RoundTx: e.RoundTx,
|
||||
MinRelayFeeRate: int64(s.wallet.MinRelayFeeRate(context.Background())),
|
||||
@@ -1565,19 +1563,19 @@ func (s *covenantlessService) scheduleSweepVtxosForRound(round *domain.Round) {
|
||||
|
||||
expirationTimestamp := s.sweeper.scheduler.AddNow(s.roundLifetime)
|
||||
|
||||
if err := s.sweeper.schedule(expirationTimestamp, round.Txid, round.CongestionTree); err != nil {
|
||||
if err := s.sweeper.schedule(expirationTimestamp, round.Txid, round.VtxoTree); err != nil {
|
||||
log.WithError(err).Warn("failed to schedule sweep tx")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *covenantlessService) getNewVtxos(round *domain.Round) []domain.Vtxo {
|
||||
if len(round.CongestionTree) <= 0 {
|
||||
if len(round.VtxoTree) <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
createdAt := time.Now().Unix()
|
||||
|
||||
leaves := round.CongestionTree.Leaves()
|
||||
leaves := round.VtxoTree.Leaves()
|
||||
vtxos := make([]domain.Vtxo, 0)
|
||||
for _, node := range leaves {
|
||||
tx, err := psbt.NewFromRawBytes(strings.NewReader(node.Tx), true)
|
||||
@@ -1593,10 +1591,9 @@ func (s *covenantlessService) getNewVtxos(round *domain.Round) []domain.Vtxo {
|
||||
}
|
||||
|
||||
vtxoPubkey := hex.EncodeToString(schnorr.SerializePubKey(vtxoTapKey))
|
||||
|
||||
vtxos = append(vtxos, domain.Vtxo{
|
||||
VtxoKey: domain.VtxoKey{Txid: node.Txid, VOut: uint32(i)},
|
||||
Pubkey: vtxoPubkey,
|
||||
PubKey: vtxoPubkey,
|
||||
Amount: uint64(out.Value),
|
||||
RoundTxid: round.Txid,
|
||||
CreatedAt: createdAt,
|
||||
@@ -1672,7 +1669,7 @@ func (s *covenantlessService) extractVtxosScripts(vtxos []domain.Vtxo) ([]string
|
||||
indexedScripts := make(map[string]struct{})
|
||||
|
||||
for _, vtxo := range vtxos {
|
||||
vtxoTapKeyBytes, err := hex.DecodeString(vtxo.Pubkey)
|
||||
vtxoTapKeyBytes, err := hex.DecodeString(vtxo.PubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1731,7 +1728,7 @@ func (s *covenantlessService) reactToFraud(ctx context.Context, vtxo domain.Vtxo
|
||||
if err != nil {
|
||||
vtxosRepo := s.repoManager.Vtxos()
|
||||
|
||||
// if the round is not found, the utxo may be spent by an async payment redeem tx
|
||||
// If the round is not found, the utxo may be spent by an out of round tx
|
||||
vtxos, err := vtxosRepo.GetVtxos(ctx, []domain.VtxoKey{
|
||||
{Txid: vtxo.SpentBy, VOut: 0},
|
||||
})
|
||||
@@ -1739,14 +1736,14 @@ func (s *covenantlessService) reactToFraud(ctx context.Context, vtxo domain.Vtxo
|
||||
return fmt.Errorf("failed to retrieve round: %s", err)
|
||||
}
|
||||
|
||||
asyncPayVtxo := vtxos[0]
|
||||
if asyncPayVtxo.Redeemed { // redeem tx is already onchain
|
||||
storedVtxo := vtxos[0]
|
||||
if storedVtxo.Redeemed { // redeem tx is already onchain
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Debugf("vtxo %s:%d has been spent by async payment", vtxo.Txid, vtxo.VOut)
|
||||
log.Debugf("vtxo %s:%d has been spent by out of round transaction", vtxo.Txid, vtxo.VOut)
|
||||
|
||||
redeemTxHex, err := s.builder.FinalizeAndExtract(asyncPayVtxo.RedeemTx)
|
||||
redeemTxHex, err := s.builder.FinalizeAndExtract(storedVtxo.RedeemTx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to finalize redeem tx: %s", err)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This package contains intermediary events that are used only by the covenantless version
|
||||
* they let to sign the congestion tree using musig2 algorithm
|
||||
* they let to sign the vtxo tree using musig2 algorithm
|
||||
* they are not included in domain because they don't mutate the Round state and should not be persisted
|
||||
*/
|
||||
package application
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
// signer should react to this event by generating a musig2 nonce for each transaction in the tree
|
||||
type RoundSigningStarted struct {
|
||||
Id string
|
||||
UnsignedVtxoTree tree.CongestionTree
|
||||
UnsignedVtxoTree tree.VtxoTree
|
||||
Cosigners []*secp256k1.PublicKey
|
||||
UnsignedRoundTx string
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@ package application
|
||||
|
||||
import "fmt"
|
||||
|
||||
type errPaymentNotFound struct {
|
||||
type errTxRequestNotFound struct {
|
||||
id string
|
||||
}
|
||||
|
||||
func (e errPaymentNotFound) Error() string {
|
||||
return fmt.Sprintf("payment %s not found", e.id)
|
||||
func (e errTxRequestNotFound) Error() string {
|
||||
return fmt.Sprintf("tx request %s not found", e.id)
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ func (p OwnershipProof) validate(vtxo domain.Vtxo) error {
|
||||
rootHash := p.ControlBlock.RootHash(p.Script)
|
||||
vtxoTapKey := txscript.ComputeTaprootOutputKey(bitcointree.UnspendableKey(), rootHash)
|
||||
|
||||
if hex.EncodeToString(schnorr.SerializePubKey(vtxoTapKey)) != vtxo.Pubkey {
|
||||
if hex.EncodeToString(schnorr.SerializePubKey(vtxoTapKey)) != vtxo.PubKey {
|
||||
return fmt.Errorf("invalid control block")
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
// sweeper is an unexported service running while the main application service is started
|
||||
// it is responsible for sweeping onchain shared outputs that expired
|
||||
// it also handles delaying the sweep events in case some parts of the tree are broadcasted
|
||||
// when a round is finalized, the main application service schedules a sweep event on the newly created congestion tree
|
||||
// when a round is finalized, the main application service schedules a sweep event on the newly created vtxo tree
|
||||
type sweeper struct {
|
||||
wallet ports.WalletService
|
||||
repoManager ports.RepoManager
|
||||
@@ -58,7 +58,7 @@ func (s *sweeper) start() error {
|
||||
}
|
||||
|
||||
for _, round := range allRounds {
|
||||
task := s.createTask(round.Txid, round.CongestionTree)
|
||||
task := s.createTask(round.Txid, round.VtxoTree)
|
||||
task()
|
||||
}
|
||||
|
||||
@@ -78,14 +78,14 @@ func (s *sweeper) removeTask(treeRootTxid string) {
|
||||
|
||||
// schedule set up a task to be executed once at the given timestamp
|
||||
func (s *sweeper) schedule(
|
||||
expirationTimestamp int64, roundTxid string, congestionTree tree.CongestionTree,
|
||||
expirationTimestamp int64, roundTxid string, vtxoTree tree.VtxoTree,
|
||||
) error {
|
||||
if len(congestionTree) <= 0 { // skip
|
||||
log.Debugf("skipping sweep scheduling (round tx %s), empty congestion tree", roundTxid)
|
||||
if len(vtxoTree) <= 0 { // skip
|
||||
log.Debugf("skipping sweep scheduling (round tx %s), empty vtxo tree", roundTxid)
|
||||
return nil
|
||||
}
|
||||
|
||||
root, err := congestionTree.Root()
|
||||
root, err := vtxoTree.Root()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -94,7 +94,7 @@ func (s *sweeper) schedule(
|
||||
return nil
|
||||
}
|
||||
|
||||
task := s.createTask(roundTxid, congestionTree)
|
||||
task := s.createTask(roundTxid, vtxoTree)
|
||||
|
||||
var fancyTime string
|
||||
if s.scheduler.Unit() == ports.UnixTime {
|
||||
@@ -112,7 +112,7 @@ func (s *sweeper) schedule(
|
||||
s.scheduledTasks[root.Txid] = struct{}{}
|
||||
s.locker.Unlock()
|
||||
|
||||
if err := s.updateVtxoExpirationTime(congestionTree, expirationTimestamp); err != nil {
|
||||
if err := s.updateVtxoExpirationTime(vtxoTree, expirationTimestamp); err != nil {
|
||||
log.WithError(err).Error("error while updating vtxo expiration time")
|
||||
}
|
||||
|
||||
@@ -120,14 +120,14 @@ func (s *sweeper) schedule(
|
||||
}
|
||||
|
||||
// createTask returns a function passed as handler in the scheduler
|
||||
// it tries to craft a sweep tx containing the onchain outputs of the given congestion tree
|
||||
// it tries to craft a sweep tx containing the onchain outputs of the given vtxo tree
|
||||
// if some parts of the tree have been broadcasted in the meantine, it will schedule the next taskes for the remaining parts of the tree
|
||||
func (s *sweeper) createTask(
|
||||
roundTxid string, congestionTree tree.CongestionTree,
|
||||
roundTxid string, vtxoTree tree.VtxoTree,
|
||||
) func() {
|
||||
return func() {
|
||||
ctx := context.Background()
|
||||
root, err := congestionTree.Root()
|
||||
root, err := vtxoTree.Root()
|
||||
if err != nil {
|
||||
log.WithError(err).Error("error while getting root node")
|
||||
return
|
||||
@@ -139,17 +139,17 @@ func (s *sweeper) createTask(
|
||||
sweepInputs := make([]ports.SweepInput, 0)
|
||||
vtxoKeys := make([]domain.VtxoKey, 0) // vtxos associated to the sweep inputs
|
||||
|
||||
// inspect the congestion tree to find onchain shared outputs
|
||||
sharedOutputs, err := findSweepableOutputs(ctx, s.wallet, s.builder, s.scheduler.Unit(), congestionTree)
|
||||
// inspect the vtxo tree to find onchain shared outputs
|
||||
sharedOutputs, err := findSweepableOutputs(ctx, s.wallet, s.builder, s.scheduler.Unit(), vtxoTree)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("error while inspecting congestion tree")
|
||||
log.WithError(err).Error("error while inspecting vtxo tree")
|
||||
return
|
||||
}
|
||||
|
||||
for expiredAt, inputs := range sharedOutputs {
|
||||
// if the shared outputs are not expired, schedule a sweep task for it
|
||||
if s.scheduler.AfterNow(expiredAt) {
|
||||
subtrees, err := computeSubTrees(congestionTree, inputs)
|
||||
subtrees, err := computeSubTrees(vtxoTree, inputs)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("error while computing subtrees")
|
||||
continue
|
||||
@@ -185,7 +185,7 @@ func (s *sweeper) createTask(
|
||||
}
|
||||
} else {
|
||||
// if it's not a vtxo, find all the vtxos leaves reachable from that input
|
||||
vtxosLeaves, err := s.builder.FindLeaves(congestionTree, input.GetHash().String(), input.GetIndex())
|
||||
vtxosLeaves, err := s.builder.FindLeaves(vtxoTree, input.GetHash().String(), input.GetIndex())
|
||||
if err != nil {
|
||||
log.WithError(err).Error("error while finding vtxos leaves")
|
||||
continue
|
||||
@@ -301,7 +301,7 @@ func (s *sweeper) createTask(
|
||||
}
|
||||
|
||||
func (s *sweeper) updateVtxoExpirationTime(
|
||||
tree tree.CongestionTree,
|
||||
tree tree.VtxoTree,
|
||||
expirationTime int64,
|
||||
) error {
|
||||
leaves := tree.Leaves()
|
||||
@@ -376,13 +376,13 @@ func (s *sweeper) createAndSendNotes(ctx context.Context, vtxosKeys []domain.Vtx
|
||||
}
|
||||
}
|
||||
|
||||
func computeSubTrees(congestionTree tree.CongestionTree, inputs []ports.SweepInput) ([]tree.CongestionTree, error) {
|
||||
subTrees := make(map[string]tree.CongestionTree, 0)
|
||||
func computeSubTrees(vtxoTree tree.VtxoTree, inputs []ports.SweepInput) ([]tree.VtxoTree, error) {
|
||||
subTrees := make(map[string]tree.VtxoTree, 0)
|
||||
|
||||
// for each sweepable input, create a sub congestion tree
|
||||
// for each sweepable input, create a sub vtxo tree
|
||||
// it allows to skip the part of the tree that has been broadcasted in the next task
|
||||
for _, input := range inputs {
|
||||
subTree, err := computeSubTree(congestionTree, input.GetHash().String())
|
||||
subTree, err := computeSubTree(vtxoTree, input.GetHash().String())
|
||||
if err != nil {
|
||||
log.WithError(err).Error("error while finding sub tree")
|
||||
continue
|
||||
@@ -398,7 +398,7 @@ func computeSubTrees(congestionTree tree.CongestionTree, inputs []ports.SweepInp
|
||||
}
|
||||
|
||||
// filter out the sub trees, remove the ones that are included in others
|
||||
filteredSubTrees := make([]tree.CongestionTree, 0)
|
||||
filteredSubTrees := make([]tree.VtxoTree, 0)
|
||||
for i, subTree := range subTrees {
|
||||
notIncludedInOtherTrees := true
|
||||
|
||||
@@ -426,19 +426,19 @@ func computeSubTrees(congestionTree tree.CongestionTree, inputs []ports.SweepInp
|
||||
return filteredSubTrees, nil
|
||||
}
|
||||
|
||||
func computeSubTree(congestionTree tree.CongestionTree, newRoot string) (tree.CongestionTree, error) {
|
||||
for _, level := range congestionTree {
|
||||
func computeSubTree(vtxoTree tree.VtxoTree, newRoot string) (tree.VtxoTree, error) {
|
||||
for _, level := range vtxoTree {
|
||||
for _, node := range level {
|
||||
if node.Txid == newRoot || node.ParentTxid == newRoot {
|
||||
newTree := make(tree.CongestionTree, 0)
|
||||
newTree := make(tree.VtxoTree, 0)
|
||||
newTree = append(newTree, []tree.Node{node})
|
||||
|
||||
children := congestionTree.Children(node.Txid)
|
||||
children := vtxoTree.Children(node.Txid)
|
||||
for len(children) > 0 {
|
||||
newTree = append(newTree, children)
|
||||
newChildren := make([]tree.Node, 0)
|
||||
for _, child := range children {
|
||||
newChildren = append(newChildren, congestionTree.Children(child.Txid)...)
|
||||
newChildren = append(newChildren, vtxoTree.Children(child.Txid)...)
|
||||
}
|
||||
children = newChildren
|
||||
}
|
||||
@@ -451,7 +451,7 @@ func computeSubTree(congestionTree tree.CongestionTree, newRoot string) (tree.Co
|
||||
return nil, fmt.Errorf("failed to create subtree, new root not found")
|
||||
}
|
||||
|
||||
func containsTree(tr0 tree.CongestionTree, tr1 tree.CongestionTree) (bool, error) {
|
||||
func containsTree(tr0 tree.VtxoTree, tr1 tree.VtxoTree) (bool, error) {
|
||||
tr1Root, err := tr1.Root()
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -468,7 +468,7 @@ func containsTree(tr0 tree.CongestionTree, tr1 tree.CongestionTree) (bool, error
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// assuming the pset is a leaf in the congestion tree, returns the vtxo outpoint
|
||||
// assuming the pset is a leaf in the vtxo tree, returns the vtxo outpoint
|
||||
func extractVtxoOutpoint(leaf tree.Node) (*domain.VtxoKey, error) {
|
||||
if !leaf.Leaf {
|
||||
return nil, fmt.Errorf("node is not a leaf")
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
paymentsThreshold = int64(128)
|
||||
txRequestsThreshold = int64(128)
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
@@ -22,11 +22,11 @@ type Service interface {
|
||||
ClaimVtxos(ctx context.Context, creds string, receivers []domain.Receiver) error
|
||||
SignVtxos(ctx context.Context, forfeitTxs []string) error
|
||||
SignRoundTx(ctx context.Context, roundTx string) error
|
||||
GetRoundByTxid(ctx context.Context, poolTxid string) (*domain.Round, error)
|
||||
GetRoundByTxid(ctx context.Context, roundTxid string) (*domain.Round, error)
|
||||
GetRoundById(ctx context.Context, id string) (*domain.Round, error)
|
||||
GetCurrentRound(ctx context.Context) (*domain.Round, error)
|
||||
GetEventsChannel(ctx context.Context) <-chan domain.RoundEvent
|
||||
UpdatePaymentStatus(ctx context.Context, paymentId string) error
|
||||
UpdateTxRequestStatus(ctx context.Context, requestID string) error
|
||||
ListVtxos(
|
||||
ctx context.Context, address string,
|
||||
) (spendableVtxos, spentVtxos []domain.Vtxo, err error)
|
||||
@@ -36,7 +36,7 @@ type Service interface {
|
||||
ctx context.Context, userPubkey *secp256k1.PublicKey,
|
||||
) (address string, scripts []string, err error)
|
||||
// Tree signing methods
|
||||
RegisterCosignerPubkey(ctx context.Context, paymentId string, ephemeralPublicKey string) error
|
||||
RegisterCosignerPubkey(ctx context.Context, requestID string, ephemeralPubkey string) error
|
||||
RegisterCosignerNonces(
|
||||
ctx context.Context, roundID string,
|
||||
pubkey *secp256k1.PublicKey, nonces string,
|
||||
@@ -106,7 +106,7 @@ type TransactionEvent interface {
|
||||
}
|
||||
|
||||
type RoundTransactionEvent struct {
|
||||
RoundTxID string
|
||||
RoundTxid string
|
||||
SpentVtxos []domain.VtxoKey
|
||||
SpendableVtxos []domain.Vtxo
|
||||
ClaimedBoardingInputs []domain.VtxoKey
|
||||
@@ -117,7 +117,7 @@ func (r RoundTransactionEvent) Type() TransactionEventType {
|
||||
}
|
||||
|
||||
type RedeemTransactionEvent struct {
|
||||
AsyncTxID string
|
||||
RedeemTxid string
|
||||
SpentVtxos []domain.VtxoKey
|
||||
SpendableVtxos []domain.Vtxo
|
||||
}
|
||||
|
||||
@@ -16,32 +16,32 @@ import (
|
||||
"github.com/nbd-wtf/go-nostr/nip19"
|
||||
)
|
||||
|
||||
type timedPayment struct {
|
||||
domain.Payment
|
||||
type timedTxRequest struct {
|
||||
domain.TxRequest
|
||||
boardingInputs []ports.BoardingInput
|
||||
notes []note.Note
|
||||
timestamp time.Time
|
||||
pingTimestamp time.Time
|
||||
}
|
||||
|
||||
type paymentsMap struct {
|
||||
type txRequestsQueue struct {
|
||||
lock *sync.RWMutex
|
||||
payments map[string]*timedPayment
|
||||
requests map[string]*timedTxRequest
|
||||
ephemeralKeys map[string]*secp256k1.PublicKey
|
||||
}
|
||||
|
||||
func newPaymentsMap() *paymentsMap {
|
||||
paymentsById := make(map[string]*timedPayment)
|
||||
func newTxRequestsQueue() *txRequestsQueue {
|
||||
requestsById := make(map[string]*timedTxRequest)
|
||||
lock := &sync.RWMutex{}
|
||||
return &paymentsMap{lock, paymentsById, make(map[string]*secp256k1.PublicKey)}
|
||||
return &txRequestsQueue{lock, requestsById, make(map[string]*secp256k1.PublicKey)}
|
||||
}
|
||||
|
||||
func (m *paymentsMap) len() int64 {
|
||||
func (m *txRequestsQueue) len() int64 {
|
||||
m.lock.RLock()
|
||||
defer m.lock.RUnlock()
|
||||
|
||||
count := int64(0)
|
||||
for _, p := range m.payments {
|
||||
for _, p := range m.requests {
|
||||
if len(p.Receivers) > 0 {
|
||||
count++
|
||||
}
|
||||
@@ -49,154 +49,154 @@ func (m *paymentsMap) len() int64 {
|
||||
return count
|
||||
}
|
||||
|
||||
func (m *paymentsMap) delete(id string) error {
|
||||
func (m *txRequestsQueue) delete(id string) error {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
if _, ok := m.payments[id]; !ok {
|
||||
return errPaymentNotFound{id}
|
||||
if _, ok := m.requests[id]; !ok {
|
||||
return errTxRequestNotFound{id}
|
||||
}
|
||||
|
||||
delete(m.payments, id)
|
||||
delete(m.requests, id)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *paymentsMap) pushWithNotes(payment domain.Payment, notes []note.Note) error {
|
||||
func (m *txRequestsQueue) pushWithNotes(request domain.TxRequest, notes []note.Note) error {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
if _, ok := m.payments[payment.Id]; ok {
|
||||
return fmt.Errorf("duplicated payment %s", payment.Id)
|
||||
if _, ok := m.requests[request.Id]; ok {
|
||||
return fmt.Errorf("duplicated tx request %s", request.Id)
|
||||
}
|
||||
|
||||
for _, note := range notes {
|
||||
for _, payment := range m.payments {
|
||||
for _, pNote := range payment.notes {
|
||||
if note.ID == pNote.ID {
|
||||
for _, txRequest := range m.requests {
|
||||
for _, rNote := range txRequest.notes {
|
||||
if note.ID == rNote.ID {
|
||||
return fmt.Errorf("duplicated note %s", note)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m.payments[payment.Id] = &timedPayment{payment, make([]ports.BoardingInput, 0), notes, time.Now(), time.Time{}}
|
||||
m.requests[request.Id] = &timedTxRequest{request, make([]ports.BoardingInput, 0), notes, time.Now(), time.Time{}}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *paymentsMap) push(
|
||||
payment domain.Payment,
|
||||
func (m *txRequestsQueue) push(
|
||||
request domain.TxRequest,
|
||||
boardingInputs []ports.BoardingInput,
|
||||
) error {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
if _, ok := m.payments[payment.Id]; ok {
|
||||
return fmt.Errorf("duplicated payment %s", payment.Id)
|
||||
if _, ok := m.requests[request.Id]; ok {
|
||||
return fmt.Errorf("duplicated tx request %s", request.Id)
|
||||
}
|
||||
|
||||
for _, input := range payment.Inputs {
|
||||
for _, pay := range m.payments {
|
||||
for _, input := range request.Inputs {
|
||||
for _, pay := range m.requests {
|
||||
for _, pInput := range pay.Inputs {
|
||||
if input.VtxoKey.Txid == pInput.VtxoKey.Txid && input.VtxoKey.VOut == pInput.VtxoKey.VOut {
|
||||
return fmt.Errorf("duplicated input, %s:%d already used by payment %s", input.VtxoKey.Txid, input.VtxoKey.VOut, pay.Id)
|
||||
return fmt.Errorf("duplicated input, %s:%d already used by tx request %s", input.VtxoKey.Txid, input.VtxoKey.VOut, pay.Id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, input := range boardingInputs {
|
||||
for _, pay := range m.payments {
|
||||
for _, pBoardingInput := range pay.boardingInputs {
|
||||
for _, request := range m.requests {
|
||||
for _, pBoardingInput := range request.boardingInputs {
|
||||
if input.Txid == pBoardingInput.Txid && input.VOut == pBoardingInput.VOut {
|
||||
return fmt.Errorf("duplicated boarding input, %s:%d already used by payment %s", input.Txid, input.VOut, pay.Id)
|
||||
return fmt.Errorf("duplicated boarding input, %s:%d already used by tx request %s", input.Txid, input.VOut, request.Id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m.payments[payment.Id] = &timedPayment{payment, boardingInputs, make([]note.Note, 0), time.Now(), time.Time{}}
|
||||
m.requests[request.Id] = &timedTxRequest{request, boardingInputs, make([]note.Note, 0), time.Now(), time.Time{}}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *paymentsMap) pushEphemeralKey(paymentId string, pubkey *secp256k1.PublicKey) error {
|
||||
func (m *txRequestsQueue) pushEphemeralKey(requestID string, pubkey *secp256k1.PublicKey) error {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
if _, ok := m.payments[paymentId]; !ok {
|
||||
return fmt.Errorf("payment %s not found, cannot register signing ephemeral public key", paymentId)
|
||||
if _, ok := m.requests[requestID]; !ok {
|
||||
return fmt.Errorf("tx request %s not found, cannot register signing ephemeral public key", requestID)
|
||||
}
|
||||
|
||||
m.ephemeralKeys[paymentId] = pubkey
|
||||
m.ephemeralKeys[requestID] = pubkey
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *paymentsMap) pop(num int64) ([]domain.Payment, []ports.BoardingInput, []*secp256k1.PublicKey, []note.Note) {
|
||||
func (m *txRequestsQueue) pop(num int64) ([]domain.TxRequest, []ports.BoardingInput, []*secp256k1.PublicKey, []note.Note) {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
paymentsByTime := make([]timedPayment, 0, len(m.payments))
|
||||
for _, p := range m.payments {
|
||||
// Skip payments without registered receivers.
|
||||
requestsByTime := make([]timedTxRequest, 0, len(m.requests))
|
||||
for _, p := range m.requests {
|
||||
// Skip tx requests without registered receivers.
|
||||
if len(p.Receivers) <= 0 {
|
||||
continue
|
||||
}
|
||||
// Skip payments for which users didn't notify to be online in the last minute.
|
||||
// Skip tx requests for which users didn't notify to be online in the last minute.
|
||||
if p.pingTimestamp.IsZero() || time.Since(p.pingTimestamp).Minutes() > 1 {
|
||||
continue
|
||||
}
|
||||
paymentsByTime = append(paymentsByTime, *p)
|
||||
requestsByTime = append(requestsByTime, *p)
|
||||
}
|
||||
sort.SliceStable(paymentsByTime, func(i, j int) bool {
|
||||
return paymentsByTime[i].timestamp.Before(paymentsByTime[j].timestamp)
|
||||
sort.SliceStable(requestsByTime, func(i, j int) bool {
|
||||
return requestsByTime[i].timestamp.Before(requestsByTime[j].timestamp)
|
||||
})
|
||||
|
||||
if num < 0 || num > int64(len(paymentsByTime)) {
|
||||
num = int64(len(paymentsByTime))
|
||||
if num < 0 || num > int64(len(requestsByTime)) {
|
||||
num = int64(len(requestsByTime))
|
||||
}
|
||||
|
||||
payments := make([]domain.Payment, 0, num)
|
||||
requests := make([]domain.TxRequest, 0, num)
|
||||
boardingInputs := make([]ports.BoardingInput, 0)
|
||||
cosigners := make([]*secp256k1.PublicKey, 0, num)
|
||||
notes := make([]note.Note, 0)
|
||||
for _, p := range paymentsByTime[:num] {
|
||||
for _, p := range requestsByTime[:num] {
|
||||
boardingInputs = append(boardingInputs, p.boardingInputs...)
|
||||
payments = append(payments, p.Payment)
|
||||
if pubkey, ok := m.ephemeralKeys[p.Payment.Id]; ok {
|
||||
requests = append(requests, p.TxRequest)
|
||||
if pubkey, ok := m.ephemeralKeys[p.TxRequest.Id]; ok {
|
||||
cosigners = append(cosigners, pubkey)
|
||||
delete(m.ephemeralKeys, p.Payment.Id)
|
||||
delete(m.ephemeralKeys, p.TxRequest.Id)
|
||||
}
|
||||
notes = append(notes, p.notes...)
|
||||
delete(m.payments, p.Id)
|
||||
delete(m.requests, p.Id)
|
||||
}
|
||||
return payments, boardingInputs, cosigners, notes
|
||||
return requests, boardingInputs, cosigners, notes
|
||||
}
|
||||
|
||||
func (m *paymentsMap) update(payment domain.Payment) error {
|
||||
func (m *txRequestsQueue) update(request domain.TxRequest) error {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
p, ok := m.payments[payment.Id]
|
||||
r, ok := m.requests[request.Id]
|
||||
if !ok {
|
||||
return fmt.Errorf("payment %s not found", payment.Id)
|
||||
return fmt.Errorf("tx request %s not found", request.Id)
|
||||
}
|
||||
|
||||
// sum inputs = vtxos + boarding utxos + notes
|
||||
sumOfInputs := uint64(0)
|
||||
for _, input := range payment.Inputs {
|
||||
for _, input := range request.Inputs {
|
||||
sumOfInputs += input.Amount
|
||||
}
|
||||
|
||||
for _, boardingInput := range p.boardingInputs {
|
||||
for _, boardingInput := range r.boardingInputs {
|
||||
sumOfInputs += boardingInput.Amount
|
||||
}
|
||||
|
||||
for _, note := range p.notes {
|
||||
for _, note := range r.notes {
|
||||
sumOfInputs += uint64(note.Value)
|
||||
}
|
||||
|
||||
// sum outputs = receivers VTXOs
|
||||
sumOfOutputs := uint64(0)
|
||||
for _, receiver := range payment.Receivers {
|
||||
for _, receiver := range request.Receivers {
|
||||
sumOfOutputs += receiver.Amount
|
||||
}
|
||||
|
||||
@@ -204,37 +204,37 @@ func (m *paymentsMap) update(payment domain.Payment) error {
|
||||
return fmt.Errorf("sum of inputs %d does not match sum of outputs %d", sumOfInputs, sumOfOutputs)
|
||||
}
|
||||
|
||||
p.Payment = payment
|
||||
r.TxRequest = request
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *paymentsMap) updatePingTimestamp(id string) error {
|
||||
func (m *txRequestsQueue) updatePingTimestamp(id string) error {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
payment, ok := m.payments[id]
|
||||
request, ok := m.requests[id]
|
||||
if !ok {
|
||||
return errPaymentNotFound{id}
|
||||
return errTxRequestNotFound{id}
|
||||
}
|
||||
|
||||
payment.pingTimestamp = time.Now()
|
||||
request.pingTimestamp = time.Now()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *paymentsMap) view(id string) (*domain.Payment, bool) {
|
||||
func (m *txRequestsQueue) view(id string) (*domain.TxRequest, bool) {
|
||||
m.lock.RLock()
|
||||
defer m.lock.RUnlock()
|
||||
|
||||
payment, ok := m.payments[id]
|
||||
request, ok := m.requests[id]
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return &domain.Payment{
|
||||
Id: payment.Id,
|
||||
Inputs: payment.Inputs,
|
||||
Receivers: payment.Receivers,
|
||||
return &domain.TxRequest{
|
||||
Id: request.Id,
|
||||
Inputs: request.Inputs,
|
||||
Receivers: request.Receivers,
|
||||
}, true
|
||||
}
|
||||
|
||||
@@ -251,10 +251,10 @@ func newForfeitTxsMap(txBuilder ports.TxBuilder) *forfeitTxsMap {
|
||||
return &forfeitTxsMap{&sync.RWMutex{}, txBuilder, make(map[domain.VtxoKey][]string), nil, nil}
|
||||
}
|
||||
|
||||
func (m *forfeitTxsMap) init(connectors []string, payments []domain.Payment) {
|
||||
func (m *forfeitTxsMap) init(connectors []string, requests []domain.TxRequest) {
|
||||
vtxosToSign := make([]domain.Vtxo, 0)
|
||||
for _, payment := range payments {
|
||||
vtxosToSign = append(vtxosToSign, payment.Inputs...)
|
||||
for _, request := range requests {
|
||||
vtxosToSign = append(vtxosToSign, request.Inputs...)
|
||||
}
|
||||
|
||||
m.lock.Lock()
|
||||
@@ -318,18 +318,18 @@ func (m *forfeitTxsMap) pop() ([]string, error) {
|
||||
return txs, nil
|
||||
}
|
||||
|
||||
// onchainOutputs iterates over all the nodes' outputs in the congestion tree and checks their onchain state
|
||||
// onchainOutputs iterates over all the nodes' outputs in the vtxo tree and checks their onchain state
|
||||
// returns the sweepable outputs as ports.SweepInput mapped by their expiration time
|
||||
func findSweepableOutputs(
|
||||
ctx context.Context,
|
||||
walletSvc ports.WalletService,
|
||||
txbuilder ports.TxBuilder,
|
||||
schedulerUnit ports.TimeUnit,
|
||||
congestionTree tree.CongestionTree,
|
||||
vtxoTree tree.VtxoTree,
|
||||
) (map[int64][]ports.SweepInput, error) {
|
||||
sweepableOutputs := make(map[int64][]ports.SweepInput)
|
||||
blocktimeCache := make(map[string]int64) // txid -> blocktime / blockheight
|
||||
nodesToCheck := congestionTree[0] // init with the root
|
||||
nodesToCheck := vtxoTree[0] // init with the root
|
||||
|
||||
for len(nodesToCheck) > 0 {
|
||||
newNodesToCheck := make([]tree.Node, 0)
|
||||
@@ -375,7 +375,7 @@ func findSweepableOutputs(
|
||||
// add the children to the nodes in order to check them during the next iteration
|
||||
// We will return the error below, but are we going to schedule the tasks for the "children roots"?
|
||||
if !node.Leaf {
|
||||
children := congestionTree.Children(node.Txid)
|
||||
children := vtxoTree.Children(node.Txid)
|
||||
newNodesToCheck = append(newNodesToCheck, children...)
|
||||
}
|
||||
continue
|
||||
@@ -393,10 +393,10 @@ func findSweepableOutputs(
|
||||
return sweepableOutputs, nil
|
||||
}
|
||||
|
||||
func getSpentVtxos(payments map[string]domain.Payment) []domain.VtxoKey {
|
||||
func getSpentVtxos(requests map[string]domain.TxRequest) []domain.VtxoKey {
|
||||
vtxos := make([]domain.VtxoKey, 0)
|
||||
for _, p := range payments {
|
||||
for _, vtxo := range p.Inputs {
|
||||
for _, request := range requests {
|
||||
for _, vtxo := range request.Inputs {
|
||||
vtxos = append(vtxos, vtxo.VtxoKey)
|
||||
}
|
||||
}
|
||||
@@ -460,12 +460,12 @@ func nip19toNostrProfile(nostrRecipient string, defaultRelays []string) (string,
|
||||
|
||||
nprofileRecipient = nostrRecipient
|
||||
case "npub":
|
||||
recipientPublicKey, ok := result.(string)
|
||||
recipientPubkey, ok := result.(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("invalid NIP-19 result: %v", result)
|
||||
}
|
||||
|
||||
nprofileRecipient, err = nip19.EncodeProfile(recipientPublicKey, defaultRelays)
|
||||
nprofileRecipient, err = nip19.EncodeProfile(recipientPubkey, defaultRelays)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to encode nostr profile: %s", err)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ func (r RoundStarted) IsEvent() {}
|
||||
func (r RoundFinalizationStarted) IsEvent() {}
|
||||
func (r RoundFinalized) IsEvent() {}
|
||||
func (r RoundFailed) IsEvent() {}
|
||||
func (r PaymentsRegistered) IsEvent() {}
|
||||
func (r TxRequestsRegistered) IsEvent() {}
|
||||
|
||||
type RoundStarted struct {
|
||||
Id string
|
||||
@@ -19,7 +19,7 @@ type RoundStarted struct {
|
||||
|
||||
type RoundFinalizationStarted struct {
|
||||
Id string
|
||||
CongestionTree tree.CongestionTree // BTC: signed
|
||||
VtxoTree tree.VtxoTree
|
||||
Connectors []string
|
||||
ConnectorAddress string
|
||||
RoundTx string
|
||||
@@ -39,7 +39,7 @@ type RoundFailed struct {
|
||||
Timestamp int64
|
||||
}
|
||||
|
||||
type PaymentsRegistered struct {
|
||||
type TxRequestsRegistered struct {
|
||||
Id string
|
||||
Payments []Payment
|
||||
TxRequests []TxRequest
|
||||
}
|
||||
|
||||
@@ -11,66 +11,66 @@ import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Payment struct {
|
||||
type TxRequest struct {
|
||||
Id string
|
||||
Inputs []Vtxo
|
||||
Receivers []Receiver
|
||||
}
|
||||
|
||||
func NewPayment(inputs []Vtxo) (*Payment, error) {
|
||||
p := &Payment{
|
||||
func NewTxRequest(inputs []Vtxo) (*TxRequest, error) {
|
||||
request := &TxRequest{
|
||||
Id: uuid.New().String(),
|
||||
Inputs: inputs,
|
||||
}
|
||||
if err := p.validate(true); err != nil {
|
||||
if err := request.validate(true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, nil
|
||||
return request, nil
|
||||
}
|
||||
|
||||
func (p *Payment) AddReceivers(receivers []Receiver) (err error) {
|
||||
if p.Receivers == nil {
|
||||
p.Receivers = make([]Receiver, 0)
|
||||
func (r *TxRequest) AddReceivers(receivers []Receiver) (err error) {
|
||||
if r.Receivers == nil {
|
||||
r.Receivers = make([]Receiver, 0)
|
||||
}
|
||||
p.Receivers = append(p.Receivers, receivers...)
|
||||
r.Receivers = append(r.Receivers, receivers...)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
p.Receivers = p.Receivers[:len(p.Receivers)-len(receivers)]
|
||||
r.Receivers = r.Receivers[:len(r.Receivers)-len(receivers)]
|
||||
}
|
||||
}()
|
||||
err = p.validate(false)
|
||||
err = r.validate(false)
|
||||
return
|
||||
}
|
||||
|
||||
func (p Payment) TotalInputAmount() uint64 {
|
||||
func (r TxRequest) TotalInputAmount() uint64 {
|
||||
tot := uint64(0)
|
||||
for _, in := range p.Inputs {
|
||||
for _, in := range r.Inputs {
|
||||
tot += in.Amount
|
||||
}
|
||||
return tot
|
||||
}
|
||||
|
||||
func (p Payment) TotalOutputAmount() uint64 {
|
||||
func (r TxRequest) TotalOutputAmount() uint64 {
|
||||
tot := uint64(0)
|
||||
for _, r := range p.Receivers {
|
||||
for _, r := range r.Receivers {
|
||||
tot += r.Amount
|
||||
}
|
||||
return tot
|
||||
}
|
||||
|
||||
func (p Payment) validate(ignoreOuts bool) error {
|
||||
if len(p.Id) <= 0 {
|
||||
func (r TxRequest) validate(ignoreOuts bool) error {
|
||||
if len(r.Id) <= 0 {
|
||||
return fmt.Errorf("missing id")
|
||||
}
|
||||
if ignoreOuts {
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(p.Receivers) <= 0 {
|
||||
if len(r.Receivers) <= 0 {
|
||||
return fmt.Errorf("missing outputs")
|
||||
}
|
||||
for _, r := range p.Receivers {
|
||||
if len(r.OnchainAddress) <= 0 && len(r.Pubkey) <= 0 {
|
||||
for _, r := range r.Receivers {
|
||||
if len(r.OnchainAddress) <= 0 && len(r.PubKey) <= 0 {
|
||||
return fmt.Errorf("missing receiver destination")
|
||||
}
|
||||
if r.Amount == 0 {
|
||||
@@ -107,7 +107,7 @@ func (k VtxoKey) Hash() string {
|
||||
type Receiver struct {
|
||||
Amount uint64
|
||||
OnchainAddress string // onchain
|
||||
Pubkey string // offchain
|
||||
PubKey string // offchain
|
||||
}
|
||||
|
||||
func (r Receiver) IsOnchain() bool {
|
||||
@@ -117,9 +117,9 @@ func (r Receiver) IsOnchain() bool {
|
||||
type Vtxo struct {
|
||||
VtxoKey
|
||||
Amount uint64
|
||||
Pubkey string
|
||||
PubKey string
|
||||
RoundTxid string
|
||||
SpentBy string // round txid or async redeem txid
|
||||
SpentBy string // round txid or redeem txid
|
||||
Spent bool
|
||||
Redeemed bool
|
||||
Swept bool
|
||||
@@ -129,7 +129,7 @@ type Vtxo struct {
|
||||
}
|
||||
|
||||
func (v Vtxo) TapKey() (*secp256k1.PublicKey, error) {
|
||||
pubkeyBytes, err := hex.DecodeString(v.Pubkey)
|
||||
pubkeyBytes, err := hex.DecodeString(v.PubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -16,36 +16,36 @@ var inputs = []domain.Vtxo{
|
||||
Txid: "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
VOut: 0,
|
||||
},
|
||||
Pubkey: pubkey,
|
||||
PubKey: pubkey,
|
||||
Amount: 1000,
|
||||
},
|
||||
}
|
||||
|
||||
func TestPayment(t *testing.T) {
|
||||
t.Run("new_payment", func(t *testing.T) {
|
||||
func TestTxRequest(t *testing.T) {
|
||||
t.Run("new_tx_request", func(t *testing.T) {
|
||||
t.Run("valid", func(t *testing.T) {
|
||||
payment, err := domain.NewPayment(inputs)
|
||||
request, err := domain.NewTxRequest(inputs)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, payment)
|
||||
require.NotEmpty(t, payment.Id)
|
||||
require.Exactly(t, inputs, payment.Inputs)
|
||||
require.Empty(t, payment.Receivers)
|
||||
require.NotNil(t, request)
|
||||
require.NotEmpty(t, request.Id)
|
||||
require.Exactly(t, inputs, request.Inputs)
|
||||
require.Empty(t, request.Receivers)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("add_receivers", func(t *testing.T) {
|
||||
t.Run("valid", func(t *testing.T) {
|
||||
payment, err := domain.NewPayment(inputs)
|
||||
request, err := domain.NewTxRequest(inputs)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, payment)
|
||||
require.NotNil(t, request)
|
||||
|
||||
err = payment.AddReceivers([]domain.Receiver{
|
||||
err = request.AddReceivers([]domain.Receiver{
|
||||
{
|
||||
Pubkey: pubkey,
|
||||
PubKey: pubkey,
|
||||
Amount: 450,
|
||||
},
|
||||
{
|
||||
Pubkey: pubkey,
|
||||
PubKey: pubkey,
|
||||
Amount: 550,
|
||||
},
|
||||
})
|
||||
@@ -63,12 +63,12 @@ func TestPayment(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
payment, err := domain.NewPayment(inputs)
|
||||
request, err := domain.NewTxRequest(inputs)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, payment)
|
||||
require.NotNil(t, request)
|
||||
|
||||
for _, f := range fixtures {
|
||||
err := payment.AddReceivers(f.receivers)
|
||||
err := request.AddReceivers(f.receivers)
|
||||
require.EqualError(t, err, f.expectedErr)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -38,11 +38,11 @@ type Round struct {
|
||||
StartingTimestamp int64
|
||||
EndingTimestamp int64
|
||||
Stage Stage
|
||||
Payments map[string]Payment
|
||||
TxRequests map[string]TxRequest
|
||||
Txid string
|
||||
UnsignedTx string
|
||||
ForfeitTxs []string
|
||||
CongestionTree tree.CongestionTree
|
||||
VtxoTree tree.VtxoTree
|
||||
Connectors []string
|
||||
ConnectorAddress string
|
||||
DustAmount uint64
|
||||
@@ -55,7 +55,7 @@ func NewRound(dustAmount uint64) *Round {
|
||||
return &Round{
|
||||
Id: uuid.New().String(),
|
||||
DustAmount: dustAmount,
|
||||
Payments: make(map[string]Payment),
|
||||
TxRequests: make(map[string]TxRequest),
|
||||
changes: make([]RoundEvent, 0),
|
||||
}
|
||||
}
|
||||
@@ -84,7 +84,7 @@ func (r *Round) On(event RoundEvent, replayed bool) {
|
||||
r.StartingTimestamp = e.Timestamp
|
||||
case RoundFinalizationStarted:
|
||||
r.Stage.Code = FinalizationStage
|
||||
r.CongestionTree = e.CongestionTree
|
||||
r.VtxoTree = e.VtxoTree
|
||||
r.Connectors = append([]string{}, e.Connectors...)
|
||||
r.ConnectorAddress = e.ConnectorAddress
|
||||
r.UnsignedTx = e.RoundTx
|
||||
@@ -96,12 +96,12 @@ func (r *Round) On(event RoundEvent, replayed bool) {
|
||||
case RoundFailed:
|
||||
r.Stage.Failed = true
|
||||
r.EndingTimestamp = e.Timestamp
|
||||
case PaymentsRegistered:
|
||||
if r.Payments == nil {
|
||||
r.Payments = make(map[string]Payment)
|
||||
case TxRequestsRegistered:
|
||||
if r.TxRequests == nil {
|
||||
r.TxRequests = make(map[string]TxRequest)
|
||||
}
|
||||
for _, p := range e.Payments {
|
||||
r.Payments[p.Id] = p
|
||||
for _, p := range e.TxRequests {
|
||||
r.TxRequests[p.Id] = p
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ func (r *Round) On(event RoundEvent, replayed bool) {
|
||||
func (r *Round) StartRegistration() ([]RoundEvent, error) {
|
||||
empty := Stage{}
|
||||
if r.Stage != empty {
|
||||
return nil, fmt.Errorf("not in a valid stage to start payment registration")
|
||||
return nil, fmt.Errorf("not in a valid stage to start tx requests registration")
|
||||
}
|
||||
|
||||
event := RoundStarted{
|
||||
@@ -125,45 +125,45 @@ func (r *Round) StartRegistration() ([]RoundEvent, error) {
|
||||
return []RoundEvent{event}, nil
|
||||
}
|
||||
|
||||
func (r *Round) RegisterPayments(payments []Payment) ([]RoundEvent, error) {
|
||||
func (r *Round) RegisterTxRequests(txRequests []TxRequest) ([]RoundEvent, error) {
|
||||
if r.Stage.Code != RegistrationStage || r.IsFailed() {
|
||||
return nil, fmt.Errorf("not in a valid stage to register payments")
|
||||
return nil, fmt.Errorf("not in a valid stage to register tx requests")
|
||||
}
|
||||
if len(payments) <= 0 {
|
||||
return nil, fmt.Errorf("missing payments to register")
|
||||
if len(txRequests) <= 0 {
|
||||
return nil, fmt.Errorf("missing tx requests to register")
|
||||
}
|
||||
for _, p := range payments {
|
||||
if err := p.validate(false); err != nil {
|
||||
for _, request := range txRequests {
|
||||
if err := request.validate(false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
event := PaymentsRegistered{
|
||||
event := TxRequestsRegistered{
|
||||
Id: r.Id,
|
||||
Payments: payments,
|
||||
TxRequests: txRequests,
|
||||
}
|
||||
r.raise(event)
|
||||
|
||||
return []RoundEvent{event}, nil
|
||||
}
|
||||
|
||||
func (r *Round) StartFinalization(connectorAddress string, connectors []string, congestionTree tree.CongestionTree, poolTx string) ([]RoundEvent, error) {
|
||||
if len(poolTx) <= 0 {
|
||||
return nil, fmt.Errorf("missing unsigned pool tx")
|
||||
func (r *Round) StartFinalization(connectorAddress string, connectors []string, vtxoTree tree.VtxoTree, roundTx string) ([]RoundEvent, error) {
|
||||
if len(roundTx) <= 0 {
|
||||
return nil, fmt.Errorf("missing unsigned round tx")
|
||||
}
|
||||
if r.Stage.Code != RegistrationStage || r.IsFailed() {
|
||||
return nil, fmt.Errorf("not in a valid stage to start payment finalization")
|
||||
return nil, fmt.Errorf("not in a valid stage to start finalization")
|
||||
}
|
||||
if len(r.Payments) <= 0 {
|
||||
return nil, fmt.Errorf("no payments registered")
|
||||
if len(r.TxRequests) <= 0 {
|
||||
return nil, fmt.Errorf("no tx requests registered")
|
||||
}
|
||||
|
||||
event := RoundFinalizationStarted{
|
||||
Id: r.Id,
|
||||
CongestionTree: congestionTree,
|
||||
VtxoTree: vtxoTree,
|
||||
Connectors: connectors,
|
||||
ConnectorAddress: connectorAddress,
|
||||
RoundTx: poolTx,
|
||||
RoundTx: roundTx,
|
||||
}
|
||||
r.raise(event)
|
||||
|
||||
@@ -172,17 +172,17 @@ func (r *Round) StartFinalization(connectorAddress string, connectors []string,
|
||||
|
||||
func (r *Round) EndFinalization(forfeitTxs []string, txid string) ([]RoundEvent, error) {
|
||||
if len(forfeitTxs) <= 0 {
|
||||
for _, p := range r.Payments {
|
||||
if len(p.Inputs) > 0 {
|
||||
for _, request := range r.TxRequests {
|
||||
if len(request.Inputs) > 0 {
|
||||
return nil, fmt.Errorf("missing list of signed forfeit txs")
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(txid) <= 0 {
|
||||
return nil, fmt.Errorf("missing pool txid")
|
||||
return nil, fmt.Errorf("missing round txid")
|
||||
}
|
||||
if r.Stage.Code != FinalizationStage || r.IsFailed() {
|
||||
return nil, fmt.Errorf("not in a valid stage to end payment finalization")
|
||||
return nil, fmt.Errorf("not in a valid stage to end finalization")
|
||||
}
|
||||
if r.Stage.Ended {
|
||||
return nil, fmt.Errorf("round already finalized")
|
||||
@@ -231,16 +231,16 @@ func (r *Round) IsFailed() bool {
|
||||
|
||||
func (r *Round) TotalInputAmount() uint64 {
|
||||
totInputs := 0
|
||||
for _, p := range r.Payments {
|
||||
totInputs += len(p.Inputs)
|
||||
for _, request := range r.TxRequests {
|
||||
totInputs += len(request.Inputs)
|
||||
}
|
||||
return uint64(totInputs * int(r.DustAmount))
|
||||
}
|
||||
|
||||
func (r *Round) TotalOutputAmount() uint64 {
|
||||
tot := uint64(0)
|
||||
for _, p := range r.Payments {
|
||||
tot += p.TotalOutputAmount()
|
||||
for _, request := range r.TxRequests {
|
||||
tot += request.TotalOutputAmount()
|
||||
}
|
||||
return tot
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
|
||||
var (
|
||||
dustAmount = uint64(450)
|
||||
payments = []domain.Payment{
|
||||
requests = []domain.TxRequest{
|
||||
{
|
||||
Id: "0",
|
||||
Inputs: []domain.Vtxo{
|
||||
@@ -20,21 +20,21 @@ var (
|
||||
Txid: txid,
|
||||
VOut: 0,
|
||||
},
|
||||
Pubkey: pubkey,
|
||||
PubKey: pubkey,
|
||||
Amount: 2000,
|
||||
},
|
||||
},
|
||||
Receivers: []domain.Receiver{
|
||||
{
|
||||
Pubkey: pubkey,
|
||||
PubKey: pubkey,
|
||||
Amount: 700,
|
||||
},
|
||||
{
|
||||
Pubkey: pubkey,
|
||||
PubKey: pubkey,
|
||||
Amount: 700,
|
||||
},
|
||||
{
|
||||
Pubkey: pubkey,
|
||||
PubKey: pubkey,
|
||||
Amount: 600,
|
||||
},
|
||||
},
|
||||
@@ -47,7 +47,7 @@ var (
|
||||
Txid: txid,
|
||||
VOut: 0,
|
||||
},
|
||||
Pubkey: pubkey,
|
||||
PubKey: pubkey,
|
||||
Amount: 1000,
|
||||
},
|
||||
{
|
||||
@@ -55,12 +55,12 @@ var (
|
||||
Txid: txid,
|
||||
VOut: 0,
|
||||
},
|
||||
Pubkey: pubkey,
|
||||
PubKey: pubkey,
|
||||
Amount: 1000,
|
||||
},
|
||||
},
|
||||
Receivers: []domain.Receiver{{
|
||||
Pubkey: pubkey,
|
||||
PubKey: pubkey,
|
||||
Amount: 2000,
|
||||
}},
|
||||
},
|
||||
@@ -68,7 +68,7 @@ var (
|
||||
emptyPtx = "cHNldP8BAgQCAAAAAQQBAAEFAQABBgEDAfsEAgAAAAA="
|
||||
emptyTx = "0200000000000000000000"
|
||||
txid = "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
congestionTree = tree.CongestionTree{
|
||||
vtxoTree = tree.VtxoTree{
|
||||
{
|
||||
{
|
||||
Txid: txid,
|
||||
@@ -113,13 +113,13 @@ var (
|
||||
}
|
||||
connectors = []string{emptyPtx, emptyPtx, emptyPtx}
|
||||
forfeitTxs = []string{emptyPtx, emptyPtx, emptyPtx, emptyPtx, emptyPtx, emptyPtx, emptyPtx, emptyPtx, emptyPtx}
|
||||
poolTx = emptyTx
|
||||
roundTx = emptyTx
|
||||
)
|
||||
|
||||
func TestRound(t *testing.T) {
|
||||
testStartRegistration(t)
|
||||
|
||||
testRegisterPayments(t)
|
||||
testRegisterTxRequests(t)
|
||||
|
||||
testStartFinalization(t)
|
||||
|
||||
@@ -165,7 +165,7 @@ func testStartRegistration(t *testing.T) {
|
||||
Failed: true,
|
||||
},
|
||||
},
|
||||
expectedErr: "not in a valid stage to start payment registration",
|
||||
expectedErr: "not in a valid stage to start tx requests registration",
|
||||
},
|
||||
{
|
||||
round: &domain.Round{
|
||||
@@ -174,7 +174,7 @@ func testStartRegistration(t *testing.T) {
|
||||
Code: domain.RegistrationStage,
|
||||
},
|
||||
},
|
||||
expectedErr: "not in a valid stage to start payment registration",
|
||||
expectedErr: "not in a valid stage to start tx requests registration",
|
||||
},
|
||||
{
|
||||
round: &domain.Round{
|
||||
@@ -183,7 +183,7 @@ func testStartRegistration(t *testing.T) {
|
||||
Code: domain.FinalizationStage,
|
||||
},
|
||||
},
|
||||
expectedErr: "not in a valid stage to start payment registration",
|
||||
expectedErr: "not in a valid stage to start tx requests registration",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -196,20 +196,20 @@ func testStartRegistration(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func testRegisterPayments(t *testing.T) {
|
||||
t.Run("register_payments", func(t *testing.T) {
|
||||
func testRegisterTxRequests(t *testing.T) {
|
||||
t.Run("register_tx_requests", func(t *testing.T) {
|
||||
t.Run("valid", func(t *testing.T) {
|
||||
round := domain.NewRound(dustAmount)
|
||||
events, err := round.StartRegistration()
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, events)
|
||||
|
||||
events, err = round.RegisterPayments(payments)
|
||||
events, err = round.RegisterTxRequests(requests)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, events, 1)
|
||||
require.Condition(t, func() bool {
|
||||
for _, payment := range payments {
|
||||
_, ok := round.Payments[payment.Id]
|
||||
for _, request := range requests {
|
||||
_, ok := round.TxRequests[request.Id]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
@@ -217,16 +217,16 @@ func testRegisterPayments(t *testing.T) {
|
||||
return true
|
||||
})
|
||||
|
||||
event, ok := events[0].(domain.PaymentsRegistered)
|
||||
event, ok := events[0].(domain.TxRequestsRegistered)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, round.Id, event.Id)
|
||||
require.Equal(t, payments, event.Payments)
|
||||
require.Equal(t, requests, event.TxRequests)
|
||||
})
|
||||
|
||||
t.Run("invalid", func(t *testing.T) {
|
||||
fixtures := []struct {
|
||||
round *domain.Round
|
||||
payments []domain.Payment
|
||||
requests []domain.TxRequest
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
@@ -234,8 +234,8 @@ func testRegisterPayments(t *testing.T) {
|
||||
Id: "id",
|
||||
Stage: domain.Stage{},
|
||||
},
|
||||
payments: payments,
|
||||
expectedErr: "not in a valid stage to register payments",
|
||||
requests: requests,
|
||||
expectedErr: "not in a valid stage to register tx requests",
|
||||
},
|
||||
{
|
||||
round: &domain.Round{
|
||||
@@ -245,8 +245,8 @@ func testRegisterPayments(t *testing.T) {
|
||||
Failed: true,
|
||||
},
|
||||
},
|
||||
payments: payments,
|
||||
expectedErr: "not in a valid stage to register payments",
|
||||
requests: requests,
|
||||
expectedErr: "not in a valid stage to register tx requests",
|
||||
},
|
||||
{
|
||||
round: &domain.Round{
|
||||
@@ -255,8 +255,8 @@ func testRegisterPayments(t *testing.T) {
|
||||
Code: domain.FinalizationStage,
|
||||
},
|
||||
},
|
||||
payments: payments,
|
||||
expectedErr: "not in a valid stage to register payments",
|
||||
requests: requests,
|
||||
expectedErr: "not in a valid stage to register tx requests",
|
||||
},
|
||||
{
|
||||
round: &domain.Round{
|
||||
@@ -265,13 +265,13 @@ func testRegisterPayments(t *testing.T) {
|
||||
Code: domain.RegistrationStage,
|
||||
},
|
||||
},
|
||||
payments: nil,
|
||||
expectedErr: "missing payments to register",
|
||||
requests: nil,
|
||||
expectedErr: "missing tx requests to register",
|
||||
},
|
||||
}
|
||||
|
||||
for _, f := range fixtures {
|
||||
events, err := f.round.RegisterPayments(f.payments)
|
||||
events, err := f.round.RegisterTxRequests(f.requests)
|
||||
require.EqualError(t, err, f.expectedErr)
|
||||
require.Empty(t, events)
|
||||
}
|
||||
@@ -287,11 +287,11 @@ func testStartFinalization(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, events)
|
||||
|
||||
events, err = round.RegisterPayments(payments)
|
||||
events, err = round.RegisterTxRequests(requests)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, events)
|
||||
|
||||
events, err = round.StartFinalization("", connectors, congestionTree, poolTx)
|
||||
events, err = round.StartFinalization("", connectors, vtxoTree, roundTx)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, events, 1)
|
||||
require.True(t, round.IsStarted())
|
||||
@@ -302,20 +302,20 @@ func testStartFinalization(t *testing.T) {
|
||||
require.True(t, ok)
|
||||
require.Equal(t, round.Id, event.Id)
|
||||
require.Exactly(t, connectors, event.Connectors)
|
||||
require.Exactly(t, congestionTree, event.CongestionTree)
|
||||
require.Exactly(t, poolTx, event.RoundTx)
|
||||
require.Exactly(t, vtxoTree, event.VtxoTree)
|
||||
require.Exactly(t, roundTx, event.RoundTx)
|
||||
})
|
||||
|
||||
t.Run("invalid", func(t *testing.T) {
|
||||
paymentsById := map[string]domain.Payment{}
|
||||
for _, p := range payments {
|
||||
paymentsById[p.Id] = p
|
||||
requestsById := map[string]domain.TxRequest{}
|
||||
for _, p := range requests {
|
||||
requestsById[p.Id] = p
|
||||
}
|
||||
fixtures := []struct {
|
||||
round *domain.Round
|
||||
connectors []string
|
||||
tree tree.CongestionTree
|
||||
poolTx string
|
||||
tree tree.VtxoTree
|
||||
roundTx string
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
@@ -324,12 +324,12 @@ func testStartFinalization(t *testing.T) {
|
||||
Stage: domain.Stage{
|
||||
Code: domain.RegistrationStage,
|
||||
},
|
||||
Payments: paymentsById,
|
||||
TxRequests: requestsById,
|
||||
},
|
||||
connectors: connectors,
|
||||
tree: congestionTree,
|
||||
poolTx: "",
|
||||
expectedErr: "missing unsigned pool tx",
|
||||
tree: vtxoTree,
|
||||
roundTx: "",
|
||||
expectedErr: "missing unsigned round tx",
|
||||
},
|
||||
{
|
||||
round: &domain.Round{
|
||||
@@ -337,12 +337,12 @@ func testStartFinalization(t *testing.T) {
|
||||
Stage: domain.Stage{
|
||||
Code: domain.RegistrationStage,
|
||||
},
|
||||
Payments: nil,
|
||||
TxRequests: nil,
|
||||
},
|
||||
connectors: connectors,
|
||||
tree: congestionTree,
|
||||
poolTx: poolTx,
|
||||
expectedErr: "no payments registered",
|
||||
tree: vtxoTree,
|
||||
roundTx: roundTx,
|
||||
expectedErr: "no tx requests registered",
|
||||
},
|
||||
{
|
||||
round: &domain.Round{
|
||||
@@ -350,12 +350,12 @@ func testStartFinalization(t *testing.T) {
|
||||
Stage: domain.Stage{
|
||||
Code: domain.UndefinedStage,
|
||||
},
|
||||
Payments: paymentsById,
|
||||
TxRequests: requestsById,
|
||||
},
|
||||
connectors: connectors,
|
||||
tree: congestionTree,
|
||||
poolTx: poolTx,
|
||||
expectedErr: "not in a valid stage to start payment finalization",
|
||||
tree: vtxoTree,
|
||||
roundTx: roundTx,
|
||||
expectedErr: "not in a valid stage to start finalization",
|
||||
},
|
||||
{
|
||||
round: &domain.Round{
|
||||
@@ -364,12 +364,12 @@ func testStartFinalization(t *testing.T) {
|
||||
Code: domain.RegistrationStage,
|
||||
Failed: true,
|
||||
},
|
||||
Payments: paymentsById,
|
||||
TxRequests: requestsById,
|
||||
},
|
||||
connectors: connectors,
|
||||
tree: congestionTree,
|
||||
poolTx: poolTx,
|
||||
expectedErr: "not in a valid stage to start payment finalization",
|
||||
tree: vtxoTree,
|
||||
roundTx: roundTx,
|
||||
expectedErr: "not in a valid stage to start finalization",
|
||||
},
|
||||
{
|
||||
round: &domain.Round{
|
||||
@@ -377,18 +377,18 @@ func testStartFinalization(t *testing.T) {
|
||||
Stage: domain.Stage{
|
||||
Code: domain.FinalizationStage,
|
||||
},
|
||||
Payments: paymentsById,
|
||||
TxRequests: requestsById,
|
||||
},
|
||||
connectors: connectors,
|
||||
tree: congestionTree,
|
||||
poolTx: poolTx,
|
||||
expectedErr: "not in a valid stage to start payment finalization",
|
||||
tree: vtxoTree,
|
||||
roundTx: roundTx,
|
||||
expectedErr: "not in a valid stage to start finalization",
|
||||
},
|
||||
}
|
||||
|
||||
for _, f := range fixtures {
|
||||
// TODO fix this
|
||||
events, err := f.round.StartFinalization("", f.connectors, f.tree, f.poolTx)
|
||||
events, err := f.round.StartFinalization("", f.connectors, f.tree, f.roundTx)
|
||||
require.EqualError(t, err, f.expectedErr)
|
||||
require.Empty(t, events)
|
||||
}
|
||||
@@ -404,11 +404,11 @@ func testEndFinalization(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, events)
|
||||
|
||||
events, err = round.RegisterPayments(payments)
|
||||
events, err = round.RegisterTxRequests(requests)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, events)
|
||||
|
||||
events, err = round.StartFinalization("", connectors, congestionTree, poolTx)
|
||||
events, err = round.StartFinalization("", connectors, vtxoTree, roundTx)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, events)
|
||||
|
||||
@@ -428,9 +428,9 @@ func testEndFinalization(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("invalid", func(t *testing.T) {
|
||||
paymentsById := map[string]domain.Payment{}
|
||||
for _, p := range payments {
|
||||
paymentsById[p.Id] = p
|
||||
requestsById := map[string]domain.TxRequest{}
|
||||
for _, p := range requests {
|
||||
requestsById[p.Id] = p
|
||||
}
|
||||
fixtures := []struct {
|
||||
round *domain.Round
|
||||
@@ -444,7 +444,7 @@ func testEndFinalization(t *testing.T) {
|
||||
Stage: domain.Stage{
|
||||
Code: domain.FinalizationStage,
|
||||
},
|
||||
Payments: paymentsById,
|
||||
TxRequests: requestsById,
|
||||
},
|
||||
forfeitTxs: nil,
|
||||
txid: txid,
|
||||
@@ -459,7 +459,7 @@ func testEndFinalization(t *testing.T) {
|
||||
},
|
||||
forfeitTxs: forfeitTxs,
|
||||
txid: "",
|
||||
expectedErr: "missing pool txid",
|
||||
expectedErr: "missing round txid",
|
||||
},
|
||||
{
|
||||
round: &domain.Round{
|
||||
@@ -467,7 +467,7 @@ func testEndFinalization(t *testing.T) {
|
||||
},
|
||||
forfeitTxs: forfeitTxs,
|
||||
txid: txid,
|
||||
expectedErr: "not in a valid stage to end payment finalization",
|
||||
expectedErr: "not in a valid stage to end finalization",
|
||||
},
|
||||
{
|
||||
round: &domain.Round{
|
||||
@@ -478,7 +478,7 @@ func testEndFinalization(t *testing.T) {
|
||||
},
|
||||
forfeitTxs: forfeitTxs,
|
||||
txid: txid,
|
||||
expectedErr: "not in a valid stage to end payment finalization",
|
||||
expectedErr: "not in a valid stage to end finalization",
|
||||
},
|
||||
{
|
||||
round: &domain.Round{
|
||||
@@ -490,7 +490,7 @@ func testEndFinalization(t *testing.T) {
|
||||
},
|
||||
forfeitTxs: []string{emptyPtx, emptyPtx, emptyPtx, emptyPtx},
|
||||
txid: txid,
|
||||
expectedErr: "not in a valid stage to end payment finalization",
|
||||
expectedErr: "not in a valid stage to end finalization",
|
||||
},
|
||||
{
|
||||
round: &domain.Round{
|
||||
@@ -523,7 +523,7 @@ func testFail(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, events)
|
||||
|
||||
events, err = round.RegisterPayments(payments)
|
||||
events, err = round.RegisterTxRequests(requests)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, events)
|
||||
|
||||
|
||||
@@ -27,15 +27,15 @@ type BoardingInput struct {
|
||||
}
|
||||
|
||||
type TxBuilder interface {
|
||||
// BuildRoundTx builds a round tx for the given payments, boarding inputs
|
||||
// it selects coin from swept rounds and ASP wallet
|
||||
// BuildRoundTx builds a round tx for the given tx requests, boarding inputs
|
||||
// it selects coin from swept rounds and server wallet
|
||||
// returns the round partial tx, the vtxo tree and the set of connectors
|
||||
BuildRoundTx(
|
||||
aspPubkey *secp256k1.PublicKey, payments []domain.Payment, boardingInputs []BoardingInput, sweptRounds []domain.Round,
|
||||
serverPubkey *secp256k1.PublicKey, txRequests []domain.TxRequest, boardingInputs []BoardingInput, sweptRounds []domain.Round,
|
||||
cosigners ...*secp256k1.PublicKey,
|
||||
) (
|
||||
roundTx string,
|
||||
congestionTree tree.CongestionTree,
|
||||
vtxoTree tree.VtxoTree,
|
||||
connectorAddress string,
|
||||
connectors []string,
|
||||
err error,
|
||||
@@ -51,7 +51,7 @@ type TxBuilder interface {
|
||||
FinalizeAndExtract(tx string) (txhex string, err error)
|
||||
VerifyTapscriptPartialSigs(tx string) (valid bool, err error)
|
||||
// FindLeaves returns all the leaves txs that are reachable from the given outpoint
|
||||
FindLeaves(congestionTree tree.CongestionTree, fromtxid string, vout uint32) (leaves []tree.Node, err error)
|
||||
FindLeaves(vtxoTree tree.VtxoTree, fromtxid string, vout uint32) (leaves []tree.Node, err error)
|
||||
VerifyAndCombinePartialTx(dest string, src string) (string, error)
|
||||
GetTxID(tx string) (string, error)
|
||||
}
|
||||
|
||||
@@ -100,8 +100,8 @@ func deserializeEvent(buf []byte) (domain.RoundEvent, error) {
|
||||
}
|
||||
}
|
||||
{
|
||||
var event = domain.PaymentsRegistered{}
|
||||
if err := json.Unmarshal(buf, &event); err == nil && len(event.Payments) > 0 {
|
||||
var event = domain.TxRequestsRegistered{}
|
||||
if err := json.Unmarshal(buf, &event); err == nil && len(event.TxRequests) > 0 {
|
||||
return event, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ func (r *vtxoRepository) GetVtxos(
|
||||
func (r *vtxoRepository) GetVtxosForRound(
|
||||
ctx context.Context, txid string,
|
||||
) ([]domain.Vtxo, error) {
|
||||
query := badgerhold.Where("PoolTx").Eq(txid)
|
||||
query := badgerhold.Where("RoundTx").Eq(txid)
|
||||
return r.findVtxos(ctx, query)
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ func (r *vtxoRepository) GetAllVtxos(
|
||||
) ([]domain.Vtxo, []domain.Vtxo, error) {
|
||||
query := badgerhold.Where("Redeemed").Eq(false)
|
||||
if len(pubkey) > 0 {
|
||||
query = query.And("Pubkey").Eq(pubkey)
|
||||
query = query.And("PubKey").Eq(pubkey)
|
||||
}
|
||||
vtxos, err := r.findVtxos(ctx, query)
|
||||
if err != nil {
|
||||
|
||||
@@ -26,7 +26,7 @@ const (
|
||||
pubkey2 = "33ffb3dee353b1a9ebe4ced64b946238d0a4ac364f275d771da6ad2445d07ae0"
|
||||
)
|
||||
|
||||
var congestionTree = [][]tree.Node{
|
||||
var vtxoTree = [][]tree.Node{
|
||||
{
|
||||
{
|
||||
Txid: randomString(32),
|
||||
@@ -149,7 +149,7 @@ func testRoundEventRepository(t *testing.T, svc ports.RepoManager) {
|
||||
},
|
||||
domain.RoundFinalizationStarted{
|
||||
Id: "1ea610ff-bf3e-4068-9bfd-b6c3f553467e",
|
||||
CongestionTree: congestionTree,
|
||||
VtxoTree: vtxoTree,
|
||||
Connectors: []string{emptyPtx, emptyPtx},
|
||||
RoundTx: emptyTx,
|
||||
},
|
||||
@@ -157,8 +157,8 @@ func testRoundEventRepository(t *testing.T, svc ports.RepoManager) {
|
||||
handler: func(round *domain.Round) {
|
||||
require.NotNil(t, round)
|
||||
require.Len(t, round.Events(), 2)
|
||||
require.Len(t, round.CongestionTree, 3)
|
||||
require.Equal(t, round.CongestionTree.NumberOfNodes(), 7)
|
||||
require.Len(t, round.VtxoTree, 3)
|
||||
require.Equal(t, round.VtxoTree.NumberOfNodes(), 7)
|
||||
require.Len(t, round.Connectors, 2)
|
||||
},
|
||||
},
|
||||
@@ -171,7 +171,7 @@ func testRoundEventRepository(t *testing.T, svc ports.RepoManager) {
|
||||
},
|
||||
domain.RoundFinalizationStarted{
|
||||
Id: "7578231e-428d-45ae-aaa4-e62c77ad5cec",
|
||||
CongestionTree: congestionTree,
|
||||
VtxoTree: vtxoTree,
|
||||
Connectors: []string{emptyPtx, emptyPtx},
|
||||
RoundTx: emptyTx,
|
||||
},
|
||||
@@ -237,9 +237,9 @@ func testRoundRepository(t *testing.T, svc ports.RepoManager) {
|
||||
require.Condition(t, roundsMatch(*round, *roundById))
|
||||
|
||||
newEvents := []domain.RoundEvent{
|
||||
domain.PaymentsRegistered{
|
||||
domain.TxRequestsRegistered{
|
||||
Id: roundId,
|
||||
Payments: []domain.Payment{
|
||||
TxRequests: []domain.TxRequest{
|
||||
{
|
||||
Id: uuid.New().String(),
|
||||
Inputs: []domain.Vtxo{
|
||||
@@ -250,12 +250,12 @@ func testRoundRepository(t *testing.T, svc ports.RepoManager) {
|
||||
},
|
||||
RoundTxid: randomString(32),
|
||||
ExpireAt: 7980322,
|
||||
Pubkey: randomString(32),
|
||||
PubKey: randomString(32),
|
||||
Amount: 300,
|
||||
},
|
||||
},
|
||||
Receivers: []domain.Receiver{{
|
||||
Pubkey: randomString(32),
|
||||
PubKey: randomString(32),
|
||||
Amount: 300,
|
||||
}},
|
||||
},
|
||||
@@ -270,17 +270,17 @@ func testRoundRepository(t *testing.T, svc ports.RepoManager) {
|
||||
},
|
||||
RoundTxid: randomString(32),
|
||||
ExpireAt: 7980322,
|
||||
Pubkey: randomString(32),
|
||||
PubKey: randomString(32),
|
||||
Amount: 600,
|
||||
},
|
||||
},
|
||||
Receivers: []domain.Receiver{
|
||||
{
|
||||
Pubkey: randomString(32),
|
||||
PubKey: randomString(32),
|
||||
Amount: 400,
|
||||
},
|
||||
{
|
||||
Pubkey: randomString(32),
|
||||
PubKey: randomString(32),
|
||||
Amount: 200,
|
||||
},
|
||||
},
|
||||
@@ -289,15 +289,15 @@ func testRoundRepository(t *testing.T, svc ports.RepoManager) {
|
||||
},
|
||||
domain.RoundFinalizationStarted{
|
||||
Id: roundId,
|
||||
CongestionTree: congestionTree,
|
||||
VtxoTree: vtxoTree,
|
||||
Connectors: []string{emptyPtx, emptyPtx},
|
||||
RoundTx: emptyTx,
|
||||
},
|
||||
}
|
||||
events = append(events, newEvents...)
|
||||
updatedRound := domain.NewRoundFromEvents(events)
|
||||
for _, pay := range updatedRound.Payments {
|
||||
err = svc.Vtxos().AddVtxos(ctx, pay.Inputs)
|
||||
for _, request := range updatedRound.TxRequests {
|
||||
err = svc.Vtxos().AddVtxos(ctx, request.Inputs)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -346,7 +346,7 @@ func testVtxoRepository(t *testing.T, svc ports.RepoManager) {
|
||||
Txid: randomString(32),
|
||||
VOut: 0,
|
||||
},
|
||||
Pubkey: pubkey,
|
||||
PubKey: pubkey,
|
||||
Amount: 1000,
|
||||
},
|
||||
{
|
||||
@@ -354,7 +354,7 @@ func testVtxoRepository(t *testing.T, svc ports.RepoManager) {
|
||||
Txid: randomString(32),
|
||||
VOut: 1,
|
||||
},
|
||||
Pubkey: pubkey,
|
||||
PubKey: pubkey,
|
||||
Amount: 2000,
|
||||
},
|
||||
}
|
||||
@@ -363,7 +363,7 @@ func testVtxoRepository(t *testing.T, svc ports.RepoManager) {
|
||||
Txid: randomString(32),
|
||||
VOut: 1,
|
||||
},
|
||||
Pubkey: pubkey2,
|
||||
PubKey: pubkey2,
|
||||
Amount: 2000,
|
||||
})
|
||||
|
||||
@@ -567,8 +567,8 @@ func roundsMatch(expected, got domain.Round) assert.Comparison {
|
||||
return false
|
||||
}
|
||||
|
||||
for k, v := range expected.Payments {
|
||||
gotValue, ok := got.Payments[k]
|
||||
for k, v := range expected.TxRequests {
|
||||
gotValue, ok := got.TxRequests[k]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
@@ -612,7 +612,7 @@ func roundsMatch(expected, got domain.Round) assert.Comparison {
|
||||
}
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(expected.CongestionTree, got.CongestionTree) {
|
||||
if !reflect.DeepEqual(expected.VtxoTree, got.VtxoTree) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
DROP TABLE IF EXISTS round;
|
||||
|
||||
DROP TABLE IF EXISTS payment;
|
||||
DROP TABLE IF EXISTS tx_request;
|
||||
|
||||
DROP TABLE IF EXISTS receiver;
|
||||
|
||||
|
||||
@@ -13,19 +13,19 @@ CREATE TABLE IF NOT EXISTS round (
|
||||
swept BOOLEAN NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS payment (
|
||||
CREATE TABLE IF NOT EXISTS tx_request (
|
||||
id TEXT PRIMARY KEY,
|
||||
round_id TEXT NOT NULL,
|
||||
FOREIGN KEY (round_id) REFERENCES round(id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS receiver (
|
||||
payment_id TEXT NOT NULL,
|
||||
request_id TEXT NOT NULL,
|
||||
pubkey TEXT,
|
||||
onchain_address TEXT,
|
||||
amount INTEGER NOT NULL,
|
||||
FOREIGN KEY (payment_id) REFERENCES payment(id),
|
||||
PRIMARY KEY (payment_id, pubkey, onchain_address)
|
||||
FOREIGN KEY (request_id) REFERENCES tx_request(id),
|
||||
PRIMARY KEY (request_id, pubkey, onchain_address)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tx (
|
||||
@@ -46,17 +46,17 @@ CREATE TABLE IF NOT EXISTS vtxo (
|
||||
vout INTEGER NOT NULL,
|
||||
pubkey TEXT NOT NULL,
|
||||
amount INTEGER NOT NULL,
|
||||
pool_tx TEXT NOT NULL,
|
||||
round_tx TEXT NOT NULL,
|
||||
spent_by TEXT NOT NULL,
|
||||
spent BOOLEAN NOT NULL,
|
||||
redeemed BOOLEAN NOT NULL,
|
||||
swept BOOLEAN NOT NULL,
|
||||
expire_at INTEGER NOT NULL,
|
||||
created_at INTEGER NOT NULL,
|
||||
payment_id TEXT,
|
||||
request_id TEXT,
|
||||
redeem_tx TEXT,
|
||||
PRIMARY KEY (txid, vout),
|
||||
FOREIGN KEY (payment_id) REFERENCES payment(id)
|
||||
FOREIGN KEY (request_id) REFERENCES tx_request(id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS note (
|
||||
@@ -81,22 +81,22 @@ FROM entity
|
||||
LEFT OUTER JOIN entity_vtxo
|
||||
ON entity.id=entity_vtxo.entity_id;
|
||||
|
||||
CREATE VIEW round_payment_vw AS SELECT payment.*
|
||||
CREATE VIEW round_request_vw AS SELECT tx_request.*
|
||||
FROM round
|
||||
LEFT OUTER JOIN payment
|
||||
ON round.id=payment.round_id;
|
||||
LEFT OUTER JOIN tx_request
|
||||
ON round.id=tx_request.round_id;
|
||||
|
||||
CREATE VIEW round_tx_vw AS SELECT tx.*
|
||||
FROM round
|
||||
LEFT OUTER JOIN tx
|
||||
ON round.id=tx.round_id;
|
||||
|
||||
CREATE VIEW payment_receiver_vw AS SELECT receiver.*
|
||||
FROM payment
|
||||
CREATE VIEW request_receiver_vw AS SELECT receiver.*
|
||||
FROM tx_request
|
||||
LEFT OUTER JOIN receiver
|
||||
ON payment.id=receiver.payment_id;
|
||||
ON tx_request.id=receiver.request_id;
|
||||
|
||||
CREATE VIEW payment_vtxo_vw AS SELECT vtxo.*
|
||||
FROM payment
|
||||
CREATE VIEW request_vtxo_vw AS SELECT vtxo.*
|
||||
FROM tx_request
|
||||
LEFT OUTER JOIN vtxo
|
||||
ON payment.id=vtxo.payment_id;
|
||||
ON tx_request.id=vtxo.request_id;
|
||||
@@ -86,7 +86,7 @@ func (r *roundRepository) AddOrUpdateRound(ctx context.Context, round domain.Rou
|
||||
return fmt.Errorf("failed to upsert round: %w", err)
|
||||
}
|
||||
|
||||
if len(round.ForfeitTxs) > 0 || len(round.Connectors) > 0 || len(round.CongestionTree) > 0 {
|
||||
if len(round.ForfeitTxs) > 0 || len(round.Connectors) > 0 || len(round.VtxoTree) > 0 {
|
||||
for pos, tx := range round.ForfeitTxs {
|
||||
if err := querierWithTx.UpsertTransaction(
|
||||
ctx,
|
||||
@@ -115,7 +115,7 @@ func (r *roundRepository) AddOrUpdateRound(ctx context.Context, round domain.Rou
|
||||
}
|
||||
}
|
||||
|
||||
for level, levelTxs := range round.CongestionTree {
|
||||
for level, levelTxs := range round.VtxoTree {
|
||||
for pos, tx := range levelTxs {
|
||||
if err := querierWithTx.UpsertTransaction(
|
||||
ctx,
|
||||
@@ -148,27 +148,27 @@ func (r *roundRepository) AddOrUpdateRound(ctx context.Context, round domain.Rou
|
||||
}
|
||||
}
|
||||
|
||||
if len(round.Payments) > 0 {
|
||||
for _, payment := range round.Payments {
|
||||
if err := querierWithTx.UpsertPayment(
|
||||
if len(round.TxRequests) > 0 {
|
||||
for _, request := range round.TxRequests {
|
||||
if err := querierWithTx.UpsertTxRequest(
|
||||
ctx,
|
||||
queries.UpsertPaymentParams{
|
||||
ID: payment.Id,
|
||||
queries.UpsertTxRequestParams{
|
||||
ID: request.Id,
|
||||
RoundID: round.Id,
|
||||
},
|
||||
); err != nil {
|
||||
return fmt.Errorf("failed to upsert payment: %w", err)
|
||||
return fmt.Errorf("failed to upsert tx request: %w", err)
|
||||
}
|
||||
|
||||
for _, receiver := range payment.Receivers {
|
||||
for _, receiver := range request.Receivers {
|
||||
if err := querierWithTx.UpsertReceiver(
|
||||
ctx,
|
||||
queries.UpsertReceiverParams{
|
||||
PaymentID: payment.Id,
|
||||
RequestID: request.Id,
|
||||
Amount: int64(receiver.Amount),
|
||||
Pubkey: sql.NullString{
|
||||
String: receiver.Pubkey,
|
||||
Valid: len(receiver.Pubkey) > 0,
|
||||
String: receiver.PubKey,
|
||||
Valid: len(receiver.PubKey) > 0,
|
||||
},
|
||||
OnchainAddress: sql.NullString{
|
||||
String: receiver.OnchainAddress,
|
||||
@@ -180,19 +180,19 @@ func (r *roundRepository) AddOrUpdateRound(ctx context.Context, round domain.Rou
|
||||
}
|
||||
}
|
||||
|
||||
for _, input := range payment.Inputs {
|
||||
if err := querierWithTx.UpdateVtxoPaymentId(
|
||||
for _, input := range request.Inputs {
|
||||
if err := querierWithTx.UpdateVtxoRequestId(
|
||||
ctx,
|
||||
queries.UpdateVtxoPaymentIdParams{
|
||||
PaymentID: sql.NullString{
|
||||
String: payment.Id,
|
||||
queries.UpdateVtxoRequestIdParams{
|
||||
RequestID: sql.NullString{
|
||||
String: request.Id,
|
||||
Valid: true,
|
||||
},
|
||||
Txid: input.Txid,
|
||||
Vout: int64(input.VOut),
|
||||
},
|
||||
); err != nil {
|
||||
return fmt.Errorf("failed to update vtxo payment id: %w", err)
|
||||
return fmt.Errorf("failed to update vtxo request id: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -210,18 +210,18 @@ func (r *roundRepository) GetRoundWithId(ctx context.Context, id string) (*domai
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rvs := make([]roundPaymentTxReceiverVtxoRow, 0, len(rows))
|
||||
rvs := make([]combinedRow, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
rvs = append(rvs, roundPaymentTxReceiverVtxoRow{
|
||||
rvs = append(rvs, combinedRow{
|
||||
round: row.Round,
|
||||
payment: row.RoundPaymentVw,
|
||||
request: row.RoundRequestVw,
|
||||
tx: row.RoundTxVw,
|
||||
receiver: row.PaymentReceiverVw,
|
||||
vtxo: row.PaymentVtxoVw,
|
||||
receiver: row.RequestReceiverVw,
|
||||
vtxo: row.RequestVtxoVw,
|
||||
})
|
||||
}
|
||||
|
||||
rounds, err := readRoundRows(rvs)
|
||||
rounds, err := rowsToRounds(rvs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -239,18 +239,18 @@ func (r *roundRepository) GetRoundWithTxid(ctx context.Context, txid string) (*d
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rvs := make([]roundPaymentTxReceiverVtxoRow, 0, len(rows))
|
||||
rvs := make([]combinedRow, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
rvs = append(rvs, roundPaymentTxReceiverVtxoRow{
|
||||
rvs = append(rvs, combinedRow{
|
||||
round: row.Round,
|
||||
payment: row.RoundPaymentVw,
|
||||
request: row.RoundRequestVw,
|
||||
tx: row.RoundTxVw,
|
||||
receiver: row.PaymentReceiverVw,
|
||||
vtxo: row.PaymentVtxoVw,
|
||||
receiver: row.RequestReceiverVw,
|
||||
vtxo: row.RequestVtxoVw,
|
||||
})
|
||||
}
|
||||
|
||||
rounds, err := readRoundRows(rvs)
|
||||
rounds, err := rowsToRounds(rvs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -268,18 +268,18 @@ func (r *roundRepository) GetSweepableRounds(ctx context.Context) ([]domain.Roun
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rvs := make([]roundPaymentTxReceiverVtxoRow, 0, len(rows))
|
||||
rvs := make([]combinedRow, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
rvs = append(rvs, roundPaymentTxReceiverVtxoRow{
|
||||
rvs = append(rvs, combinedRow{
|
||||
round: row.Round,
|
||||
payment: row.RoundPaymentVw,
|
||||
request: row.RoundRequestVw,
|
||||
tx: row.RoundTxVw,
|
||||
receiver: row.PaymentReceiverVw,
|
||||
vtxo: row.PaymentVtxoVw,
|
||||
receiver: row.RequestReceiverVw,
|
||||
vtxo: row.RequestVtxoVw,
|
||||
})
|
||||
}
|
||||
|
||||
rounds, err := readRoundRows(rvs)
|
||||
rounds, err := rowsToRounds(rvs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -299,18 +299,18 @@ func (r *roundRepository) GetSweptRounds(ctx context.Context) ([]domain.Round, e
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rvs := make([]roundPaymentTxReceiverVtxoRow, 0, len(rows))
|
||||
rvs := make([]combinedRow, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
rvs = append(rvs, roundPaymentTxReceiverVtxoRow{
|
||||
rvs = append(rvs, combinedRow{
|
||||
round: row.Round,
|
||||
payment: row.RoundPaymentVw,
|
||||
request: row.RoundRequestVw,
|
||||
tx: row.RoundTxVw,
|
||||
receiver: row.PaymentReceiverVw,
|
||||
vtxo: row.PaymentVtxoVw,
|
||||
receiver: row.RequestReceiverVw,
|
||||
vtxo: row.RequestVtxoVw,
|
||||
})
|
||||
}
|
||||
|
||||
rounds, err := readRoundRows(rvs)
|
||||
rounds, err := rowsToRounds(rvs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -324,23 +324,23 @@ func (r *roundRepository) GetSweptRounds(ctx context.Context) ([]domain.Round, e
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func rowToReceiver(row queries.PaymentReceiverVw) domain.Receiver {
|
||||
func rowToReceiver(row queries.RequestReceiverVw) domain.Receiver {
|
||||
return domain.Receiver{
|
||||
Amount: uint64(row.Amount.Int64),
|
||||
Pubkey: row.Pubkey.String,
|
||||
PubKey: row.Pubkey.String,
|
||||
OnchainAddress: row.OnchainAddress.String,
|
||||
}
|
||||
}
|
||||
|
||||
type roundPaymentTxReceiverVtxoRow struct {
|
||||
type combinedRow struct {
|
||||
round queries.Round
|
||||
payment queries.RoundPaymentVw
|
||||
request queries.RoundRequestVw
|
||||
tx queries.RoundTxVw
|
||||
receiver queries.PaymentReceiverVw
|
||||
vtxo queries.PaymentVtxoVw
|
||||
receiver queries.RequestReceiverVw
|
||||
vtxo queries.RequestVtxoVw
|
||||
}
|
||||
|
||||
func readRoundRows(rows []roundPaymentTxReceiverVtxoRow) ([]*domain.Round, error) {
|
||||
func rowsToRounds(rows []combinedRow) ([]*domain.Round, error) {
|
||||
rounds := make(map[string]*domain.Round)
|
||||
|
||||
for _, v := range rows {
|
||||
@@ -364,35 +364,34 @@ func readRoundRows(rows []roundPaymentTxReceiverVtxoRow) ([]*domain.Round, error
|
||||
DustAmount: uint64(v.round.DustAmount),
|
||||
Version: uint(v.round.Version),
|
||||
Swept: v.round.Swept,
|
||||
Payments: make(map[string]domain.Payment),
|
||||
TxRequests: make(map[string]domain.TxRequest),
|
||||
}
|
||||
}
|
||||
|
||||
if v.payment.ID.Valid {
|
||||
payment, ok := round.Payments[v.payment.ID.String]
|
||||
if v.request.ID.Valid {
|
||||
request, ok := round.TxRequests[v.request.ID.String]
|
||||
if !ok {
|
||||
payment = domain.Payment{
|
||||
Id: v.payment.ID.String,
|
||||
request = domain.TxRequest{
|
||||
Id: v.request.ID.String,
|
||||
Inputs: make([]domain.Vtxo, 0),
|
||||
Receivers: make([]domain.Receiver, 0),
|
||||
}
|
||||
round.Payments[v.payment.ID.String] = payment
|
||||
round.TxRequests[v.request.ID.String] = request
|
||||
}
|
||||
|
||||
if v.vtxo.PaymentID.Valid {
|
||||
payment, ok = round.Payments[v.vtxo.PaymentID.String]
|
||||
if v.vtxo.RequestID.Valid {
|
||||
request, ok = round.TxRequests[v.vtxo.RequestID.String]
|
||||
if !ok {
|
||||
payment = domain.Payment{
|
||||
Id: v.vtxo.PaymentID.String,
|
||||
request = domain.TxRequest{
|
||||
Id: v.vtxo.RequestID.String,
|
||||
Inputs: make([]domain.Vtxo, 0),
|
||||
Receivers: make([]domain.Receiver, 0),
|
||||
}
|
||||
}
|
||||
|
||||
vtxo := rowToPaymentVtxoVw(v.vtxo)
|
||||
vtxo := combinedRowToVtxo(v.vtxo)
|
||||
found := false
|
||||
|
||||
for _, v := range payment.Inputs {
|
||||
for _, v := range request.Inputs {
|
||||
if vtxo.Txid == v.Txid && vtxo.VOut == v.VOut {
|
||||
found = true
|
||||
break
|
||||
@@ -400,16 +399,16 @@ func readRoundRows(rows []roundPaymentTxReceiverVtxoRow) ([]*domain.Round, error
|
||||
}
|
||||
|
||||
if !found {
|
||||
payment.Inputs = append(payment.Inputs, rowToPaymentVtxoVw(v.vtxo))
|
||||
round.Payments[v.vtxo.PaymentID.String] = payment
|
||||
request.Inputs = append(request.Inputs, combinedRowToVtxo(v.vtxo))
|
||||
round.TxRequests[v.vtxo.RequestID.String] = request
|
||||
}
|
||||
}
|
||||
|
||||
if v.receiver.PaymentID.Valid {
|
||||
payment, ok = round.Payments[v.receiver.PaymentID.String]
|
||||
if v.receiver.RequestID.Valid {
|
||||
request, ok = round.TxRequests[v.receiver.RequestID.String]
|
||||
if !ok {
|
||||
payment = domain.Payment{
|
||||
Id: v.receiver.PaymentID.String,
|
||||
request = domain.TxRequest{
|
||||
Id: v.receiver.RequestID.String,
|
||||
Inputs: make([]domain.Vtxo, 0),
|
||||
Receivers: make([]domain.Receiver, 0),
|
||||
}
|
||||
@@ -418,17 +417,17 @@ func readRoundRows(rows []roundPaymentTxReceiverVtxoRow) ([]*domain.Round, error
|
||||
rcv := rowToReceiver(v.receiver)
|
||||
|
||||
found := false
|
||||
for _, rcv := range payment.Receivers {
|
||||
for _, rcv := range request.Receivers {
|
||||
if (v.receiver.Pubkey.Valid || v.receiver.OnchainAddress.Valid) && v.receiver.Amount.Valid {
|
||||
if rcv.Pubkey == v.receiver.Pubkey.String && rcv.OnchainAddress == v.receiver.OnchainAddress.String && int64(rcv.Amount) == v.receiver.Amount.Int64 {
|
||||
if rcv.PubKey == v.receiver.Pubkey.String && rcv.OnchainAddress == v.receiver.OnchainAddress.String && int64(rcv.Amount) == v.receiver.Amount.Int64 {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
payment.Receivers = append(payment.Receivers, rcv)
|
||||
round.Payments[v.receiver.PaymentID.String] = payment
|
||||
request.Receivers = append(request.Receivers, rcv)
|
||||
round.TxRequests[v.receiver.RequestID.String] = request
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -444,10 +443,10 @@ func readRoundRows(rows []roundPaymentTxReceiverVtxoRow) ([]*domain.Round, error
|
||||
round.Connectors[position.Int64] = v.tx.Tx.String
|
||||
case "tree":
|
||||
level := v.tx.TreeLevel
|
||||
round.CongestionTree = extendArray(round.CongestionTree, int(level.Int64))
|
||||
round.CongestionTree[int(level.Int64)] = extendArray(round.CongestionTree[int(level.Int64)], int(position.Int64))
|
||||
if round.CongestionTree[int(level.Int64)][position.Int64] == (tree.Node{}) {
|
||||
round.CongestionTree[int(level.Int64)][position.Int64] = tree.Node{
|
||||
round.VtxoTree = extendArray(round.VtxoTree, int(level.Int64))
|
||||
round.VtxoTree[int(level.Int64)] = extendArray(round.VtxoTree[int(level.Int64)], int(position.Int64))
|
||||
if round.VtxoTree[int(level.Int64)][position.Int64] == (tree.Node{}) {
|
||||
round.VtxoTree[int(level.Int64)][position.Int64] = tree.Node{
|
||||
Tx: v.tx.Tx.String,
|
||||
Txid: v.tx.Txid.String,
|
||||
ParentTxid: v.tx.ParentTxid.String,
|
||||
@@ -469,15 +468,15 @@ func readRoundRows(rows []roundPaymentTxReceiverVtxoRow) ([]*domain.Round, error
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func rowToPaymentVtxoVw(row queries.PaymentVtxoVw) domain.Vtxo {
|
||||
func combinedRowToVtxo(row queries.RequestVtxoVw) domain.Vtxo {
|
||||
return domain.Vtxo{
|
||||
VtxoKey: domain.VtxoKey{
|
||||
Txid: row.Txid.String,
|
||||
VOut: uint32(row.Vout.Int64),
|
||||
},
|
||||
Amount: uint64(row.Amount.Int64),
|
||||
Pubkey: row.Pubkey.String,
|
||||
RoundTxid: row.PoolTx.String,
|
||||
PubKey: row.Pubkey.String,
|
||||
RoundTxid: row.RoundTx.String,
|
||||
SpentBy: row.SpentBy.String,
|
||||
Spent: row.Spent.Bool,
|
||||
Redeemed: row.Redeemed.Bool,
|
||||
|
||||
@@ -39,41 +39,36 @@ type Note struct {
|
||||
ID int64
|
||||
}
|
||||
|
||||
type Payment struct {
|
||||
ID string
|
||||
RoundID string
|
||||
type Receiver struct {
|
||||
RequestID string
|
||||
Pubkey sql.NullString
|
||||
OnchainAddress sql.NullString
|
||||
Amount int64
|
||||
}
|
||||
|
||||
type PaymentReceiverVw struct {
|
||||
PaymentID sql.NullString
|
||||
type RequestReceiverVw struct {
|
||||
RequestID sql.NullString
|
||||
Pubkey sql.NullString
|
||||
OnchainAddress sql.NullString
|
||||
Amount sql.NullInt64
|
||||
}
|
||||
|
||||
type PaymentVtxoVw struct {
|
||||
type RequestVtxoVw struct {
|
||||
Txid sql.NullString
|
||||
Vout sql.NullInt64
|
||||
Pubkey sql.NullString
|
||||
Amount sql.NullInt64
|
||||
PoolTx sql.NullString
|
||||
RoundTx sql.NullString
|
||||
SpentBy sql.NullString
|
||||
Spent sql.NullBool
|
||||
Redeemed sql.NullBool
|
||||
Swept sql.NullBool
|
||||
ExpireAt sql.NullInt64
|
||||
CreatedAt sql.NullInt64
|
||||
PaymentID sql.NullString
|
||||
RequestID sql.NullString
|
||||
RedeemTx sql.NullString
|
||||
}
|
||||
|
||||
type Receiver struct {
|
||||
PaymentID string
|
||||
Pubkey sql.NullString
|
||||
OnchainAddress sql.NullString
|
||||
Amount int64
|
||||
}
|
||||
|
||||
type Round struct {
|
||||
ID string
|
||||
StartingTimestamp int64
|
||||
@@ -89,7 +84,7 @@ type Round struct {
|
||||
Swept bool
|
||||
}
|
||||
|
||||
type RoundPaymentVw struct {
|
||||
type RoundRequestVw struct {
|
||||
ID sql.NullString
|
||||
RoundID sql.NullString
|
||||
}
|
||||
@@ -118,18 +113,23 @@ type Tx struct {
|
||||
IsLeaf sql.NullBool
|
||||
}
|
||||
|
||||
type TxRequest struct {
|
||||
ID string
|
||||
RoundID string
|
||||
}
|
||||
|
||||
type Vtxo struct {
|
||||
Txid string
|
||||
Vout int64
|
||||
Pubkey string
|
||||
Amount int64
|
||||
PoolTx string
|
||||
RoundTx string
|
||||
SpentBy string
|
||||
Spent bool
|
||||
Redeemed bool
|
||||
Swept bool
|
||||
ExpireAt int64
|
||||
CreatedAt int64
|
||||
PaymentID sql.NullString
|
||||
RequestID sql.NullString
|
||||
RedeemTx sql.NullString
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ func (q *Queries) SelectEntitiesByVtxo(ctx context.Context, arg SelectEntitiesBy
|
||||
}
|
||||
|
||||
const selectNotRedeemedVtxos = `-- name: SelectNotRedeemedVtxos :many
|
||||
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.pool_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.created_at, vtxo.payment_id, vtxo.redeem_tx FROM vtxo
|
||||
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.round_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.created_at, vtxo.request_id, vtxo.redeem_tx FROM vtxo
|
||||
WHERE redeemed = false
|
||||
`
|
||||
|
||||
@@ -213,14 +213,14 @@ func (q *Queries) SelectNotRedeemedVtxos(ctx context.Context) ([]SelectNotRedeem
|
||||
&i.Vtxo.Vout,
|
||||
&i.Vtxo.Pubkey,
|
||||
&i.Vtxo.Amount,
|
||||
&i.Vtxo.PoolTx,
|
||||
&i.Vtxo.RoundTx,
|
||||
&i.Vtxo.SpentBy,
|
||||
&i.Vtxo.Spent,
|
||||
&i.Vtxo.Redeemed,
|
||||
&i.Vtxo.Swept,
|
||||
&i.Vtxo.ExpireAt,
|
||||
&i.Vtxo.CreatedAt,
|
||||
&i.Vtxo.PaymentID,
|
||||
&i.Vtxo.RequestID,
|
||||
&i.Vtxo.RedeemTx,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
@@ -237,7 +237,7 @@ func (q *Queries) SelectNotRedeemedVtxos(ctx context.Context) ([]SelectNotRedeem
|
||||
}
|
||||
|
||||
const selectNotRedeemedVtxosWithPubkey = `-- name: SelectNotRedeemedVtxosWithPubkey :many
|
||||
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.pool_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.created_at, vtxo.payment_id, vtxo.redeem_tx FROM vtxo
|
||||
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.round_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.created_at, vtxo.request_id, vtxo.redeem_tx FROM vtxo
|
||||
WHERE redeemed = false AND pubkey = ?
|
||||
`
|
||||
|
||||
@@ -259,14 +259,14 @@ func (q *Queries) SelectNotRedeemedVtxosWithPubkey(ctx context.Context, pubkey s
|
||||
&i.Vtxo.Vout,
|
||||
&i.Vtxo.Pubkey,
|
||||
&i.Vtxo.Amount,
|
||||
&i.Vtxo.PoolTx,
|
||||
&i.Vtxo.RoundTx,
|
||||
&i.Vtxo.SpentBy,
|
||||
&i.Vtxo.Spent,
|
||||
&i.Vtxo.Redeemed,
|
||||
&i.Vtxo.Swept,
|
||||
&i.Vtxo.ExpireAt,
|
||||
&i.Vtxo.CreatedAt,
|
||||
&i.Vtxo.PaymentID,
|
||||
&i.Vtxo.RequestID,
|
||||
&i.Vtxo.RedeemTx,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
@@ -343,24 +343,24 @@ func (q *Queries) SelectRoundIdsInRange(ctx context.Context, arg SelectRoundIdsI
|
||||
|
||||
const selectRoundWithRoundId = `-- name: SelectRoundWithRoundId :many
|
||||
SELECT round.id, round.starting_timestamp, round.ending_timestamp, round.ended, round.failed, round.stage_code, round.txid, round.unsigned_tx, round.connector_address, round.dust_amount, round.version, round.swept,
|
||||
round_payment_vw.id, round_payment_vw.round_id,
|
||||
round_request_vw.id, round_request_vw.round_id,
|
||||
round_tx_vw.id, round_tx_vw.tx, round_tx_vw.round_id, round_tx_vw.type, round_tx_vw.position, round_tx_vw.txid, round_tx_vw.tree_level, round_tx_vw.parent_txid, round_tx_vw.is_leaf,
|
||||
payment_receiver_vw.payment_id, payment_receiver_vw.pubkey, payment_receiver_vw.onchain_address, payment_receiver_vw.amount,
|
||||
payment_vtxo_vw.txid, payment_vtxo_vw.vout, payment_vtxo_vw.pubkey, payment_vtxo_vw.amount, payment_vtxo_vw.pool_tx, payment_vtxo_vw.spent_by, payment_vtxo_vw.spent, payment_vtxo_vw.redeemed, payment_vtxo_vw.swept, payment_vtxo_vw.expire_at, payment_vtxo_vw.created_at, payment_vtxo_vw.payment_id, payment_vtxo_vw.redeem_tx
|
||||
request_receiver_vw.request_id, request_receiver_vw.pubkey, request_receiver_vw.onchain_address, request_receiver_vw.amount,
|
||||
request_vtxo_vw.txid, request_vtxo_vw.vout, request_vtxo_vw.pubkey, request_vtxo_vw.amount, request_vtxo_vw.round_tx, request_vtxo_vw.spent_by, request_vtxo_vw.spent, request_vtxo_vw.redeemed, request_vtxo_vw.swept, request_vtxo_vw.expire_at, request_vtxo_vw.created_at, request_vtxo_vw.request_id, request_vtxo_vw.redeem_tx
|
||||
FROM round
|
||||
LEFT OUTER JOIN round_payment_vw ON round.id=round_payment_vw.round_id
|
||||
LEFT OUTER JOIN round_request_vw ON round.id=round_request_vw.round_id
|
||||
LEFT OUTER JOIN round_tx_vw ON round.id=round_tx_vw.round_id
|
||||
LEFT OUTER JOIN payment_receiver_vw ON round_payment_vw.id=payment_receiver_vw.payment_id
|
||||
LEFT OUTER JOIN payment_vtxo_vw ON round_payment_vw.id=payment_vtxo_vw.payment_id
|
||||
LEFT OUTER JOIN request_receiver_vw ON round_request_vw.id=request_receiver_vw.request_id
|
||||
LEFT OUTER JOIN request_vtxo_vw ON round_request_vw.id=request_vtxo_vw.request_id
|
||||
WHERE round.id = ?
|
||||
`
|
||||
|
||||
type SelectRoundWithRoundIdRow struct {
|
||||
Round Round
|
||||
RoundPaymentVw RoundPaymentVw
|
||||
RoundRequestVw RoundRequestVw
|
||||
RoundTxVw RoundTxVw
|
||||
PaymentReceiverVw PaymentReceiverVw
|
||||
PaymentVtxoVw PaymentVtxoVw
|
||||
RequestReceiverVw RequestReceiverVw
|
||||
RequestVtxoVw RequestVtxoVw
|
||||
}
|
||||
|
||||
func (q *Queries) SelectRoundWithRoundId(ctx context.Context, id string) ([]SelectRoundWithRoundIdRow, error) {
|
||||
@@ -385,8 +385,8 @@ func (q *Queries) SelectRoundWithRoundId(ctx context.Context, id string) ([]Sele
|
||||
&i.Round.DustAmount,
|
||||
&i.Round.Version,
|
||||
&i.Round.Swept,
|
||||
&i.RoundPaymentVw.ID,
|
||||
&i.RoundPaymentVw.RoundID,
|
||||
&i.RoundRequestVw.ID,
|
||||
&i.RoundRequestVw.RoundID,
|
||||
&i.RoundTxVw.ID,
|
||||
&i.RoundTxVw.Tx,
|
||||
&i.RoundTxVw.RoundID,
|
||||
@@ -396,23 +396,23 @@ func (q *Queries) SelectRoundWithRoundId(ctx context.Context, id string) ([]Sele
|
||||
&i.RoundTxVw.TreeLevel,
|
||||
&i.RoundTxVw.ParentTxid,
|
||||
&i.RoundTxVw.IsLeaf,
|
||||
&i.PaymentReceiverVw.PaymentID,
|
||||
&i.PaymentReceiverVw.Pubkey,
|
||||
&i.PaymentReceiverVw.OnchainAddress,
|
||||
&i.PaymentReceiverVw.Amount,
|
||||
&i.PaymentVtxoVw.Txid,
|
||||
&i.PaymentVtxoVw.Vout,
|
||||
&i.PaymentVtxoVw.Pubkey,
|
||||
&i.PaymentVtxoVw.Amount,
|
||||
&i.PaymentVtxoVw.PoolTx,
|
||||
&i.PaymentVtxoVw.SpentBy,
|
||||
&i.PaymentVtxoVw.Spent,
|
||||
&i.PaymentVtxoVw.Redeemed,
|
||||
&i.PaymentVtxoVw.Swept,
|
||||
&i.PaymentVtxoVw.ExpireAt,
|
||||
&i.PaymentVtxoVw.CreatedAt,
|
||||
&i.PaymentVtxoVw.PaymentID,
|
||||
&i.PaymentVtxoVw.RedeemTx,
|
||||
&i.RequestReceiverVw.RequestID,
|
||||
&i.RequestReceiverVw.Pubkey,
|
||||
&i.RequestReceiverVw.OnchainAddress,
|
||||
&i.RequestReceiverVw.Amount,
|
||||
&i.RequestVtxoVw.Txid,
|
||||
&i.RequestVtxoVw.Vout,
|
||||
&i.RequestVtxoVw.Pubkey,
|
||||
&i.RequestVtxoVw.Amount,
|
||||
&i.RequestVtxoVw.RoundTx,
|
||||
&i.RequestVtxoVw.SpentBy,
|
||||
&i.RequestVtxoVw.Spent,
|
||||
&i.RequestVtxoVw.Redeemed,
|
||||
&i.RequestVtxoVw.Swept,
|
||||
&i.RequestVtxoVw.ExpireAt,
|
||||
&i.RequestVtxoVw.CreatedAt,
|
||||
&i.RequestVtxoVw.RequestID,
|
||||
&i.RequestVtxoVw.RedeemTx,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -429,24 +429,24 @@ func (q *Queries) SelectRoundWithRoundId(ctx context.Context, id string) ([]Sele
|
||||
|
||||
const selectRoundWithRoundTxId = `-- name: SelectRoundWithRoundTxId :many
|
||||
SELECT round.id, round.starting_timestamp, round.ending_timestamp, round.ended, round.failed, round.stage_code, round.txid, round.unsigned_tx, round.connector_address, round.dust_amount, round.version, round.swept,
|
||||
round_payment_vw.id, round_payment_vw.round_id,
|
||||
round_request_vw.id, round_request_vw.round_id,
|
||||
round_tx_vw.id, round_tx_vw.tx, round_tx_vw.round_id, round_tx_vw.type, round_tx_vw.position, round_tx_vw.txid, round_tx_vw.tree_level, round_tx_vw.parent_txid, round_tx_vw.is_leaf,
|
||||
payment_receiver_vw.payment_id, payment_receiver_vw.pubkey, payment_receiver_vw.onchain_address, payment_receiver_vw.amount,
|
||||
payment_vtxo_vw.txid, payment_vtxo_vw.vout, payment_vtxo_vw.pubkey, payment_vtxo_vw.amount, payment_vtxo_vw.pool_tx, payment_vtxo_vw.spent_by, payment_vtxo_vw.spent, payment_vtxo_vw.redeemed, payment_vtxo_vw.swept, payment_vtxo_vw.expire_at, payment_vtxo_vw.created_at, payment_vtxo_vw.payment_id, payment_vtxo_vw.redeem_tx
|
||||
request_receiver_vw.request_id, request_receiver_vw.pubkey, request_receiver_vw.onchain_address, request_receiver_vw.amount,
|
||||
request_vtxo_vw.txid, request_vtxo_vw.vout, request_vtxo_vw.pubkey, request_vtxo_vw.amount, request_vtxo_vw.round_tx, request_vtxo_vw.spent_by, request_vtxo_vw.spent, request_vtxo_vw.redeemed, request_vtxo_vw.swept, request_vtxo_vw.expire_at, request_vtxo_vw.created_at, request_vtxo_vw.request_id, request_vtxo_vw.redeem_tx
|
||||
FROM round
|
||||
LEFT OUTER JOIN round_payment_vw ON round.id=round_payment_vw.round_id
|
||||
LEFT OUTER JOIN round_request_vw ON round.id=round_request_vw.round_id
|
||||
LEFT OUTER JOIN round_tx_vw ON round.id=round_tx_vw.round_id
|
||||
LEFT OUTER JOIN payment_receiver_vw ON round_payment_vw.id=payment_receiver_vw.payment_id
|
||||
LEFT OUTER JOIN payment_vtxo_vw ON round_payment_vw.id=payment_vtxo_vw.payment_id
|
||||
LEFT OUTER JOIN request_receiver_vw ON round_request_vw.id=request_receiver_vw.request_id
|
||||
LEFT OUTER JOIN request_vtxo_vw ON round_request_vw.id=request_vtxo_vw.request_id
|
||||
WHERE round.txid = ?
|
||||
`
|
||||
|
||||
type SelectRoundWithRoundTxIdRow struct {
|
||||
Round Round
|
||||
RoundPaymentVw RoundPaymentVw
|
||||
RoundRequestVw RoundRequestVw
|
||||
RoundTxVw RoundTxVw
|
||||
PaymentReceiverVw PaymentReceiverVw
|
||||
PaymentVtxoVw PaymentVtxoVw
|
||||
RequestReceiverVw RequestReceiverVw
|
||||
RequestVtxoVw RequestVtxoVw
|
||||
}
|
||||
|
||||
func (q *Queries) SelectRoundWithRoundTxId(ctx context.Context, txid string) ([]SelectRoundWithRoundTxIdRow, error) {
|
||||
@@ -471,8 +471,8 @@ func (q *Queries) SelectRoundWithRoundTxId(ctx context.Context, txid string) ([]
|
||||
&i.Round.DustAmount,
|
||||
&i.Round.Version,
|
||||
&i.Round.Swept,
|
||||
&i.RoundPaymentVw.ID,
|
||||
&i.RoundPaymentVw.RoundID,
|
||||
&i.RoundRequestVw.ID,
|
||||
&i.RoundRequestVw.RoundID,
|
||||
&i.RoundTxVw.ID,
|
||||
&i.RoundTxVw.Tx,
|
||||
&i.RoundTxVw.RoundID,
|
||||
@@ -482,23 +482,23 @@ func (q *Queries) SelectRoundWithRoundTxId(ctx context.Context, txid string) ([]
|
||||
&i.RoundTxVw.TreeLevel,
|
||||
&i.RoundTxVw.ParentTxid,
|
||||
&i.RoundTxVw.IsLeaf,
|
||||
&i.PaymentReceiverVw.PaymentID,
|
||||
&i.PaymentReceiverVw.Pubkey,
|
||||
&i.PaymentReceiverVw.OnchainAddress,
|
||||
&i.PaymentReceiverVw.Amount,
|
||||
&i.PaymentVtxoVw.Txid,
|
||||
&i.PaymentVtxoVw.Vout,
|
||||
&i.PaymentVtxoVw.Pubkey,
|
||||
&i.PaymentVtxoVw.Amount,
|
||||
&i.PaymentVtxoVw.PoolTx,
|
||||
&i.PaymentVtxoVw.SpentBy,
|
||||
&i.PaymentVtxoVw.Spent,
|
||||
&i.PaymentVtxoVw.Redeemed,
|
||||
&i.PaymentVtxoVw.Swept,
|
||||
&i.PaymentVtxoVw.ExpireAt,
|
||||
&i.PaymentVtxoVw.CreatedAt,
|
||||
&i.PaymentVtxoVw.PaymentID,
|
||||
&i.PaymentVtxoVw.RedeemTx,
|
||||
&i.RequestReceiverVw.RequestID,
|
||||
&i.RequestReceiverVw.Pubkey,
|
||||
&i.RequestReceiverVw.OnchainAddress,
|
||||
&i.RequestReceiverVw.Amount,
|
||||
&i.RequestVtxoVw.Txid,
|
||||
&i.RequestVtxoVw.Vout,
|
||||
&i.RequestVtxoVw.Pubkey,
|
||||
&i.RequestVtxoVw.Amount,
|
||||
&i.RequestVtxoVw.RoundTx,
|
||||
&i.RequestVtxoVw.SpentBy,
|
||||
&i.RequestVtxoVw.Spent,
|
||||
&i.RequestVtxoVw.Redeemed,
|
||||
&i.RequestVtxoVw.Swept,
|
||||
&i.RequestVtxoVw.ExpireAt,
|
||||
&i.RequestVtxoVw.CreatedAt,
|
||||
&i.RequestVtxoVw.RequestID,
|
||||
&i.RequestVtxoVw.RedeemTx,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -515,24 +515,24 @@ func (q *Queries) SelectRoundWithRoundTxId(ctx context.Context, txid string) ([]
|
||||
|
||||
const selectSweepableRounds = `-- name: SelectSweepableRounds :many
|
||||
SELECT round.id, round.starting_timestamp, round.ending_timestamp, round.ended, round.failed, round.stage_code, round.txid, round.unsigned_tx, round.connector_address, round.dust_amount, round.version, round.swept,
|
||||
round_payment_vw.id, round_payment_vw.round_id,
|
||||
round_request_vw.id, round_request_vw.round_id,
|
||||
round_tx_vw.id, round_tx_vw.tx, round_tx_vw.round_id, round_tx_vw.type, round_tx_vw.position, round_tx_vw.txid, round_tx_vw.tree_level, round_tx_vw.parent_txid, round_tx_vw.is_leaf,
|
||||
payment_receiver_vw.payment_id, payment_receiver_vw.pubkey, payment_receiver_vw.onchain_address, payment_receiver_vw.amount,
|
||||
payment_vtxo_vw.txid, payment_vtxo_vw.vout, payment_vtxo_vw.pubkey, payment_vtxo_vw.amount, payment_vtxo_vw.pool_tx, payment_vtxo_vw.spent_by, payment_vtxo_vw.spent, payment_vtxo_vw.redeemed, payment_vtxo_vw.swept, payment_vtxo_vw.expire_at, payment_vtxo_vw.created_at, payment_vtxo_vw.payment_id, payment_vtxo_vw.redeem_tx
|
||||
request_receiver_vw.request_id, request_receiver_vw.pubkey, request_receiver_vw.onchain_address, request_receiver_vw.amount,
|
||||
request_vtxo_vw.txid, request_vtxo_vw.vout, request_vtxo_vw.pubkey, request_vtxo_vw.amount, request_vtxo_vw.round_tx, request_vtxo_vw.spent_by, request_vtxo_vw.spent, request_vtxo_vw.redeemed, request_vtxo_vw.swept, request_vtxo_vw.expire_at, request_vtxo_vw.created_at, request_vtxo_vw.request_id, request_vtxo_vw.redeem_tx
|
||||
FROM round
|
||||
LEFT OUTER JOIN round_payment_vw ON round.id=round_payment_vw.round_id
|
||||
LEFT OUTER JOIN round_request_vw ON round.id=round_request_vw.round_id
|
||||
LEFT OUTER JOIN round_tx_vw ON round.id=round_tx_vw.round_id
|
||||
LEFT OUTER JOIN payment_receiver_vw ON round_payment_vw.id=payment_receiver_vw.payment_id
|
||||
LEFT OUTER JOIN payment_vtxo_vw ON round_payment_vw.id=payment_vtxo_vw.payment_id
|
||||
LEFT OUTER JOIN request_receiver_vw ON round_request_vw.id=request_receiver_vw.request_id
|
||||
LEFT OUTER JOIN request_vtxo_vw ON round_request_vw.id=request_vtxo_vw.request_id
|
||||
WHERE round.swept = false AND round.ended = true AND round.failed = false
|
||||
`
|
||||
|
||||
type SelectSweepableRoundsRow struct {
|
||||
Round Round
|
||||
RoundPaymentVw RoundPaymentVw
|
||||
RoundRequestVw RoundRequestVw
|
||||
RoundTxVw RoundTxVw
|
||||
PaymentReceiverVw PaymentReceiverVw
|
||||
PaymentVtxoVw PaymentVtxoVw
|
||||
RequestReceiverVw RequestReceiverVw
|
||||
RequestVtxoVw RequestVtxoVw
|
||||
}
|
||||
|
||||
func (q *Queries) SelectSweepableRounds(ctx context.Context) ([]SelectSweepableRoundsRow, error) {
|
||||
@@ -557,8 +557,8 @@ func (q *Queries) SelectSweepableRounds(ctx context.Context) ([]SelectSweepableR
|
||||
&i.Round.DustAmount,
|
||||
&i.Round.Version,
|
||||
&i.Round.Swept,
|
||||
&i.RoundPaymentVw.ID,
|
||||
&i.RoundPaymentVw.RoundID,
|
||||
&i.RoundRequestVw.ID,
|
||||
&i.RoundRequestVw.RoundID,
|
||||
&i.RoundTxVw.ID,
|
||||
&i.RoundTxVw.Tx,
|
||||
&i.RoundTxVw.RoundID,
|
||||
@@ -568,23 +568,23 @@ func (q *Queries) SelectSweepableRounds(ctx context.Context) ([]SelectSweepableR
|
||||
&i.RoundTxVw.TreeLevel,
|
||||
&i.RoundTxVw.ParentTxid,
|
||||
&i.RoundTxVw.IsLeaf,
|
||||
&i.PaymentReceiverVw.PaymentID,
|
||||
&i.PaymentReceiverVw.Pubkey,
|
||||
&i.PaymentReceiverVw.OnchainAddress,
|
||||
&i.PaymentReceiverVw.Amount,
|
||||
&i.PaymentVtxoVw.Txid,
|
||||
&i.PaymentVtxoVw.Vout,
|
||||
&i.PaymentVtxoVw.Pubkey,
|
||||
&i.PaymentVtxoVw.Amount,
|
||||
&i.PaymentVtxoVw.PoolTx,
|
||||
&i.PaymentVtxoVw.SpentBy,
|
||||
&i.PaymentVtxoVw.Spent,
|
||||
&i.PaymentVtxoVw.Redeemed,
|
||||
&i.PaymentVtxoVw.Swept,
|
||||
&i.PaymentVtxoVw.ExpireAt,
|
||||
&i.PaymentVtxoVw.CreatedAt,
|
||||
&i.PaymentVtxoVw.PaymentID,
|
||||
&i.PaymentVtxoVw.RedeemTx,
|
||||
&i.RequestReceiverVw.RequestID,
|
||||
&i.RequestReceiverVw.Pubkey,
|
||||
&i.RequestReceiverVw.OnchainAddress,
|
||||
&i.RequestReceiverVw.Amount,
|
||||
&i.RequestVtxoVw.Txid,
|
||||
&i.RequestVtxoVw.Vout,
|
||||
&i.RequestVtxoVw.Pubkey,
|
||||
&i.RequestVtxoVw.Amount,
|
||||
&i.RequestVtxoVw.RoundTx,
|
||||
&i.RequestVtxoVw.SpentBy,
|
||||
&i.RequestVtxoVw.Spent,
|
||||
&i.RequestVtxoVw.Redeemed,
|
||||
&i.RequestVtxoVw.Swept,
|
||||
&i.RequestVtxoVw.ExpireAt,
|
||||
&i.RequestVtxoVw.CreatedAt,
|
||||
&i.RequestVtxoVw.RequestID,
|
||||
&i.RequestVtxoVw.RedeemTx,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -600,7 +600,7 @@ func (q *Queries) SelectSweepableRounds(ctx context.Context) ([]SelectSweepableR
|
||||
}
|
||||
|
||||
const selectSweepableVtxos = `-- name: SelectSweepableVtxos :many
|
||||
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.pool_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.created_at, vtxo.payment_id, vtxo.redeem_tx FROM vtxo
|
||||
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.round_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.created_at, vtxo.request_id, vtxo.redeem_tx FROM vtxo
|
||||
WHERE redeemed = false AND swept = false
|
||||
`
|
||||
|
||||
@@ -622,14 +622,14 @@ func (q *Queries) SelectSweepableVtxos(ctx context.Context) ([]SelectSweepableVt
|
||||
&i.Vtxo.Vout,
|
||||
&i.Vtxo.Pubkey,
|
||||
&i.Vtxo.Amount,
|
||||
&i.Vtxo.PoolTx,
|
||||
&i.Vtxo.RoundTx,
|
||||
&i.Vtxo.SpentBy,
|
||||
&i.Vtxo.Spent,
|
||||
&i.Vtxo.Redeemed,
|
||||
&i.Vtxo.Swept,
|
||||
&i.Vtxo.ExpireAt,
|
||||
&i.Vtxo.CreatedAt,
|
||||
&i.Vtxo.PaymentID,
|
||||
&i.Vtxo.RequestID,
|
||||
&i.Vtxo.RedeemTx,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
@@ -647,24 +647,24 @@ func (q *Queries) SelectSweepableVtxos(ctx context.Context) ([]SelectSweepableVt
|
||||
|
||||
const selectSweptRounds = `-- name: SelectSweptRounds :many
|
||||
SELECT round.id, round.starting_timestamp, round.ending_timestamp, round.ended, round.failed, round.stage_code, round.txid, round.unsigned_tx, round.connector_address, round.dust_amount, round.version, round.swept,
|
||||
round_payment_vw.id, round_payment_vw.round_id,
|
||||
round_request_vw.id, round_request_vw.round_id,
|
||||
round_tx_vw.id, round_tx_vw.tx, round_tx_vw.round_id, round_tx_vw.type, round_tx_vw.position, round_tx_vw.txid, round_tx_vw.tree_level, round_tx_vw.parent_txid, round_tx_vw.is_leaf,
|
||||
payment_receiver_vw.payment_id, payment_receiver_vw.pubkey, payment_receiver_vw.onchain_address, payment_receiver_vw.amount,
|
||||
payment_vtxo_vw.txid, payment_vtxo_vw.vout, payment_vtxo_vw.pubkey, payment_vtxo_vw.amount, payment_vtxo_vw.pool_tx, payment_vtxo_vw.spent_by, payment_vtxo_vw.spent, payment_vtxo_vw.redeemed, payment_vtxo_vw.swept, payment_vtxo_vw.expire_at, payment_vtxo_vw.created_at, payment_vtxo_vw.payment_id, payment_vtxo_vw.redeem_tx
|
||||
request_receiver_vw.request_id, request_receiver_vw.pubkey, request_receiver_vw.onchain_address, request_receiver_vw.amount,
|
||||
request_vtxo_vw.txid, request_vtxo_vw.vout, request_vtxo_vw.pubkey, request_vtxo_vw.amount, request_vtxo_vw.round_tx, request_vtxo_vw.spent_by, request_vtxo_vw.spent, request_vtxo_vw.redeemed, request_vtxo_vw.swept, request_vtxo_vw.expire_at, request_vtxo_vw.created_at, request_vtxo_vw.request_id, request_vtxo_vw.redeem_tx
|
||||
FROM round
|
||||
LEFT OUTER JOIN round_payment_vw ON round.id=round_payment_vw.round_id
|
||||
LEFT OUTER JOIN round_request_vw ON round.id=round_request_vw.round_id
|
||||
LEFT OUTER JOIN round_tx_vw ON round.id=round_tx_vw.round_id
|
||||
LEFT OUTER JOIN payment_receiver_vw ON round_payment_vw.id=payment_receiver_vw.payment_id
|
||||
LEFT OUTER JOIN payment_vtxo_vw ON round_payment_vw.id=payment_vtxo_vw.payment_id
|
||||
LEFT OUTER JOIN request_receiver_vw ON round_request_vw.id=request_receiver_vw.request_id
|
||||
LEFT OUTER JOIN request_vtxo_vw ON round_request_vw.id=request_vtxo_vw.request_id
|
||||
WHERE round.swept = true AND round.failed = false AND round.ended = true AND round.connector_address <> ''
|
||||
`
|
||||
|
||||
type SelectSweptRoundsRow struct {
|
||||
Round Round
|
||||
RoundPaymentVw RoundPaymentVw
|
||||
RoundRequestVw RoundRequestVw
|
||||
RoundTxVw RoundTxVw
|
||||
PaymentReceiverVw PaymentReceiverVw
|
||||
PaymentVtxoVw PaymentVtxoVw
|
||||
RequestReceiverVw RequestReceiverVw
|
||||
RequestVtxoVw RequestVtxoVw
|
||||
}
|
||||
|
||||
func (q *Queries) SelectSweptRounds(ctx context.Context) ([]SelectSweptRoundsRow, error) {
|
||||
@@ -689,8 +689,8 @@ func (q *Queries) SelectSweptRounds(ctx context.Context) ([]SelectSweptRoundsRow
|
||||
&i.Round.DustAmount,
|
||||
&i.Round.Version,
|
||||
&i.Round.Swept,
|
||||
&i.RoundPaymentVw.ID,
|
||||
&i.RoundPaymentVw.RoundID,
|
||||
&i.RoundRequestVw.ID,
|
||||
&i.RoundRequestVw.RoundID,
|
||||
&i.RoundTxVw.ID,
|
||||
&i.RoundTxVw.Tx,
|
||||
&i.RoundTxVw.RoundID,
|
||||
@@ -700,23 +700,23 @@ func (q *Queries) SelectSweptRounds(ctx context.Context) ([]SelectSweptRoundsRow
|
||||
&i.RoundTxVw.TreeLevel,
|
||||
&i.RoundTxVw.ParentTxid,
|
||||
&i.RoundTxVw.IsLeaf,
|
||||
&i.PaymentReceiverVw.PaymentID,
|
||||
&i.PaymentReceiverVw.Pubkey,
|
||||
&i.PaymentReceiverVw.OnchainAddress,
|
||||
&i.PaymentReceiverVw.Amount,
|
||||
&i.PaymentVtxoVw.Txid,
|
||||
&i.PaymentVtxoVw.Vout,
|
||||
&i.PaymentVtxoVw.Pubkey,
|
||||
&i.PaymentVtxoVw.Amount,
|
||||
&i.PaymentVtxoVw.PoolTx,
|
||||
&i.PaymentVtxoVw.SpentBy,
|
||||
&i.PaymentVtxoVw.Spent,
|
||||
&i.PaymentVtxoVw.Redeemed,
|
||||
&i.PaymentVtxoVw.Swept,
|
||||
&i.PaymentVtxoVw.ExpireAt,
|
||||
&i.PaymentVtxoVw.CreatedAt,
|
||||
&i.PaymentVtxoVw.PaymentID,
|
||||
&i.PaymentVtxoVw.RedeemTx,
|
||||
&i.RequestReceiverVw.RequestID,
|
||||
&i.RequestReceiverVw.Pubkey,
|
||||
&i.RequestReceiverVw.OnchainAddress,
|
||||
&i.RequestReceiverVw.Amount,
|
||||
&i.RequestVtxoVw.Txid,
|
||||
&i.RequestVtxoVw.Vout,
|
||||
&i.RequestVtxoVw.Pubkey,
|
||||
&i.RequestVtxoVw.Amount,
|
||||
&i.RequestVtxoVw.RoundTx,
|
||||
&i.RequestVtxoVw.SpentBy,
|
||||
&i.RequestVtxoVw.Spent,
|
||||
&i.RequestVtxoVw.Redeemed,
|
||||
&i.RequestVtxoVw.Swept,
|
||||
&i.RequestVtxoVw.ExpireAt,
|
||||
&i.RequestVtxoVw.CreatedAt,
|
||||
&i.RequestVtxoVw.RequestID,
|
||||
&i.RequestVtxoVw.RedeemTx,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -732,7 +732,7 @@ func (q *Queries) SelectSweptRounds(ctx context.Context) ([]SelectSweptRoundsRow
|
||||
}
|
||||
|
||||
const selectVtxoByOutpoint = `-- name: SelectVtxoByOutpoint :one
|
||||
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.pool_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.created_at, vtxo.payment_id, vtxo.redeem_tx FROM vtxo
|
||||
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.round_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.created_at, vtxo.request_id, vtxo.redeem_tx FROM vtxo
|
||||
WHERE txid = ? AND vout = ?
|
||||
`
|
||||
|
||||
@@ -753,50 +753,50 @@ func (q *Queries) SelectVtxoByOutpoint(ctx context.Context, arg SelectVtxoByOutp
|
||||
&i.Vtxo.Vout,
|
||||
&i.Vtxo.Pubkey,
|
||||
&i.Vtxo.Amount,
|
||||
&i.Vtxo.PoolTx,
|
||||
&i.Vtxo.RoundTx,
|
||||
&i.Vtxo.SpentBy,
|
||||
&i.Vtxo.Spent,
|
||||
&i.Vtxo.Redeemed,
|
||||
&i.Vtxo.Swept,
|
||||
&i.Vtxo.ExpireAt,
|
||||
&i.Vtxo.CreatedAt,
|
||||
&i.Vtxo.PaymentID,
|
||||
&i.Vtxo.RequestID,
|
||||
&i.Vtxo.RedeemTx,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const selectVtxosByPoolTxid = `-- name: SelectVtxosByPoolTxid :many
|
||||
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.pool_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.created_at, vtxo.payment_id, vtxo.redeem_tx FROM vtxo
|
||||
WHERE pool_tx = ?
|
||||
const selectVtxosByRoundTxid = `-- name: SelectVtxosByRoundTxid :many
|
||||
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.round_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.created_at, vtxo.request_id, vtxo.redeem_tx FROM vtxo
|
||||
WHERE round_tx = ?
|
||||
`
|
||||
|
||||
type SelectVtxosByPoolTxidRow struct {
|
||||
type SelectVtxosByRoundTxidRow struct {
|
||||
Vtxo Vtxo
|
||||
}
|
||||
|
||||
func (q *Queries) SelectVtxosByPoolTxid(ctx context.Context, poolTx string) ([]SelectVtxosByPoolTxidRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, selectVtxosByPoolTxid, poolTx)
|
||||
func (q *Queries) SelectVtxosByRoundTxid(ctx context.Context, roundTx string) ([]SelectVtxosByRoundTxidRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, selectVtxosByRoundTxid, roundTx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []SelectVtxosByPoolTxidRow
|
||||
var items []SelectVtxosByRoundTxidRow
|
||||
for rows.Next() {
|
||||
var i SelectVtxosByPoolTxidRow
|
||||
var i SelectVtxosByRoundTxidRow
|
||||
if err := rows.Scan(
|
||||
&i.Vtxo.Txid,
|
||||
&i.Vtxo.Vout,
|
||||
&i.Vtxo.Pubkey,
|
||||
&i.Vtxo.Amount,
|
||||
&i.Vtxo.PoolTx,
|
||||
&i.Vtxo.RoundTx,
|
||||
&i.Vtxo.SpentBy,
|
||||
&i.Vtxo.Spent,
|
||||
&i.Vtxo.Redeemed,
|
||||
&i.Vtxo.Swept,
|
||||
&i.Vtxo.ExpireAt,
|
||||
&i.Vtxo.CreatedAt,
|
||||
&i.Vtxo.PaymentID,
|
||||
&i.Vtxo.RequestID,
|
||||
&i.Vtxo.RedeemTx,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
@@ -868,18 +868,18 @@ func (q *Queries) UpdateVtxoExpireAt(ctx context.Context, arg UpdateVtxoExpireAt
|
||||
return err
|
||||
}
|
||||
|
||||
const updateVtxoPaymentId = `-- name: UpdateVtxoPaymentId :exec
|
||||
UPDATE vtxo SET payment_id = ? WHERE txid = ? AND vout = ?
|
||||
const updateVtxoRequestId = `-- name: UpdateVtxoRequestId :exec
|
||||
UPDATE vtxo SET request_id = ? WHERE txid = ? AND vout = ?
|
||||
`
|
||||
|
||||
type UpdateVtxoPaymentIdParams struct {
|
||||
PaymentID sql.NullString
|
||||
type UpdateVtxoRequestIdParams struct {
|
||||
RequestID sql.NullString
|
||||
Txid string
|
||||
Vout int64
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateVtxoPaymentId(ctx context.Context, arg UpdateVtxoPaymentIdParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateVtxoPaymentId, arg.PaymentID, arg.Txid, arg.Vout)
|
||||
func (q *Queries) UpdateVtxoRequestId(ctx context.Context, arg UpdateVtxoRequestIdParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateVtxoRequestId, arg.RequestID, arg.Txid, arg.Vout)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -916,31 +916,16 @@ func (q *Queries) UpsertEntityVtxo(ctx context.Context, arg UpsertEntityVtxoPara
|
||||
return err
|
||||
}
|
||||
|
||||
const upsertPayment = `-- name: UpsertPayment :exec
|
||||
INSERT INTO payment (id, round_id) VALUES (?, ?)
|
||||
ON CONFLICT(id) DO UPDATE SET round_id = EXCLUDED.round_id
|
||||
`
|
||||
|
||||
type UpsertPaymentParams struct {
|
||||
ID string
|
||||
RoundID string
|
||||
}
|
||||
|
||||
func (q *Queries) UpsertPayment(ctx context.Context, arg UpsertPaymentParams) error {
|
||||
_, err := q.db.ExecContext(ctx, upsertPayment, arg.ID, arg.RoundID)
|
||||
return err
|
||||
}
|
||||
|
||||
const upsertReceiver = `-- name: UpsertReceiver :exec
|
||||
INSERT INTO receiver (payment_id, pubkey, onchain_address, amount) VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT(payment_id, pubkey, onchain_address) DO UPDATE SET
|
||||
INSERT INTO receiver (request_id, pubkey, onchain_address, amount) VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT(request_id, pubkey, onchain_address) DO UPDATE SET
|
||||
amount = EXCLUDED.amount,
|
||||
pubkey = EXCLUDED.pubkey,
|
||||
onchain_address = EXCLUDED.onchain_address
|
||||
`
|
||||
|
||||
type UpsertReceiverParams struct {
|
||||
PaymentID string
|
||||
RequestID string
|
||||
Pubkey sql.NullString
|
||||
OnchainAddress sql.NullString
|
||||
Amount int64
|
||||
@@ -948,7 +933,7 @@ type UpsertReceiverParams struct {
|
||||
|
||||
func (q *Queries) UpsertReceiver(ctx context.Context, arg UpsertReceiverParams) error {
|
||||
_, err := q.db.ExecContext(ctx, upsertReceiver,
|
||||
arg.PaymentID,
|
||||
arg.RequestID,
|
||||
arg.Pubkey,
|
||||
arg.OnchainAddress,
|
||||
arg.Amount,
|
||||
@@ -1057,12 +1042,27 @@ func (q *Queries) UpsertTransaction(ctx context.Context, arg UpsertTransactionPa
|
||||
return err
|
||||
}
|
||||
|
||||
const upsertTxRequest = `-- name: UpsertTxRequest :exec
|
||||
INSERT INTO tx_request (id, round_id) VALUES (?, ?)
|
||||
ON CONFLICT(id) DO UPDATE SET round_id = EXCLUDED.round_id
|
||||
`
|
||||
|
||||
type UpsertTxRequestParams struct {
|
||||
ID string
|
||||
RoundID string
|
||||
}
|
||||
|
||||
func (q *Queries) UpsertTxRequest(ctx context.Context, arg UpsertTxRequestParams) error {
|
||||
_, err := q.db.ExecContext(ctx, upsertTxRequest, arg.ID, arg.RoundID)
|
||||
return err
|
||||
}
|
||||
|
||||
const upsertVtxo = `-- name: UpsertVtxo :exec
|
||||
INSERT INTO vtxo (txid, vout, pubkey, amount, pool_tx, spent_by, spent, redeemed, swept, expire_at, created_at, redeem_tx)
|
||||
INSERT INTO vtxo (txid, vout, pubkey, amount, round_tx, spent_by, spent, redeemed, swept, expire_at, created_at, redeem_tx)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(txid, vout) DO UPDATE SET
|
||||
pubkey = EXCLUDED.pubkey,
|
||||
amount = EXCLUDED.amount,
|
||||
pool_tx = EXCLUDED.pool_tx,
|
||||
round_tx = EXCLUDED.round_tx,
|
||||
spent_by = EXCLUDED.spent_by,
|
||||
spent = EXCLUDED.spent,
|
||||
redeemed = EXCLUDED.redeemed,
|
||||
@@ -1077,7 +1077,7 @@ type UpsertVtxoParams struct {
|
||||
Vout int64
|
||||
Pubkey string
|
||||
Amount int64
|
||||
PoolTx string
|
||||
RoundTx string
|
||||
SpentBy string
|
||||
Spent bool
|
||||
Redeemed bool
|
||||
@@ -1093,7 +1093,7 @@ func (q *Queries) UpsertVtxo(ctx context.Context, arg UpsertVtxoParams) error {
|
||||
arg.Vout,
|
||||
arg.Pubkey,
|
||||
arg.Amount,
|
||||
arg.PoolTx,
|
||||
arg.RoundTx,
|
||||
arg.SpentBy,
|
||||
arg.Spent,
|
||||
arg.Redeemed,
|
||||
|
||||
@@ -39,70 +39,70 @@ ON CONFLICT(id) DO UPDATE SET
|
||||
version = EXCLUDED.version,
|
||||
swept = EXCLUDED.swept;
|
||||
|
||||
-- name: UpsertPayment :exec
|
||||
INSERT INTO payment (id, round_id) VALUES (?, ?)
|
||||
-- name: UpsertTxRequest :exec
|
||||
INSERT INTO tx_request (id, round_id) VALUES (?, ?)
|
||||
ON CONFLICT(id) DO UPDATE SET round_id = EXCLUDED.round_id;
|
||||
|
||||
-- name: UpsertReceiver :exec
|
||||
INSERT INTO receiver (payment_id, pubkey, onchain_address, amount) VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT(payment_id, pubkey, onchain_address) DO UPDATE SET
|
||||
INSERT INTO receiver (request_id, pubkey, onchain_address, amount) VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT(request_id, pubkey, onchain_address) DO UPDATE SET
|
||||
amount = EXCLUDED.amount,
|
||||
pubkey = EXCLUDED.pubkey,
|
||||
onchain_address = EXCLUDED.onchain_address;
|
||||
|
||||
-- name: UpdateVtxoPaymentId :exec
|
||||
UPDATE vtxo SET payment_id = ? WHERE txid = ? AND vout = ?;
|
||||
-- name: UpdateVtxoRequestId :exec
|
||||
UPDATE vtxo SET request_id = ? WHERE txid = ? AND vout = ?;
|
||||
|
||||
-- name: SelectRoundWithRoundId :many
|
||||
SELECT sqlc.embed(round),
|
||||
sqlc.embed(round_payment_vw),
|
||||
sqlc.embed(round_request_vw),
|
||||
sqlc.embed(round_tx_vw),
|
||||
sqlc.embed(payment_receiver_vw),
|
||||
sqlc.embed(payment_vtxo_vw)
|
||||
sqlc.embed(request_receiver_vw),
|
||||
sqlc.embed(request_vtxo_vw)
|
||||
FROM round
|
||||
LEFT OUTER JOIN round_payment_vw ON round.id=round_payment_vw.round_id
|
||||
LEFT OUTER JOIN round_request_vw ON round.id=round_request_vw.round_id
|
||||
LEFT OUTER JOIN round_tx_vw ON round.id=round_tx_vw.round_id
|
||||
LEFT OUTER JOIN payment_receiver_vw ON round_payment_vw.id=payment_receiver_vw.payment_id
|
||||
LEFT OUTER JOIN payment_vtxo_vw ON round_payment_vw.id=payment_vtxo_vw.payment_id
|
||||
LEFT OUTER JOIN request_receiver_vw ON round_request_vw.id=request_receiver_vw.request_id
|
||||
LEFT OUTER JOIN request_vtxo_vw ON round_request_vw.id=request_vtxo_vw.request_id
|
||||
WHERE round.id = ?;
|
||||
|
||||
-- name: SelectRoundWithRoundTxId :many
|
||||
SELECT sqlc.embed(round),
|
||||
sqlc.embed(round_payment_vw),
|
||||
sqlc.embed(round_request_vw),
|
||||
sqlc.embed(round_tx_vw),
|
||||
sqlc.embed(payment_receiver_vw),
|
||||
sqlc.embed(payment_vtxo_vw)
|
||||
sqlc.embed(request_receiver_vw),
|
||||
sqlc.embed(request_vtxo_vw)
|
||||
FROM round
|
||||
LEFT OUTER JOIN round_payment_vw ON round.id=round_payment_vw.round_id
|
||||
LEFT OUTER JOIN round_request_vw ON round.id=round_request_vw.round_id
|
||||
LEFT OUTER JOIN round_tx_vw ON round.id=round_tx_vw.round_id
|
||||
LEFT OUTER JOIN payment_receiver_vw ON round_payment_vw.id=payment_receiver_vw.payment_id
|
||||
LEFT OUTER JOIN payment_vtxo_vw ON round_payment_vw.id=payment_vtxo_vw.payment_id
|
||||
LEFT OUTER JOIN request_receiver_vw ON round_request_vw.id=request_receiver_vw.request_id
|
||||
LEFT OUTER JOIN request_vtxo_vw ON round_request_vw.id=request_vtxo_vw.request_id
|
||||
WHERE round.txid = ?;
|
||||
|
||||
-- name: SelectSweepableRounds :many
|
||||
SELECT sqlc.embed(round),
|
||||
sqlc.embed(round_payment_vw),
|
||||
sqlc.embed(round_request_vw),
|
||||
sqlc.embed(round_tx_vw),
|
||||
sqlc.embed(payment_receiver_vw),
|
||||
sqlc.embed(payment_vtxo_vw)
|
||||
sqlc.embed(request_receiver_vw),
|
||||
sqlc.embed(request_vtxo_vw)
|
||||
FROM round
|
||||
LEFT OUTER JOIN round_payment_vw ON round.id=round_payment_vw.round_id
|
||||
LEFT OUTER JOIN round_request_vw ON round.id=round_request_vw.round_id
|
||||
LEFT OUTER JOIN round_tx_vw ON round.id=round_tx_vw.round_id
|
||||
LEFT OUTER JOIN payment_receiver_vw ON round_payment_vw.id=payment_receiver_vw.payment_id
|
||||
LEFT OUTER JOIN payment_vtxo_vw ON round_payment_vw.id=payment_vtxo_vw.payment_id
|
||||
LEFT OUTER JOIN request_receiver_vw ON round_request_vw.id=request_receiver_vw.request_id
|
||||
LEFT OUTER JOIN request_vtxo_vw ON round_request_vw.id=request_vtxo_vw.request_id
|
||||
WHERE round.swept = false AND round.ended = true AND round.failed = false;
|
||||
|
||||
-- name: SelectSweptRounds :many
|
||||
SELECT sqlc.embed(round),
|
||||
sqlc.embed(round_payment_vw),
|
||||
sqlc.embed(round_request_vw),
|
||||
sqlc.embed(round_tx_vw),
|
||||
sqlc.embed(payment_receiver_vw),
|
||||
sqlc.embed(payment_vtxo_vw)
|
||||
sqlc.embed(request_receiver_vw),
|
||||
sqlc.embed(request_vtxo_vw)
|
||||
FROM round
|
||||
LEFT OUTER JOIN round_payment_vw ON round.id=round_payment_vw.round_id
|
||||
LEFT OUTER JOIN round_request_vw ON round.id=round_request_vw.round_id
|
||||
LEFT OUTER JOIN round_tx_vw ON round.id=round_tx_vw.round_id
|
||||
LEFT OUTER JOIN payment_receiver_vw ON round_payment_vw.id=payment_receiver_vw.payment_id
|
||||
LEFT OUTER JOIN payment_vtxo_vw ON round_payment_vw.id=payment_vtxo_vw.payment_id
|
||||
LEFT OUTER JOIN request_receiver_vw ON round_request_vw.id=request_receiver_vw.request_id
|
||||
LEFT OUTER JOIN request_vtxo_vw ON round_request_vw.id=request_vtxo_vw.request_id
|
||||
WHERE round.swept = true AND round.failed = false AND round.ended = true AND round.connector_address <> '';
|
||||
|
||||
-- name: SelectRoundIdsInRange :many
|
||||
@@ -112,11 +112,11 @@ SELECT id FROM round WHERE starting_timestamp > ? AND starting_timestamp < ?;
|
||||
SELECT id FROM round;
|
||||
|
||||
-- name: UpsertVtxo :exec
|
||||
INSERT INTO vtxo (txid, vout, pubkey, amount, pool_tx, spent_by, spent, redeemed, swept, expire_at, created_at, redeem_tx)
|
||||
INSERT INTO vtxo (txid, vout, pubkey, amount, round_tx, spent_by, spent, redeemed, swept, expire_at, created_at, redeem_tx)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(txid, vout) DO UPDATE SET
|
||||
pubkey = EXCLUDED.pubkey,
|
||||
amount = EXCLUDED.amount,
|
||||
pool_tx = EXCLUDED.pool_tx,
|
||||
round_tx = EXCLUDED.round_tx,
|
||||
spent_by = EXCLUDED.spent_by,
|
||||
spent = EXCLUDED.spent,
|
||||
redeemed = EXCLUDED.redeemed,
|
||||
@@ -141,9 +141,9 @@ WHERE redeemed = false AND pubkey = ?;
|
||||
SELECT sqlc.embed(vtxo) FROM vtxo
|
||||
WHERE txid = ? AND vout = ?;
|
||||
|
||||
-- name: SelectVtxosByPoolTxid :many
|
||||
-- name: SelectVtxosByRoundTxid :many
|
||||
SELECT sqlc.embed(vtxo) FROM vtxo
|
||||
WHERE pool_tx = ?;
|
||||
WHERE round_tx = ?;
|
||||
|
||||
-- name: MarkVtxoAsRedeemed :exec
|
||||
UPDATE vtxo SET redeemed = true WHERE txid = ? AND vout = ?;
|
||||
|
||||
@@ -42,9 +42,9 @@ func (v *vxtoRepository) AddVtxos(ctx context.Context, vtxos []domain.Vtxo) erro
|
||||
ctx, queries.UpsertVtxoParams{
|
||||
Txid: vtxo.Txid,
|
||||
Vout: int64(vtxo.VOut),
|
||||
Pubkey: vtxo.Pubkey,
|
||||
Pubkey: vtxo.PubKey,
|
||||
Amount: int64(vtxo.Amount),
|
||||
PoolTx: vtxo.RoundTxid,
|
||||
RoundTx: vtxo.RoundTxid,
|
||||
SpentBy: vtxo.SpentBy,
|
||||
Spent: vtxo.Spent,
|
||||
Redeemed: vtxo.Redeemed,
|
||||
@@ -150,7 +150,7 @@ func (v *vxtoRepository) GetVtxos(ctx context.Context, outpoints []domain.VtxoKe
|
||||
}
|
||||
|
||||
func (v *vxtoRepository) GetVtxosForRound(ctx context.Context, txid string) ([]domain.Vtxo, error) {
|
||||
res, err := v.querier.SelectVtxosByPoolTxid(ctx, txid)
|
||||
res, err := v.querier.SelectVtxosByRoundTxid(ctx, txid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -251,8 +251,8 @@ func rowToVtxo(row queries.Vtxo) domain.Vtxo {
|
||||
VOut: uint32(row.Vout),
|
||||
},
|
||||
Amount: uint64(row.Amount),
|
||||
Pubkey: row.Pubkey,
|
||||
RoundTxid: row.PoolTx,
|
||||
PubKey: row.Pubkey,
|
||||
RoundTxid: row.RoundTx,
|
||||
SpentBy: row.SpentBy,
|
||||
Spent: row.Spent,
|
||||
Redeemed: row.Redeemed,
|
||||
|
||||
@@ -315,41 +315,41 @@ func (b *txBuilder) VerifyForfeitTxs(vtxos []domain.Vtxo, connectors []string, f
|
||||
}
|
||||
|
||||
func (b *txBuilder) BuildRoundTx(
|
||||
aspPubkey *secp256k1.PublicKey,
|
||||
payments []domain.Payment,
|
||||
serverPubkey *secp256k1.PublicKey,
|
||||
requests []domain.TxRequest,
|
||||
boardingInputs []ports.BoardingInput,
|
||||
sweptRounds []domain.Round,
|
||||
_ ...*secp256k1.PublicKey, // cosigners are not used in the covenant
|
||||
) (roundTx string, congestionTree tree.CongestionTree, connectorAddress string, connectors []string, err error) {
|
||||
// The creation of the tree and the pool tx are tightly coupled:
|
||||
) (roundTx string, vtxoTree tree.VtxoTree, connectorAddress string, connectors []string, err error) {
|
||||
// The creation of the tree and the round tx are tightly coupled:
|
||||
// - building the tree requires knowing the shared outpoint (txid:vout)
|
||||
// - building the pool tx requires knowing the shared output script and amount
|
||||
// - building the round tx requires knowing the shared output script and amount
|
||||
// The idea here is to first create all the data for the outputs of the txs
|
||||
// of the congestion tree to calculate the shared output script and amount.
|
||||
// With these data the pool tx can be created, and once the shared utxo
|
||||
// outpoint is obtained, the congestion tree can be finally created.
|
||||
// of the vtxo tree to calculate the shared output script and amount.
|
||||
// With these data the round tx can be created, and once the shared utxo
|
||||
// outpoint is obtained, the vtxo tree can be finally created.
|
||||
// The factory function `treeFactoryFn` returned below holds all outputs data
|
||||
// generated in the process and takes the shared utxo outpoint as argument.
|
||||
// This is safe as the memory allocated for `craftCongestionTree` is freed
|
||||
// only after `BuildPoolTx` returns.
|
||||
// This is safe as the memory allocated for `BuildVtxoTree` is flushed
|
||||
// only after `BuildRoundTx` returns.
|
||||
|
||||
var sharedOutputScript []byte
|
||||
var sharedOutputAmount uint64
|
||||
var treeFactoryFn tree.TreeFactory
|
||||
|
||||
if !isOnchainOnly(payments) {
|
||||
if !isOnchainOnly(requests) {
|
||||
feeSatsPerNode, err := b.wallet.MinRelayFee(context.Background(), uint64(common.CovenantTreeTxSize))
|
||||
if err != nil {
|
||||
return "", nil, "", nil, err
|
||||
}
|
||||
|
||||
vtxosLeaves, err := getOutputVtxosLeaves(payments)
|
||||
vtxosLeaves, err := getOutputVtxosLeaves(requests)
|
||||
if err != nil {
|
||||
return "", nil, "", nil, err
|
||||
}
|
||||
|
||||
treeFactoryFn, sharedOutputScript, sharedOutputAmount, err = tree.CraftCongestionTree(
|
||||
b.onchainNetwork().AssetID, aspPubkey, vtxosLeaves, feeSatsPerNode, b.roundLifetime,
|
||||
treeFactoryFn, sharedOutputScript, sharedOutputAmount, err = tree.BuildVtxoTree(
|
||||
b.onchainNetwork().AssetID, serverPubkey, vtxosLeaves, feeSatsPerNode, b.roundLifetime,
|
||||
)
|
||||
if err != nil {
|
||||
return "", nil, "", nil, err
|
||||
@@ -361,8 +361,8 @@ func (b *txBuilder) BuildRoundTx(
|
||||
return
|
||||
}
|
||||
|
||||
ptx, err := b.createPoolTx(
|
||||
sharedOutputAmount, sharedOutputScript, payments, boardingInputs, aspPubkey, connectorAddress, sweptRounds,
|
||||
ptx, err := b.createRoundTx(
|
||||
sharedOutputAmount, sharedOutputScript, requests, boardingInputs, serverPubkey, connectorAddress, sweptRounds,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -374,7 +374,7 @@ func (b *txBuilder) BuildRoundTx(
|
||||
}
|
||||
|
||||
if treeFactoryFn != nil {
|
||||
congestionTree, err = treeFactoryFn(psetv2.InputArgs{
|
||||
vtxoTree, err = treeFactoryFn(psetv2.InputArgs{
|
||||
Txid: unsignedTx.TxHash().String(),
|
||||
TxIndex: 0,
|
||||
})
|
||||
@@ -388,7 +388,7 @@ func (b *txBuilder) BuildRoundTx(
|
||||
return
|
||||
}
|
||||
|
||||
if countSpentVtxos(payments) <= 0 {
|
||||
if countSpentVtxos(requests) <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -402,7 +402,7 @@ func (b *txBuilder) BuildRoundTx(
|
||||
return "", nil, "", nil, err
|
||||
}
|
||||
|
||||
connectorsPsets, err := b.createConnectors(roundTx, payments, connectorAddress, connectorAmount, connectorFeeAmount)
|
||||
connectorsPsets, err := b.createConnectors(roundTx, requests, connectorAddress, connectorAmount, connectorFeeAmount)
|
||||
if err != nil {
|
||||
return "", nil, "", nil, err
|
||||
}
|
||||
@@ -477,7 +477,7 @@ func (b *txBuilder) verifyTapscriptPartialSigs(pset *psetv2.Pset) (bool, error)
|
||||
utx, _ := pset.UnsignedTx()
|
||||
txid := utx.TxHash().String()
|
||||
|
||||
aspPublicKey, err := b.wallet.GetPubkey(context.Background())
|
||||
serverPubkey, err := b.wallet.GetPubkey(context.Background())
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -511,8 +511,8 @@ func (b *txBuilder) verifyTapscriptPartialSigs(pset *psetv2.Pset) (bool, error)
|
||||
}
|
||||
}
|
||||
|
||||
// we don't need to check if ASP signed
|
||||
keys[hex.EncodeToString(schnorr.SerializePubKey(aspPublicKey))] = true
|
||||
// we don't need to check if server signed
|
||||
keys[hex.EncodeToString(schnorr.SerializePubKey(serverPubkey))] = true
|
||||
|
||||
rootHash := tapLeaf.ControlBlock.RootHash(tapLeaf.Script)
|
||||
tapKeyFromControlBlock := taproot.ComputeTaprootOutputKey(tree.UnspendableKey(), rootHash[:])
|
||||
@@ -629,15 +629,15 @@ func (b *txBuilder) FinalizeAndExtract(tx string) (string, error) {
|
||||
}
|
||||
|
||||
func (b *txBuilder) FindLeaves(
|
||||
congestionTree tree.CongestionTree,
|
||||
vtxoTree tree.VtxoTree,
|
||||
fromtxid string,
|
||||
fromvout uint32,
|
||||
) ([]tree.Node, error) {
|
||||
allLeaves := congestionTree.Leaves()
|
||||
allLeaves := vtxoTree.Leaves()
|
||||
foundLeaves := make([]tree.Node, 0)
|
||||
|
||||
for _, leaf := range allLeaves {
|
||||
branch, err := congestionTree.Branch(leaf.Txid)
|
||||
branch, err := vtxoTree.Branch(leaf.Txid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -669,16 +669,16 @@ func (b *txBuilder) FindLeaves(
|
||||
return foundLeaves, nil
|
||||
}
|
||||
|
||||
func (b *txBuilder) createPoolTx(
|
||||
func (b *txBuilder) createRoundTx(
|
||||
sharedOutputAmount uint64,
|
||||
sharedOutputScript []byte,
|
||||
payments []domain.Payment,
|
||||
requests []domain.TxRequest,
|
||||
boardingInputs []ports.BoardingInput,
|
||||
aspPubKey *secp256k1.PublicKey,
|
||||
serverPubkey *secp256k1.PublicKey,
|
||||
connectorAddress string,
|
||||
sweptRounds []domain.Round,
|
||||
) (*psetv2.Pset, error) {
|
||||
aspScript, err := p2wpkhScript(aspPubKey, b.onchainNetwork())
|
||||
serverScript, err := p2wpkhScript(serverPubkey, b.onchainNetwork())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -698,7 +698,7 @@ func (b *txBuilder) createPoolTx(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nbOfInputs := countSpentVtxos(payments)
|
||||
nbOfInputs := countSpentVtxos(requests)
|
||||
connectorsAmount := (dustAmount + connectorMinRelayFee) * nbOfInputs
|
||||
if nbOfInputs > 1 {
|
||||
connectorsAmount -= connectorMinRelayFee
|
||||
@@ -725,7 +725,7 @@ func (b *txBuilder) createPoolTx(
|
||||
})
|
||||
}
|
||||
|
||||
onchainOutputs, err := getOnchainOutputs(payments, b.onchainNetwork())
|
||||
onchainOutputs, err := getOnchainOutputs(requests, b.onchainNetwork())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -760,7 +760,7 @@ func (b *txBuilder) createPoolTx(
|
||||
outputs = append(outputs, psetv2.OutputArgs{
|
||||
Asset: b.onchainNetwork().AssetID,
|
||||
Amount: change,
|
||||
Script: aspScript,
|
||||
Script: serverScript,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -878,7 +878,7 @@ func (b *txBuilder) createPoolTx(
|
||||
{
|
||||
Asset: b.onchainNetwork().AssetID,
|
||||
Amount: change,
|
||||
Script: aspScript,
|
||||
Script: serverScript,
|
||||
},
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
@@ -904,7 +904,7 @@ func (b *txBuilder) createPoolTx(
|
||||
{
|
||||
Asset: b.onchainNetwork().AssetID,
|
||||
Amount: change,
|
||||
Script: aspScript,
|
||||
Script: serverScript,
|
||||
},
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
@@ -1009,24 +1009,24 @@ func (b *txBuilder) VerifyAndCombinePartialTx(dest string, src string) (string,
|
||||
}
|
||||
|
||||
func (b *txBuilder) createConnectors(
|
||||
roundTx string, payments []domain.Payment,
|
||||
roundTx string, requests []domain.TxRequest,
|
||||
connectorAddress string,
|
||||
connectorAmount, feeAmount uint64,
|
||||
) ([]*psetv2.Pset, error) {
|
||||
txid, _ := getTxid(roundTx)
|
||||
|
||||
aspScript, err := address.ToOutputScript(connectorAddress)
|
||||
serverScript, err := address.ToOutputScript(connectorAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
connectorOutput := psetv2.OutputArgs{
|
||||
Asset: b.onchainNetwork().AssetID,
|
||||
Script: aspScript,
|
||||
Script: serverScript,
|
||||
Amount: connectorAmount,
|
||||
}
|
||||
|
||||
numberOfConnectors := countSpentVtxos(payments)
|
||||
numberOfConnectors := countSpentVtxos(requests)
|
||||
|
||||
previousInput := psetv2.InputArgs{
|
||||
Txid: txid,
|
||||
@@ -1035,7 +1035,7 @@ func (b *txBuilder) createConnectors(
|
||||
|
||||
if numberOfConnectors == 1 {
|
||||
outputs := []psetv2.OutputArgs{connectorOutput}
|
||||
connectorTx, err := craftConnectorTx(previousInput, aspScript, outputs, feeAmount)
|
||||
connectorTx, err := craftConnectorTx(previousInput, serverScript, outputs, feeAmount)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1056,11 +1056,11 @@ func (b *txBuilder) createConnectors(
|
||||
if totalConnectorAmount > 0 {
|
||||
outputs = append(outputs, psetv2.OutputArgs{
|
||||
Asset: b.onchainNetwork().AssetID,
|
||||
Script: aspScript,
|
||||
Script: serverScript,
|
||||
Amount: totalConnectorAmount,
|
||||
})
|
||||
}
|
||||
connectorTx, err := craftConnectorTx(previousInput, aspScript, outputs, feeAmount)
|
||||
connectorTx, err := craftConnectorTx(previousInput, serverScript, outputs, feeAmount)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -53,30 +53,30 @@ func TestMain(m *testing.M) {
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestBuildPoolTx(t *testing.T) {
|
||||
func TestBuildRoundTx(t *testing.T) {
|
||||
builder := txbuilder.NewTxBuilder(
|
||||
wallet, common.Liquid, roundLifetime, boardingExitDelay,
|
||||
)
|
||||
|
||||
fixtures, err := parsePoolTxFixtures()
|
||||
fixtures, err := parseRoundTxFixtures()
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, fixtures)
|
||||
|
||||
if len(fixtures.Valid) > 0 {
|
||||
t.Run("valid", func(t *testing.T) {
|
||||
for _, f := range fixtures.Valid {
|
||||
poolTx, congestionTree, connAddr, _, err := builder.BuildRoundTx(
|
||||
pubkey, f.Payments, []ports.BoardingInput{}, []domain.Round{},
|
||||
roundTx, vtxoTree, connAddr, _, err := builder.BuildRoundTx(
|
||||
pubkey, f.Requests, []ports.BoardingInput{}, []domain.Round{},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, poolTx)
|
||||
require.NotEmpty(t, congestionTree)
|
||||
require.NotEmpty(t, roundTx)
|
||||
require.NotEmpty(t, vtxoTree)
|
||||
require.Equal(t, connectorAddress, connAddr)
|
||||
require.Equal(t, f.ExpectedNumOfNodes, congestionTree.NumberOfNodes())
|
||||
require.Len(t, congestionTree.Leaves(), f.ExpectedNumOfLeaves)
|
||||
require.Equal(t, f.ExpectedNumOfNodes, vtxoTree.NumberOfNodes())
|
||||
require.Len(t, vtxoTree.Leaves(), f.ExpectedNumOfLeaves)
|
||||
|
||||
err = tree.ValidateCongestionTree(
|
||||
congestionTree, poolTx, pubkey, roundLifetime,
|
||||
err = tree.ValidateVtxoTree(
|
||||
vtxoTree, roundTx, pubkey, roundLifetime,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -86,13 +86,13 @@ func TestBuildPoolTx(t *testing.T) {
|
||||
if len(fixtures.Invalid) > 0 {
|
||||
t.Run("invalid", func(t *testing.T) {
|
||||
for _, f := range fixtures.Invalid {
|
||||
poolTx, congestionTree, connAddr, _, err := builder.BuildRoundTx(
|
||||
pubkey, f.Payments, []ports.BoardingInput{}, []domain.Round{},
|
||||
roundTx, vtxoTree, connAddr, _, err := builder.BuildRoundTx(
|
||||
pubkey, f.Requests, []ports.BoardingInput{}, []domain.Round{},
|
||||
)
|
||||
require.EqualError(t, err, f.ExpectedErr)
|
||||
require.Empty(t, poolTx)
|
||||
require.Empty(t, roundTx)
|
||||
require.Empty(t, connAddr)
|
||||
require.Empty(t, congestionTree)
|
||||
require.Empty(t, vtxoTree)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -117,19 +117,19 @@ func randomHex(len int) string {
|
||||
return hex.EncodeToString(buf)
|
||||
}
|
||||
|
||||
type poolTxFixtures struct {
|
||||
type roundTxFixtures struct {
|
||||
Valid []struct {
|
||||
Payments []domain.Payment
|
||||
Requests []domain.TxRequest
|
||||
ExpectedNumOfNodes int
|
||||
ExpectedNumOfLeaves int
|
||||
}
|
||||
Invalid []struct {
|
||||
Payments []domain.Payment
|
||||
Requests []domain.TxRequest
|
||||
ExpectedErr string
|
||||
}
|
||||
}
|
||||
|
||||
func parsePoolTxFixtures() (*poolTxFixtures, error) {
|
||||
func parseRoundTxFixtures() (*roundTxFixtures, error) {
|
||||
file, err := os.ReadFile("testdata/fixtures.json")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -139,9 +139,9 @@ func parsePoolTxFixtures() (*poolTxFixtures, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vv := v["buildPoolTx"].(map[string]interface{})
|
||||
vv := v["buildRoundTx"].(map[string]interface{})
|
||||
file, _ = json.Marshal(vv)
|
||||
var fixtures poolTxFixtures
|
||||
var fixtures roundTxFixtures
|
||||
if err := json.Unmarshal(file, &fixtures); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"buildPoolTx": {
|
||||
"buildRoundTx": {
|
||||
"valid": [
|
||||
{
|
||||
"payments": [
|
||||
"requests": [
|
||||
{
|
||||
"id": "0",
|
||||
"inputs": [
|
||||
@@ -26,7 +26,7 @@
|
||||
"expectedNumOfLeaves": 1
|
||||
},
|
||||
{
|
||||
"payments": [
|
||||
"requests": [
|
||||
{
|
||||
"id": "0",
|
||||
"inputs": [
|
||||
@@ -54,7 +54,7 @@
|
||||
"expectedNumOfLeaves": 2
|
||||
},
|
||||
{
|
||||
"payments": [
|
||||
"requests": [
|
||||
{
|
||||
"id": "0",
|
||||
"inputs": [
|
||||
@@ -126,7 +126,7 @@
|
||||
"expectedNumOfLeaves": 6
|
||||
},
|
||||
{
|
||||
"payments": [
|
||||
"requests": [
|
||||
{
|
||||
"id": "a242cdd8-f3d5-46c0-ae98-94135a2bee3f",
|
||||
"inputs": [
|
||||
@@ -199,7 +199,7 @@
|
||||
"buildForfeitTxs": {
|
||||
"valid": [
|
||||
{
|
||||
"payments": [
|
||||
"requests": [
|
||||
{
|
||||
"id": "0",
|
||||
"inputs": [
|
||||
@@ -230,8 +230,8 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"poolTx": "cHNldP8BAgQCAAAAAQQBAQEFAQMBBgEDAfsEAgAAAAABDiDk7dXxh4KQzgLO8i1ABtaLCe4aPL12GVhN1E9zM1ePLwEPBAAAAAABEAT/////AAEDCOgDAAAAAAAAAQQWABSNnpy01UJqd99eTg2M1IpdKId11gf8BHBzZXQCICWyUQcOKcoZBDzzPM1zJOLdqwPsxK4LXnfE/A5c9slaB/wEcHNldAgEAAAAAAABAwh4BQAAAAAAAAEEFgAUjZ6ctNVCanffXk4NjNSKXSiHddYH/ARwc2V0AiAlslEHDinKGQQ88zzNcyTi3asD7MSuC153xPwOXPbJWgf8BHBzZXQIBAAAAAAAAQMI9AEAAAAAAAABBAAH/ARwc2V0AiAlslEHDinKGQQ88zzNcyTi3asD7MSuC153xPwOXPbJWgf8BHBzZXQIBAAAAAAA",
|
||||
"poolTxid": "7981fce656f266472cc742444527cb32a8bed8c90fed6d47adbfc4c8780d4d9a",
|
||||
"roundTx": "cHNldP8BAgQCAAAAAQQBAQEFAQMBBgEDAfsEAgAAAAABDiDk7dXxh4KQzgLO8i1ABtaLCe4aPL12GVhN1E9zM1ePLwEPBAAAAAABEAT/////AAEDCOgDAAAAAAAAAQQWABSNnpy01UJqd99eTg2M1IpdKId11gf8BHBzZXQCICWyUQcOKcoZBDzzPM1zJOLdqwPsxK4LXnfE/A5c9slaB/wEcHNldAgEAAAAAAABAwh4BQAAAAAAAAEEFgAUjZ6ctNVCanffXk4NjNSKXSiHddYH/ARwc2V0AiAlslEHDinKGQQ88zzNcyTi3asD7MSuC153xPwOXPbJWgf8BHBzZXQIBAAAAAAAAQMI9AEAAAAAAAABBAAH/ARwc2V0AiAlslEHDinKGQQ88zzNcyTi3asD7MSuC153xPwOXPbJWgf8BHBzZXQIBAAAAAAA",
|
||||
"roundTxid": "7981fce656f266472cc742444527cb32a8bed8c90fed6d47adbfc4c8780d4d9a",
|
||||
"expectedNumOfForfeitTxs": 4,
|
||||
"expectedNumOfConnectors": 1
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ import (
|
||||
"github.com/vulpemventures/go-elements/transaction"
|
||||
)
|
||||
|
||||
func p2wpkhScript(publicKey *secp256k1.PublicKey, net *network.Network) ([]byte, error) {
|
||||
payment := payment.FromPublicKey(publicKey, net, nil)
|
||||
func p2wpkhScript(pubkey *secp256k1.PublicKey, net *network.Network) ([]byte, error) {
|
||||
payment := payment.FromPublicKey(pubkey, net, nil)
|
||||
addr, err := payment.WitnessPubKeyHash()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -46,11 +46,11 @@ func getPsetId(pset *psetv2.Pset) (string, error) {
|
||||
}
|
||||
|
||||
func getOnchainOutputs(
|
||||
payments []domain.Payment, net *network.Network,
|
||||
requests []domain.TxRequest, net *network.Network,
|
||||
) ([]psetv2.OutputArgs, error) {
|
||||
outputs := make([]psetv2.OutputArgs, 0)
|
||||
for _, payment := range payments {
|
||||
for _, receiver := range payment.Receivers {
|
||||
for _, request := range requests {
|
||||
for _, receiver := range request.Receivers {
|
||||
if receiver.IsOnchain() {
|
||||
receiverScript, err := address.ToOutputScript(receiver.OnchainAddress)
|
||||
if err != nil {
|
||||
@@ -69,14 +69,14 @@ func getOnchainOutputs(
|
||||
}
|
||||
|
||||
func getOutputVtxosLeaves(
|
||||
payments []domain.Payment,
|
||||
requests []domain.TxRequest,
|
||||
) ([]tree.VtxoLeaf, error) {
|
||||
receivers := make([]tree.VtxoLeaf, 0)
|
||||
for _, payment := range payments {
|
||||
for _, receiver := range payment.Receivers {
|
||||
for _, request := range requests {
|
||||
for _, receiver := range request.Receivers {
|
||||
if !receiver.IsOnchain() {
|
||||
receivers = append(receivers, tree.VtxoLeaf{
|
||||
Pubkey: receiver.Pubkey,
|
||||
PubKey: receiver.PubKey,
|
||||
Amount: receiver.Amount,
|
||||
})
|
||||
}
|
||||
@@ -104,10 +104,10 @@ func toWitnessUtxo(in ports.TxInput) (*transaction.TxOutput, error) {
|
||||
return transaction.NewTxOutput(assetBytes, valueBytes, scriptBytes), nil
|
||||
}
|
||||
|
||||
func countSpentVtxos(payments []domain.Payment) uint64 {
|
||||
func countSpentVtxos(requests []domain.TxRequest) uint64 {
|
||||
var sum uint64
|
||||
for _, payment := range payments {
|
||||
sum += uint64(len(payment.Inputs))
|
||||
for _, request := range requests {
|
||||
sum += uint64(len(request.Inputs))
|
||||
}
|
||||
return sum
|
||||
}
|
||||
@@ -144,9 +144,9 @@ func addInputs(
|
||||
return nil
|
||||
}
|
||||
|
||||
func isOnchainOnly(payments []domain.Payment) bool {
|
||||
for _, p := range payments {
|
||||
for _, r := range p.Receivers {
|
||||
func isOnchainOnly(requests []domain.TxRequest) bool {
|
||||
for _, request := range requests {
|
||||
for _, r := range request.Receivers {
|
||||
if !r.IsOnchain() {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ func (b *txBuilder) VerifyTapscriptPartialSigs(tx string) (bool, error) {
|
||||
func (b *txBuilder) verifyTapscriptPartialSigs(ptx *psbt.Packet) (bool, error) {
|
||||
txid := ptx.UnsignedTx.TxID()
|
||||
|
||||
aspPublicKey, err := b.wallet.GetPubkey(context.Background())
|
||||
serverPubkey, err := b.wallet.GetPubkey(context.Background())
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -93,8 +93,8 @@ func (b *txBuilder) verifyTapscriptPartialSigs(ptx *psbt.Packet) (bool, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// we don't need to check if ASP signed
|
||||
keys[hex.EncodeToString(schnorr.SerializePubKey(aspPublicKey))] = true
|
||||
// we don't need to check if server signed
|
||||
keys[hex.EncodeToString(schnorr.SerializePubKey(serverPubkey))] = true
|
||||
|
||||
if len(tapLeaf.ControlBlock) == 0 {
|
||||
return false, fmt.Errorf("missing control block for input %d", index)
|
||||
@@ -471,12 +471,12 @@ func (b *txBuilder) VerifyForfeitTxs(vtxos []domain.Vtxo, connectors []string, f
|
||||
}
|
||||
|
||||
func (b *txBuilder) BuildRoundTx(
|
||||
aspPubkey *secp256k1.PublicKey,
|
||||
payments []domain.Payment,
|
||||
serverPubkey *secp256k1.PublicKey,
|
||||
requests []domain.TxRequest,
|
||||
boardingInputs []ports.BoardingInput,
|
||||
sweptRounds []domain.Round,
|
||||
cosigners ...*secp256k1.PublicKey,
|
||||
) (roundTx string, congestionTree tree.CongestionTree, connectorAddress string, connectors []string, err error) {
|
||||
) (roundTx string, vtxoTree tree.VtxoTree, connectorAddress string, connectors []string, err error) {
|
||||
var sharedOutputScript []byte
|
||||
var sharedOutputAmount int64
|
||||
|
||||
@@ -484,7 +484,7 @@ func (b *txBuilder) BuildRoundTx(
|
||||
return "", nil, "", nil, fmt.Errorf("missing cosigners")
|
||||
}
|
||||
|
||||
receivers, err := getOutputVtxosLeaves(payments)
|
||||
receivers, err := getOutputVtxosLeaves(requests)
|
||||
if err != nil {
|
||||
return "", nil, "", nil, err
|
||||
}
|
||||
@@ -494,9 +494,9 @@ func (b *txBuilder) BuildRoundTx(
|
||||
return
|
||||
}
|
||||
|
||||
if !isOnchainOnly(payments) {
|
||||
if !isOnchainOnly(requests) {
|
||||
sharedOutputScript, sharedOutputAmount, err = bitcointree.CraftSharedOutput(
|
||||
cosigners, aspPubkey, receivers, feeAmount, b.roundLifetime,
|
||||
cosigners, serverPubkey, receivers, feeAmount, b.roundLifetime,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -509,7 +509,7 @@ func (b *txBuilder) BuildRoundTx(
|
||||
}
|
||||
|
||||
ptx, err := b.createRoundTx(
|
||||
sharedOutputAmount, sharedOutputScript, payments, boardingInputs, connectorAddress, sweptRounds,
|
||||
sharedOutputAmount, sharedOutputScript, requests, boardingInputs, connectorAddress, sweptRounds,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -520,21 +520,21 @@ func (b *txBuilder) BuildRoundTx(
|
||||
return
|
||||
}
|
||||
|
||||
if !isOnchainOnly(payments) {
|
||||
if !isOnchainOnly(requests) {
|
||||
initialOutpoint := &wire.OutPoint{
|
||||
Hash: ptx.UnsignedTx.TxHash(),
|
||||
Index: 0,
|
||||
}
|
||||
|
||||
congestionTree, err = bitcointree.CraftCongestionTree(
|
||||
initialOutpoint, cosigners, aspPubkey, receivers, feeAmount, b.roundLifetime,
|
||||
vtxoTree, err = bitcointree.BuildVtxoTree(
|
||||
initialOutpoint, cosigners, serverPubkey, receivers, feeAmount, b.roundLifetime,
|
||||
)
|
||||
if err != nil {
|
||||
return "", nil, "", nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if countSpentVtxos(payments) <= 0 {
|
||||
if countSpentVtxos(requests) <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -553,7 +553,7 @@ func (b *txBuilder) BuildRoundTx(
|
||||
return "", nil, "", nil, err
|
||||
}
|
||||
|
||||
connectorsPsbts, err := b.createConnectors(roundTx, payments, connectorPkScript, minRelayFeeConnectorTx)
|
||||
connectorsPsbts, err := b.createConnectors(roundTx, requests, connectorPkScript, minRelayFeeConnectorTx)
|
||||
if err != nil {
|
||||
return "", nil, "", nil, err
|
||||
}
|
||||
@@ -566,7 +566,7 @@ func (b *txBuilder) BuildRoundTx(
|
||||
connectors = append(connectors, b64)
|
||||
}
|
||||
|
||||
return roundTx, congestionTree, connectorAddress, connectors, nil
|
||||
return roundTx, vtxoTree, connectorAddress, connectors, nil
|
||||
}
|
||||
|
||||
func (b *txBuilder) GetSweepInput(node tree.Node) (lifetime int64, sweepInput ports.SweepInput, err error) {
|
||||
@@ -611,12 +611,12 @@ func (b *txBuilder) GetSweepInput(node tree.Node) (lifetime int64, sweepInput po
|
||||
return lifetime, sweepInput, nil
|
||||
}
|
||||
|
||||
func (b *txBuilder) FindLeaves(congestionTree tree.CongestionTree, fromtxid string, vout uint32) ([]tree.Node, error) {
|
||||
allLeaves := congestionTree.Leaves()
|
||||
func (b *txBuilder) FindLeaves(vtxoTree tree.VtxoTree, fromtxid string, vout uint32) ([]tree.Node, error) {
|
||||
allLeaves := vtxoTree.Leaves()
|
||||
foundLeaves := make([]tree.Node, 0)
|
||||
|
||||
for _, leaf := range allLeaves {
|
||||
branch, err := congestionTree.Branch(leaf.Txid)
|
||||
branch, err := vtxoTree.Branch(leaf.Txid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -647,7 +647,7 @@ func (b *txBuilder) FindLeaves(congestionTree tree.CongestionTree, fromtxid stri
|
||||
func (b *txBuilder) createRoundTx(
|
||||
sharedOutputAmount int64,
|
||||
sharedOutputScript []byte,
|
||||
payments []domain.Payment,
|
||||
requests []domain.TxRequest,
|
||||
boardingInputs []ports.BoardingInput,
|
||||
connectorAddress string,
|
||||
sweptRounds []domain.Round,
|
||||
@@ -674,7 +674,7 @@ func (b *txBuilder) createRoundTx(
|
||||
|
||||
connectorAmount := dustLimit
|
||||
|
||||
nbOfInputs := countSpentVtxos(payments)
|
||||
nbOfInputs := countSpentVtxos(requests)
|
||||
connectorsAmount := (connectorAmount + connectorMinRelayFee) * nbOfInputs
|
||||
if nbOfInputs > 1 {
|
||||
connectorsAmount -= connectorMinRelayFee
|
||||
@@ -699,7 +699,7 @@ func (b *txBuilder) createRoundTx(
|
||||
})
|
||||
}
|
||||
|
||||
onchainOutputs, err := getOnchainOutputs(payments, b.onchainNetwork())
|
||||
onchainOutputs, err := getOnchainOutputs(requests, b.onchainNetwork())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1021,9 +1021,9 @@ func (b *txBuilder) VerifyAndCombinePartialTx(dest string, src string) (string,
|
||||
}
|
||||
|
||||
func (b *txBuilder) createConnectors(
|
||||
poolTx string, payments []domain.Payment, connectorScript []byte, feeAmount uint64,
|
||||
roundTx string, requests []domain.TxRequest, connectorScript []byte, feeAmount uint64,
|
||||
) ([]*psbt.Packet, error) {
|
||||
partialTx, err := psbt.NewFromRawBytes(strings.NewReader(poolTx), true)
|
||||
partialTx, err := psbt.NewFromRawBytes(strings.NewReader(roundTx), true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1038,7 +1038,7 @@ func (b *txBuilder) createConnectors(
|
||||
Value: int64(connectorAmount),
|
||||
}
|
||||
|
||||
numberOfConnectors := countSpentVtxos(payments)
|
||||
numberOfConnectors := countSpentVtxos(requests)
|
||||
|
||||
previousInput := &wire.OutPoint{
|
||||
Hash: partialTx.UnsignedTx.TxHash(),
|
||||
|
||||
@@ -55,12 +55,12 @@ func TestMain(m *testing.M) {
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestBuildPoolTx(t *testing.T) {
|
||||
func TestBuildRoundTx(t *testing.T) {
|
||||
builder := txbuilder.NewTxBuilder(
|
||||
wallet, common.Bitcoin, roundLifetime, boardingExitDelay,
|
||||
)
|
||||
|
||||
fixtures, err := parsePoolTxFixtures()
|
||||
fixtures, err := parseRoundTxFixtures()
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, fixtures)
|
||||
|
||||
@@ -68,25 +68,25 @@ func TestBuildPoolTx(t *testing.T) {
|
||||
t.Run("valid", func(t *testing.T) {
|
||||
for _, f := range fixtures.Valid {
|
||||
cosigners := make([]*secp256k1.PublicKey, 0)
|
||||
for range f.Payments {
|
||||
for range f.Requests {
|
||||
randKey, err := secp256k1.GeneratePrivateKey()
|
||||
require.NoError(t, err)
|
||||
|
||||
cosigners = append(cosigners, randKey.PubKey())
|
||||
}
|
||||
|
||||
poolTx, congestionTree, connAddr, _, err := builder.BuildRoundTx(
|
||||
pubkey, f.Payments, []ports.BoardingInput{}, []domain.Round{}, cosigners...,
|
||||
roundTx, vtxoTree, connAddr, _, err := builder.BuildRoundTx(
|
||||
pubkey, f.Requests, []ports.BoardingInput{}, []domain.Round{}, cosigners...,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, poolTx)
|
||||
require.NotEmpty(t, congestionTree)
|
||||
require.NotEmpty(t, roundTx)
|
||||
require.NotEmpty(t, vtxoTree)
|
||||
require.Equal(t, connectorAddress, connAddr)
|
||||
require.Equal(t, f.ExpectedNumOfNodes, congestionTree.NumberOfNodes())
|
||||
require.Len(t, congestionTree.Leaves(), f.ExpectedNumOfLeaves)
|
||||
require.Equal(t, f.ExpectedNumOfNodes, vtxoTree.NumberOfNodes())
|
||||
require.Len(t, vtxoTree.Leaves(), f.ExpectedNumOfLeaves)
|
||||
|
||||
err = bitcointree.ValidateCongestionTree(
|
||||
congestionTree, poolTx, pubkey, roundLifetime,
|
||||
err = bitcointree.ValidateVtxoTree(
|
||||
vtxoTree, roundTx, pubkey, roundLifetime,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -96,13 +96,13 @@ func TestBuildPoolTx(t *testing.T) {
|
||||
if len(fixtures.Invalid) > 0 {
|
||||
t.Run("invalid", func(t *testing.T) {
|
||||
for _, f := range fixtures.Invalid {
|
||||
poolTx, congestionTree, connAddr, _, err := builder.BuildRoundTx(
|
||||
pubkey, f.Payments, []ports.BoardingInput{}, []domain.Round{},
|
||||
roundTx, vtxoTree, connAddr, _, err := builder.BuildRoundTx(
|
||||
pubkey, f.Requests, []ports.BoardingInput{}, []domain.Round{},
|
||||
)
|
||||
require.EqualError(t, err, f.ExpectedErr)
|
||||
require.Empty(t, poolTx)
|
||||
require.Empty(t, roundTx)
|
||||
require.Empty(t, connAddr)
|
||||
require.Empty(t, congestionTree)
|
||||
require.Empty(t, vtxoTree)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -127,19 +127,19 @@ func randomHex(len int) string {
|
||||
return hex.EncodeToString(buf)
|
||||
}
|
||||
|
||||
type poolTxFixtures struct {
|
||||
type roundTxFixtures struct {
|
||||
Valid []struct {
|
||||
Payments []domain.Payment
|
||||
Requests []domain.TxRequest
|
||||
ExpectedNumOfNodes int
|
||||
ExpectedNumOfLeaves int
|
||||
}
|
||||
Invalid []struct {
|
||||
Payments []domain.Payment
|
||||
Requests []domain.TxRequest
|
||||
ExpectedErr string
|
||||
}
|
||||
}
|
||||
|
||||
func parsePoolTxFixtures() (*poolTxFixtures, error) {
|
||||
func parseRoundTxFixtures() (*roundTxFixtures, error) {
|
||||
file, err := os.ReadFile("testdata/fixtures.json")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -149,9 +149,9 @@ func parsePoolTxFixtures() (*poolTxFixtures, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vv := v["buildPoolTx"].(map[string]interface{})
|
||||
vv := v["buildRoundTx"].(map[string]interface{})
|
||||
file, _ = json.Marshal(vv)
|
||||
var fixtures poolTxFixtures
|
||||
var fixtures roundTxFixtures
|
||||
if err := json.Unmarshal(file, &fixtures); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"buildPoolTx": {
|
||||
"buildRoundTx": {
|
||||
"valid": [
|
||||
{
|
||||
"payments": [
|
||||
"requests": [
|
||||
{
|
||||
"id": "0",
|
||||
"inputs": [
|
||||
@@ -26,7 +26,7 @@
|
||||
"expectedNumOfLeaves": 1
|
||||
},
|
||||
{
|
||||
"payments": [
|
||||
"requests": [
|
||||
{
|
||||
"id": "0",
|
||||
"inputs": [
|
||||
@@ -54,7 +54,7 @@
|
||||
"expectedNumOfLeaves": 2
|
||||
},
|
||||
{
|
||||
"payments": [
|
||||
"requests": [
|
||||
{
|
||||
"id": "0",
|
||||
"inputs": [
|
||||
@@ -126,7 +126,7 @@
|
||||
"expectedNumOfLeaves": 6
|
||||
},
|
||||
{
|
||||
"payments": [
|
||||
"requests": [
|
||||
{
|
||||
"id": "a242cdd8-f3d5-46c0-ae98-94135a2bee3f",
|
||||
"inputs": [
|
||||
@@ -199,7 +199,7 @@
|
||||
"buildForfeitTxs": {
|
||||
"valid": [
|
||||
{
|
||||
"payments": [
|
||||
"requests": [
|
||||
{
|
||||
"id": "a242cdd8-f3d5-46c0-ae98-94135a2bee3f",
|
||||
"inputs": [
|
||||
@@ -263,8 +263,8 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"poolTx": "cHNidP8BALICAAAAAnonOnsJBkHUUaKf/7fdS0/sVyBCgDPusYzGSZZiXPbtAAAAAAD/////VLtr81ZII3QJnXgrIwgcnbsq3aa4L3qdHOAn2evlFtEAAAAAAP////8CohIAAAAAAAAiUSBZarBUuSIHnlkuIoel9MmvexqTGK8jCZaRjt8L+Pb3s+gDAAAAAAAAIlEgI95L4kHEn2fAA+vysD+RIR4eD3AIQwc+FyCInJ8HivYAAAAAAAEBIOgDAAAAAAAAF6kU6p9IboLvs92Dpp/Zbj8BE3V9oDyHAAEBIOgDAAAAAAAAF6kU6p9IboLvs92Dpp/Zbj8BE3V9oDyHAAAA",
|
||||
"poolTxid": "7c0c10756cdb9ab8e605f1c82e25989761308cf4c60e6a6f42b72d46144c4ce0",
|
||||
"roundTx": "cHNidP8BALICAAAAAnonOnsJBkHUUaKf/7fdS0/sVyBCgDPusYzGSZZiXPbtAAAAAAD/////VLtr81ZII3QJnXgrIwgcnbsq3aa4L3qdHOAn2evlFtEAAAAAAP////8CohIAAAAAAAAiUSBZarBUuSIHnlkuIoel9MmvexqTGK8jCZaRjt8L+Pb3s+gDAAAAAAAAIlEgI95L4kHEn2fAA+vysD+RIR4eD3AIQwc+FyCInJ8HivYAAAAAAAEBIOgDAAAAAAAAF6kU6p9IboLvs92Dpp/Zbj8BE3V9oDyHAAEBIOgDAAAAAAAAF6kU6p9IboLvs92Dpp/Zbj8BE3V9oDyHAAAA",
|
||||
"roundTxid": "7c0c10756cdb9ab8e605f1c82e25989761308cf4c60e6a6f42b72d46144c4ce0",
|
||||
"expectedNumOfForfeitTxs": 25,
|
||||
"expectedNumOfConnectors": 4
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user