3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-13 10:45:51 +00:00
altcoinj/core/src/paymentchannel.proto
Martin Zachrison 63b4b179e0 Payment channel API. Negotiation af the channel duration.
1. Client requests a time window, in seconds relative to now.
2. Server suggests an expire time, absolute time in seconds
3. Client accepts or rejects the servers proposal.
Note that the IPaymentChannelClient.ClinentConnection interface has a new method. This will break old implementations.
Let the client request the duration of a payment channel. Server can set allowed time window.
2014-09-09 13:29:22 +02:00

260 lines
14 KiB
Protocol Buffer

/** Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Authors: Mike Hearn, Matt Corallo
*/
/* Notes:
* - Endianness: All byte arrays that represent numbers (such as hashes and private keys) are Big Endian
* - To regenerate after editing, run mvn clean package -DupdateProtobuf
*/
package paymentchannels;
option java_package = "org.bitcoin.paymentchannel";
option java_outer_classname = "Protos";
// This message is designed to be either sent raw over the network (e.g. length prefixed) or embedded inside another
// protocol that is being extended to support micropayments. In this file "primary" typically can be read as "client"
// and "secondary" as "server".
message TwoWayChannelMessage {
enum MessageType {
CLIENT_VERSION = 1;
SERVER_VERSION = 2;
INITIATE = 3;
PROVIDE_REFUND = 4;
RETURN_REFUND = 5;
PROVIDE_CONTRACT = 6;
// Note that there are no optional fields set for CHANNEL_OPEN, it is sent from the
// secondary to the primary to indicate that the provided contract was received,
// verified, and broadcast successfully and the primary can now provide UPDATE messages
// at will to begin paying secondary. If the channel is interrupted after the
// CHANNEL_OPEN message (ie closed without an explicit CLOSE or ERROR) the primary may
// reopen the channel by setting the contract transaction hash in its CLIENT_VERSION
// message.
CHANNEL_OPEN = 7;
UPDATE_PAYMENT = 8;
// Sent by the server to the client after an UPDATE_PAYMENT message is successfully processed.
PAYMENT_ACK = 11;
// Either side can send this message. If the client sends it to the server, then the server
// takes the most recent signature it received in an UPDATE_PAYMENT and uses it to create a
// valid transaction, which it then broadcasts on the network.
//
// Once broadcast is complete, it sends back another CLOSE message with the settlement field set, containing
// the final state of the contract.
//
// The server is allowed to initiate settlement whenever it wants, in which case the client will
// asynchronously receive a CLOSE message with the settlement field set. The server is also allowed
// to send a CLOSE to mark the end of a connection without any settlement taking place, in which
// case this is just an equivalent to a TCP FIN packet. An explicit end-of-protocol markers can be
// useful when this protocol is embedded inside another.
CLOSE = 9;
// Used to indicate an error condition.
// Both parties should make an effort to send either an ERROR or a CLOSE immediately
// before closing the socket (unless they just received an ERROR or a CLOSE). This is important
// because the protocol may not run over TCP.
ERROR = 10;
};
// This is required so if a new message type is added in future, old software aborts trying
// to read the message as early as possible. If the message doesn't parse, the socket should
// be closed.
required MessageType type = 1;
// Now one optional field for each message. Only the field specified by type should be read.
optional ClientVersion client_version = 2;
optional ServerVersion server_version = 3;
optional Initiate initiate = 4;
optional ProvideRefund provide_refund = 5;
optional ReturnRefund return_refund = 6;
optional ProvideContract provide_contract = 7;
optional UpdatePayment update_payment = 8;
optional PaymentAck payment_ack = 11;
optional Settlement settlement = 9;
optional Error error = 10;
}
// Sent by primary to secondary on opening the connection. If anything is received before this is
// sent, the socket is closed.
message ClientVersion {
required int32 major = 1;
optional int32 minor = 2 [default = 0];
// The hash of the multisig contract of a previous channel. This indicates that the primary
// wishes to reopen the given channel. If the server is willing to reopen it, it simply
// responds with a SERVER_VERSION and then immediately sends a CHANNEL_OPEN, it otherwise
// follows SERVER_VERSION with an Initiate representing a new channel
optional bytes previous_channel_contract_hash = 3;
// How many seconds should the channel be open, only used when a new channel is created.
// Defaults to 24 h minus 60 seconds, 24*60*60 - 60
optional uint64 time_window_secs = 4 [default = 86340];
}
// Send by secondary to primary upon receiving the ClientVersion message. If it is willing to
// speak the given major version, it sends back the same major version and the minor version it
// speaks. If it is not, it may send back a lower major version representing the highest version
// it is willing to speak, or sends a NO_ACCEPTABLE_VERSION Error. If the secondary sends back a
// lower major version, the secondary should either expect to continue with that version, or
// should immediately close the connection with a NO_ACCEPTABLE_VERSION Error. Backwards
// incompatible changes to the protocol bump the major version. Extensions bump the minor version
message ServerVersion {
required int32 major = 1;
optional int32 minor = 2 [default = 0];
}
// Sent from server to client once version nego is done.
message Initiate {
// This must be a raw pubkey in regular ECDSA form. Both compressed and non-compressed forms
// are accepted. It is used only in the creation of the multisig contract, as outputs are
// created entirely by the secondary
required bytes multisig_key = 1;
// Once a channel is exhausted a new one must be set up. So secondary indicates the minimum
// size it's willing to accept here. This can be lower to trade off resources against
// security but shouldn't be so low the transactions get rejected by the network as spam.
// Zero isn't a sensible value to have here, so we make the field required.
required uint64 min_accepted_channel_size = 2;
// Rough UNIX time for when the channel expires. This is determined by the block header
// timestamps which can be very inaccurate when miners use the obsolete RollNTime hack.
// Channels could also be specified in terms of block heights but then how do you know the
// current chain height if you don't have internet access? Trust the server? Probably opens up
// attack vectors. We can assume the client has an independent clock, however. If the client
// considers this value too far off (eg more than a day), it may send an ERROR and close the
// channel.
required uint64 expire_time_secs = 3;
// The amount of money the server requires for the initial payment. The act of opening a channel
// always transfers some quantity of money to the server: it's impossible to have a channel with
// zero value transferred. This rule ensures that you can't get a channel that can't be settled
// due to having paid under the dust limit. Because the dust limit will float in future, the
// server tells the client what it thinks it is, and the client is supposed to sanity check this
// value.
required uint64 min_payment = 4;
}
// Sent from primary to secondary after Initiate to begin the refund transaction signing.
message ProvideRefund {
// This must be a raw pubkey in regular ECDSA form. Both compressed and non-compressed forms
// are accepted. It is only used in the creation of the multisig contract.
required bytes multisig_key = 1;
// The serialized bytes of the return transaction in Satoshi format.
// * It must have exactly one input which spends the multisig output (see ProvideContract for
// details of exactly what that output must look like). This output must have a sequence
// number of 0.
// * It must have the lock time set to a time after the min_time_window_secs (from the
// Initiate message).
// * It must have exactly one output which goes back to the primary. This output's
// scriptPubKey will be reused to create payment transactions.
required bytes tx = 2;
}
// Sent from secondary to primary after it has done initial verification of the refund
// transaction. Contains the primary's signature which is required to spend the multisig contract
// to the refund transaction. Must be signed using SIGHASH_NONE|SIGHASH_ANYONECANPAY (and include
// the postfix type byte) to allow the client to add any outputs/inputs it wants as long as the
// input's sequence and transaction's nLockTime remain set.
message ReturnRefund {
required bytes signature = 1;
}
// Sent from the primary to the secondary to complete initialization.
message ProvideContract {
// The serialized bytes of the transaction in Satoshi format.
// * It must be signed and completely valid and ready for broadcast (ie it includes the
// necessary fees) TODO: tell the client how much fee it needs
// * Its first output must be a 2-of-2 multisig output with the first pubkey being the
// primary's and the second being the secondary's (ie the script must be exactly "OP_2
// ProvideRefund.multisig_key Initiate.multisig_key OP_2 OP_CHECKMULTISIG")
required bytes tx = 1;
// To open the channel, an initial payment of the server-specified dust limit value must be
// provided. This ensures that the channel is never in an un-settleable state due to either
// no payment tx having been provided at all, or a payment that is smaller than the dust
// limit being provided.
required UpdatePayment initial_payment = 2;
}
// This message can only be used by the primary after it has received a CHANNEL_OPEN message. It
// creates a new payment transaction. Note that we don't resubmit the entire TX, this is to avoid
// (re)parsing bugs and overhead. The payment transaction is created by the primary by:
// * Adding an input which spends the multisig contract
// * Setting this input's scriptSig to the given signature and a new signature created by the
// primary (the primary should ensure the signature provided correctly spends the multisig
// contract)
// * Adding an output who's scriptPubKey is the same as the refund output (the only output) in
// the refund transaction
// * Setting this output's value to client_change_value (which must be lower than the most recent
// client_change_value and lower than the multisig contract's output value)
// * Adding any number of additional outputs as desired (leaving sufficient fee, if necessary)
// * Adding any number of additional inputs as desired (eg to add more fee)
message UpdatePayment {
// The value which is sent back to the primary. The rest of the multisig output is left for
// the secondary to do with as they wish.
required uint64 client_change_value = 1;
// A SIGHASH_SINGLE|SIGHASH_ANYONECANPAY signature (including the postfix type byte) which
// spends the primary's part of the multisig contract's output. This signature only covers
// the primary's refund output and thus the secondary is free to do what they wish with their
// part of the multisig output.
required bytes signature = 2;
// Information about this update. Used to extend this protocol.
optional bytes info = 3;
}
// This message is sent as an acknowledgement of an UpdatePayment message
message PaymentAck {
// Information about this update. Used to extend this protocol
optional bytes info = 1;
}
message Settlement {
// A copy of the fully signed final contract that settles the channel. The client can verify
// the transaction is correct and then commit it to their wallet.
required bytes tx = 3;
}
// An Error can be sent by either party at any time
// Both parties should make an effort to send either an ERROR or a CLOSE immediately before
// closing the socket (unless they just received an ERROR or a CLOSE)
message Error {
enum ErrorCode {
TIMEOUT = 1; // Protocol timeout occurred (one party hung).
SYNTAX_ERROR = 2; // Generic error indicating some message was not properly
// formatted or was out of order.
NO_ACCEPTABLE_VERSION = 3; // We don't speak the version the other side asked for.
BAD_TRANSACTION = 4; // A provided transaction was not in the proper structure
// (wrong inputs/outputs, sequence, lock time, signature,
// etc)
TIME_WINDOW_UNACCEPTABLE = 5; // The expire time specified by the secondary was unacceptable
// for the primary
CHANNEL_VALUE_TOO_LARGE = 6; // The minimum channel value specified by the secondary was
// too large for the primary
MIN_PAYMENT_TOO_LARGE = 7; // The min "dust limit" specified by the server was too large for the client.
OTHER = 8;
};
optional ErrorCode code = 1 [default=OTHER];
optional string explanation = 2; // NOT SAFE FOR HTML WITHOUT ESCAPING
// Can be set by the client when erroring to the server if a value was out of range. Can help with debugging.
optional uint64 expected_value = 3;
}