/** 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; }