3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-22 07:05:50 +00:00
altcoinj/core/src/paymentchannel.proto
Will Shackleton 8af0fa9884 Implemented version 2 of payment channels API
I implemented version 2 of the payment channels API using
OP_CHECKLOCKTIMEVERIFY-style payment channels.
2016-02-10 11:15:35 +01:00

272 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.
// For version 1:
// * 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")
// For version 2:
// * 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 CHECKLOCKTIMEVERIFY output with the first pubkey being the
// primary's and the second being the secondary's.
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 field is added in protocol version 2 to send the client public key to the server.
// In version 1 it isn't used.
// 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.
optional bytes client_key = 3;
}
// 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;
}