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