Cleanup comments & removed notes on escrow
This commit is contained in:
parent
84c0f56330
commit
f2a1c0368a
@ -1,121 +0,0 @@
|
||||
NOTE: Not implemented in code, only included as part of the wire protocol for
|
||||
future implementation!
|
||||
|
||||
There are multiple R-value hashes supported in HTLCs in the wire protocol. This
|
||||
is to support conditional multiparty payments, e.g. 2-of-3 "escrow", which is
|
||||
one of the biggest use cases of bitcoin scripting today. An example use case is
|
||||
a 3rd party escrow verifies whether a seller should be paid. This design is
|
||||
such that the escrow is not a traditional custodial escrow, but instead
|
||||
determines who should get the money in the event of non-cooperation.
|
||||
|
||||
In this implementation, we are including *wire protocol support* but not
|
||||
writing code yet for 2-of-3, it is to be implemented later. Arbitrary N-of-M
|
||||
can be supported with M values higher than 3 and lower than max script size,
|
||||
but let's keep this simple for now!
|
||||
|
||||
How it works: Require 2-of-3 R-value preimages (from 3 hashes) in order for the
|
||||
HTLC to be fulfilled. For each hop in the payment, it requires this 2-of-3
|
||||
condition. The timeout minimum for each hop in the path is at least the minimum
|
||||
agreed contractual escrow timeout. This means each hop consumes a higher amount
|
||||
of time-value (due to much longer timeouts along all channels in the path),
|
||||
which does have greater pressure towards lower hop-distances compared to
|
||||
straight payments.
|
||||
|
||||
This is a slightly different way of thinking about things. It's not signatures
|
||||
that the escrow produces (or for that matters any of the 3-parties in the
|
||||
2-of-3). It's some secret which is revealed to authorize payment. So if the
|
||||
Escrow wants the payment to go through, they disclose the secret (R-value) to
|
||||
the recipient. If the recipient is unable to produce 2-of-3, after the agreed
|
||||
timeout, the sender will be refunded. Sender and receiver can agree to
|
||||
authorize payment in most cases where there is cooperation, escrow is only
|
||||
contacted if there is non-cooperation.
|
||||
|
||||
Supported in the wire protocol for the uint8 (two 4-bit N-of-M):
|
||||
17 (00010001): 1-of-1
|
||||
34 (00100010): 2-of-2
|
||||
35 (00100011): 2-of-3 [with Recipient being 1 of the two N parties]
|
||||
51 (00110011): 3-of-3
|
||||
|
||||
I think the only ones that really matter are 1-of-1, 2-of-3, and 2-of-2. 1-of-2
|
||||
and 1-of-3 doesn't make sense if the recipient must consent to receiving funds
|
||||
anyway (pushing funds w/o consent is tricky due to pay-to-contract-hash) so
|
||||
that's basically a 1-of-1.
|
||||
|
||||
Assume the order in the stack is Sender, Escrow, Recipient.
|
||||
|
||||
For PAID 2-of-3 Escrow+Recipient, the HTLC stack is:
|
||||
<BobSig> <0> <EscrowPreimageR> <RecipientPreimageR> <0>
|
||||
|
||||
If it's REFUND because 2-of-3 has not been redeemed in time:
|
||||
<AliceSig> <1>
|
||||
|
||||
Script (we use OP_1/OP_0 to distinctly show computed true/false. 0/1 is for
|
||||
supplied data as part of the sigScript/redeemScript stack):
|
||||
-------------------------------------------------------------------------------
|
||||
//Paid
|
||||
OP_IF
|
||||
<CSVDelay> OP_DROP OP_CSV
|
||||
|
||||
//Stack: <BobSig> <0> <EscrowPreimageR> <RecipientPreimageR>
|
||||
//Recipient must agree to receive funds.
|
||||
OP_HASH160 <RecipientHash> OP_EQUALVERIFY
|
||||
|
||||
//Stack: <BobSig> <0> <EscrowPreimageR>
|
||||
//Either the Sender or Escrow must consent for payment
|
||||
OP_HASH160 <EscrowHash> OP_EQUAL
|
||||
//Stack: <BobSig> <0> <OP_1>
|
||||
OP_SWAP
|
||||
//Stack: <BobSig> <OP_1> <0>
|
||||
OP_HASH160 <SenderHash> OP_EQUAL
|
||||
//Stack: <BobSig> <OP_1> <OP_0>
|
||||
OP_BOOLOR
|
||||
//Stack: <BobSig> <OP_1>
|
||||
OP_VERIFY
|
||||
|
||||
<BobPubKey>
|
||||
//Stack: <BobSig> <BobPubKey>
|
||||
//Refund
|
||||
OP_ELSE
|
||||
<CSVDelay> OP_DROP OP_CSV
|
||||
|
||||
<HTLCTimeout> OP_DROP OP_CLTV
|
||||
<AlicePubKey>
|
||||
//Stack: <AliceSig> <AlicePubKey>
|
||||
OP_ENDIF
|
||||
OP_CHECKSIG
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Note: It is possible that Alice and Bob may not be Sender, Recipient, nor
|
||||
Escrow!
|
||||
|
||||
The result? We can do 2-of-3 escrow payments which refund to the sender after a
|
||||
timeout! The Sender and Recipient can agree to redeem and they only need to go
|
||||
to the Escrow if there's a dispute. All nodes along the path gets paid or
|
||||
refunded atomically, the same as a single-HTLC payment on Lightning.
|
||||
|
||||
Possible Resolution States:
|
||||
* Recipient paid: Recipient and Sender provide R-values
|
||||
* Recipient paid: Recipient and Escrow provide R-values
|
||||
* Sender refunded via timeout: Sender is refunded if Recipient cannot convince
|
||||
Escrow or Sender to disclose their R-value before HTLC timeout
|
||||
* Payment immediately cancelled and Sender gets refunded: Payment sent in the
|
||||
opposite direction enforced by same R-values (if there is sender & receiver
|
||||
consent & cooperation to cancel payment)
|
||||
|
||||
Sender+Escrow isn't going to want to push funds w/o cooperation of Recipient.
|
||||
However, it's possible to construct a script that way.
|
||||
|
||||
Ta-da! "Smart Contract(TM)" maymay.
|
||||
|
||||
Escrow-enforced immediately refundable payments (2-of-3 can immediately cancel
|
||||
a payment) are also possible but requires another payment in the opposite
|
||||
direction with the R-value hashed twice (the H becomes the R-value) and funds
|
||||
encumbered in the opposite direction, but that's kind of annoying to write...
|
||||
it's easier if immediate refund can only occur when both Recipient+Sender agree
|
||||
to cancel the payment immediately (otherwise it will wait until the timeout).
|
||||
|
||||
Escrow is only contacted if the recipient needs to redeem and the sender is
|
||||
uncooperative so this is still true to the "lazy escrow service" in Bitcoin
|
||||
multisig.
|
||||
|
||||
(2-of-2 is also needed for payment cancellation.)
|
@ -11,15 +11,15 @@ import (
|
||||
type CloseComplete struct {
|
||||
ReservationID uint64
|
||||
|
||||
ResponderCloseSig *btcec.Signature //Requester's Commitment
|
||||
CloseShaHash *wire.ShaHash //TxID of the Close Tx
|
||||
ResponderCloseSig *btcec.Signature // Requester's Commitment
|
||||
CloseShaHash *wire.ShaHash // TxID of the Close Tx
|
||||
}
|
||||
|
||||
func (c *CloseComplete) Decode(r io.Reader, pver uint32) error {
|
||||
//ReservationID (8)
|
||||
//ResponderCloseSig (73)
|
||||
// First byte length then sig
|
||||
//CloseShaHash (32)
|
||||
// ReservationID (8)
|
||||
// ResponderCloseSig (73)
|
||||
// First byte length then sig
|
||||
// CloseShaHash (32)
|
||||
err := readElements(r,
|
||||
&c.ReservationID,
|
||||
&c.ResponderCloseSig,
|
||||
@ -31,17 +31,17 @@ func (c *CloseComplete) Decode(r io.Reader, pver uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new CloseComplete
|
||||
// Creates a new CloseComplete
|
||||
func NewCloseComplete() *CloseComplete {
|
||||
return &CloseComplete{}
|
||||
}
|
||||
|
||||
//Serializes the item from the CloseComplete struct
|
||||
//Writes the data to w
|
||||
// Serializes the item from the CloseComplete struct
|
||||
// Writes the data to w
|
||||
func (c *CloseComplete) Encode(w io.Writer, pver uint32) error {
|
||||
//ReservationID
|
||||
//ResponderCloseSig
|
||||
//CloseShaHash
|
||||
// ReservationID
|
||||
// ResponderCloseSig
|
||||
// CloseShaHash
|
||||
err := writeElements(w,
|
||||
c.ReservationID,
|
||||
c.ResponderCloseSig,
|
||||
@ -58,13 +58,13 @@ func (c *CloseComplete) Command() uint32 {
|
||||
}
|
||||
|
||||
func (c *CloseComplete) MaxPayloadLength(uint32) uint32 {
|
||||
//8 + 73 + 32
|
||||
// 8 + 73 + 32
|
||||
return 113
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *CloseComplete) Validate() error {
|
||||
//We're good!
|
||||
// We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
//"github.com/btcsuite/btcutil"
|
||||
// "github.com/btcsuite/btcutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -16,19 +16,19 @@ var (
|
||||
)
|
||||
|
||||
func TestCloseCompleteEncodeDecode(t *testing.T) {
|
||||
//All of these types being passed are of the message interface type
|
||||
//Test serialization, runs: message.Encode(b, 0)
|
||||
//Returns bytes
|
||||
//Compares the expected serialized string from the original
|
||||
// All of these types being passed are of the message interface type
|
||||
// Test serialization, runs: message.Encode(b, 0)
|
||||
// Returns bytes
|
||||
// Compares the expected serialized string from the original
|
||||
s := SerializeTest(t, closeComplete, closeCompleteSerializedString, filename)
|
||||
|
||||
//Test deserialization, runs: message.Decode(s, 0)
|
||||
//Makes sure the deserialized struct is the same as the original
|
||||
// Test deserialization, runs: message.Decode(s, 0)
|
||||
// Makes sure the deserialized struct is the same as the original
|
||||
newMessage := NewCloseComplete()
|
||||
DeserializeTest(t, s, newMessage, closeComplete)
|
||||
|
||||
//Test message using Message interface
|
||||
//Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
//Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
// Test message using Message interface
|
||||
// Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
// Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
MessageSerializeDeserializeTest(t, closeComplete, closeCompleteSerializedMessage)
|
||||
}
|
||||
|
@ -11,15 +11,15 @@ import (
|
||||
type CloseRequest struct {
|
||||
ReservationID uint64
|
||||
|
||||
RequesterCloseSig *btcec.Signature //Requester's Commitment
|
||||
RequesterCloseSig *btcec.Signature // Requester's Commitment
|
||||
Fee btcutil.Amount
|
||||
}
|
||||
|
||||
func (c *CloseRequest) Decode(r io.Reader, pver uint32) error {
|
||||
//ReservationID (8)
|
||||
//RequesterCloseSig (73)
|
||||
// First byte length then sig
|
||||
//Fee (8)
|
||||
// ReservationID (8)
|
||||
// RequesterCloseSig (73)
|
||||
// First byte length then sig
|
||||
// Fee (8)
|
||||
err := readElements(r,
|
||||
&c.ReservationID,
|
||||
&c.RequesterCloseSig,
|
||||
@ -31,17 +31,17 @@ func (c *CloseRequest) Decode(r io.Reader, pver uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new CloseRequest
|
||||
// Creates a new CloseRequest
|
||||
func NewCloseRequest() *CloseRequest {
|
||||
return &CloseRequest{}
|
||||
}
|
||||
|
||||
//Serializes the item from the CloseRequest struct
|
||||
//Writes the data to w
|
||||
// Serializes the item from the CloseRequest struct
|
||||
// Writes the data to w
|
||||
func (c *CloseRequest) Encode(w io.Writer, pver uint32) error {
|
||||
//ReservationID
|
||||
//RequesterCloseSig
|
||||
//Fee
|
||||
// ReservationID
|
||||
// RequesterCloseSig
|
||||
// Fee
|
||||
err := writeElements(w,
|
||||
c.ReservationID,
|
||||
c.RequesterCloseSig,
|
||||
@ -58,17 +58,17 @@ func (c *CloseRequest) Command() uint32 {
|
||||
}
|
||||
|
||||
func (c *CloseRequest) MaxPayloadLength(uint32) uint32 {
|
||||
//8 + 73 + 8
|
||||
// 8 + 73 + 8
|
||||
return 89
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *CloseRequest) Validate() error {
|
||||
//Fee must be greater than 0
|
||||
// Fee must be greater than 0
|
||||
if c.Fee < 0 {
|
||||
return fmt.Errorf("Fee must be greater than zero.")
|
||||
}
|
||||
//We're good!
|
||||
// We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -16,19 +16,19 @@ var (
|
||||
)
|
||||
|
||||
func TestCloseRequestEncodeDecode(t *testing.T) {
|
||||
//All of these types being passed are of the message interface type
|
||||
//Test serialization, runs: message.Encode(b, 0)
|
||||
//Returns bytes
|
||||
//Compares the expected serialized string from the original
|
||||
// All of these types being passed are of the message interface type
|
||||
// Test serialization, runs: message.Encode(b, 0)
|
||||
// Returns bytes
|
||||
// Compares the expected serialized string from the original
|
||||
s := SerializeTest(t, closeRequest, closeRequestSerializedString, filename)
|
||||
|
||||
//Test deserialization, runs: message.Decode(s, 0)
|
||||
//Makes sure the deserialized struct is the same as the original
|
||||
// Test deserialization, runs: message.Decode(s, 0)
|
||||
// Makes sure the deserialized struct is the same as the original
|
||||
newMessage := NewCloseRequest()
|
||||
DeserializeTest(t, s, newMessage, closeRequest)
|
||||
|
||||
//Test message using Message interface
|
||||
//Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
//Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
// Test message using Message interface
|
||||
// Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
// Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
MessageSerializeDeserializeTest(t, closeRequest, closeRequestSerializedMessage)
|
||||
}
|
||||
|
@ -5,28 +5,28 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
//Multiple Clearing Requests are possible by putting this inside an array of
|
||||
//clearing requests
|
||||
// Multiple Clearing Requests are possible by putting this inside an array of
|
||||
// clearing requests
|
||||
type CommitRevocation struct {
|
||||
//We can use a different data type for this if necessary...
|
||||
// We can use a different data type for this if necessary...
|
||||
ChannelID uint64
|
||||
|
||||
//Height of the commitment
|
||||
//You should have the most recent commitment height stored locally
|
||||
//This should be validated!
|
||||
//This is used for shachain.
|
||||
//Each party increments their own CommitmentHeight, they can differ for
|
||||
//each part of the Commitment.
|
||||
// Height of the commitment
|
||||
// You should have the most recent commitment height stored locally
|
||||
// This should be validated!
|
||||
// This is used for shachain.
|
||||
// Each party increments their own CommitmentHeight, they can differ for
|
||||
// each part of the Commitment.
|
||||
CommitmentHeight uint64
|
||||
|
||||
//Revocation to use
|
||||
// Revocation to use
|
||||
RevocationProof [20]byte
|
||||
}
|
||||
|
||||
func (c *CommitRevocation) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//CommitmentHeight(8)
|
||||
//RevocationProof(20)
|
||||
// ChannelID(8)
|
||||
// CommitmentHeight(8)
|
||||
// RevocationProof(20)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.CommitmentHeight,
|
||||
@ -39,13 +39,13 @@ func (c *CommitRevocation) Decode(r io.Reader, pver uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new CommitRevocation
|
||||
// Creates a new CommitRevocation
|
||||
func NewCommitRevocation() *CommitRevocation {
|
||||
return &CommitRevocation{}
|
||||
}
|
||||
|
||||
//Serializes the item from the CommitRevocation struct
|
||||
//Writes the data to w
|
||||
// Serializes the item from the CommitRevocation struct
|
||||
// Writes the data to w
|
||||
func (c *CommitRevocation) Encode(w io.Writer, pver uint32) error {
|
||||
err := writeElements(w,
|
||||
c.ChannelID,
|
||||
@ -67,9 +67,9 @@ func (c *CommitRevocation) MaxPayloadLength(uint32) uint32 {
|
||||
return 36
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *CommitRevocation) Validate() error {
|
||||
//We're good!
|
||||
// We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -5,32 +5,32 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
//Need to to do this here
|
||||
// Need to to do this here
|
||||
_ = copy(revocationHash[:], revocationHashBytes)
|
||||
|
||||
commitRevocation = &CommitRevocation{
|
||||
ChannelID: uint64(12345678),
|
||||
CommitmentHeight: uint64(12345),
|
||||
RevocationProof: revocationHash, //technically it's not a hash... fix later
|
||||
RevocationProof: revocationHash, // technically it's not a hash... fix later
|
||||
}
|
||||
commitRevocationSerializedString = "0000000000bc614e00000000000030394132b6b48371f7b022a16eacb9b2b0ebee134d41"
|
||||
commitRevocationSerializedMessage = "0709110b000007da000000240000000000bc614e00000000000030394132b6b48371f7b022a16eacb9b2b0ebee134d41"
|
||||
)
|
||||
|
||||
func TestCommitRevocationEncodeDecode(t *testing.T) {
|
||||
//All of these types being passed are of the message interface type
|
||||
//Test serialization, runs: message.Encode(b, 0)
|
||||
//Returns bytes
|
||||
//Compares the expected serialized string from the original
|
||||
// All of these types being passed are of the message interface type
|
||||
// Test serialization, runs: message.Encode(b, 0)
|
||||
// Returns bytes
|
||||
// Compares the expected serialized string from the original
|
||||
s := SerializeTest(t, commitRevocation, commitRevocationSerializedString, filename)
|
||||
|
||||
//Test deserialization, runs: message.Decode(s, 0)
|
||||
//Makes sure the deserialized struct is the same as the original
|
||||
// Test deserialization, runs: message.Decode(s, 0)
|
||||
// Makes sure the deserialized struct is the same as the original
|
||||
newMessage := NewCommitRevocation()
|
||||
DeserializeTest(t, s, newMessage, commitRevocation)
|
||||
|
||||
//Test message using Message interface
|
||||
//Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
//Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
// Test message using Message interface
|
||||
// Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
// Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
MessageSerializeDeserializeTest(t, commitRevocation, commitRevocationSerializedMessage)
|
||||
}
|
||||
|
@ -7,40 +7,40 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
//Multiple Clearing Requests are possible by putting this inside an array of
|
||||
//clearing requests
|
||||
// Multiple Clearing Requests are possible by putting this inside an array of
|
||||
// clearing requests
|
||||
type CommitSignature struct {
|
||||
//We can use a different data type for this if necessary...
|
||||
// We can use a different data type for this if necessary...
|
||||
ChannelID uint64
|
||||
|
||||
//Height of the commitment
|
||||
//You should have the most recent commitment height stored locally
|
||||
//This should be validated!
|
||||
//This is used for shachain.
|
||||
//Each party increments their own CommitmentHeight, they can differ for
|
||||
//each part of the Commitment.
|
||||
// Height of the commitment
|
||||
// You should have the most recent commitment height stored locally
|
||||
// This should be validated!
|
||||
// This is used for shachain.
|
||||
// Each party increments their own CommitmentHeight, they can differ for
|
||||
// each part of the Commitment.
|
||||
CommitmentHeight uint64
|
||||
|
||||
//List of HTLC Keys which are updated from all parties
|
||||
// List of HTLC Keys which are updated from all parties
|
||||
UpdatedHTLCKeys []uint64
|
||||
|
||||
//Hash of the revocation to use
|
||||
// Hash of the revocation to use
|
||||
RevocationHash [20]byte
|
||||
|
||||
//Total miners' fee that was used
|
||||
// Total miners' fee that was used
|
||||
Fee btcutil.Amount
|
||||
|
||||
//Signature for the new Commitment
|
||||
CommitSig *btcec.Signature //Requester's Commitment
|
||||
// Signature for the new Commitment
|
||||
CommitSig *btcec.Signature // Requester's Commitment
|
||||
}
|
||||
|
||||
func (c *CommitSignature) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//CommitmentHeight(8)
|
||||
//c.UpdatedHTLCKeys(8*1000max)
|
||||
//RevocationHash(20)
|
||||
//Fee(8)
|
||||
//RequesterCommitSig(73max+2)
|
||||
// ChannelID(8)
|
||||
// CommitmentHeight(8)
|
||||
// c.UpdatedHTLCKeys(8*1000max)
|
||||
// RevocationHash(20)
|
||||
// Fee(8)
|
||||
// RequesterCommitSig(73max+2)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.CommitmentHeight,
|
||||
@ -56,13 +56,13 @@ func (c *CommitSignature) Decode(r io.Reader, pver uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new CommitSignature
|
||||
// Creates a new CommitSignature
|
||||
func NewCommitSignature() *CommitSignature {
|
||||
return &CommitSignature{}
|
||||
}
|
||||
|
||||
//Serializes the item from the CommitSignature struct
|
||||
//Writes the data to w
|
||||
// Serializes the item from the CommitSignature struct
|
||||
// Writes the data to w
|
||||
func (c *CommitSignature) Encode(w io.Writer, pver uint32) error {
|
||||
err := writeElements(w,
|
||||
c.ChannelID,
|
||||
@ -87,24 +87,24 @@ func (c *CommitSignature) MaxPayloadLength(uint32) uint32 {
|
||||
return 8192
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *CommitSignature) Validate() error {
|
||||
if c.Fee < 0 {
|
||||
//While fees can be negative, it's too confusing to allow
|
||||
//negative payments. Maybe for some wallets, but not this one!
|
||||
// While fees can be negative, it's too confusing to allow
|
||||
// negative payments. Maybe for some wallets, but not this one!
|
||||
return fmt.Errorf("Amount paid cannot be negative.")
|
||||
}
|
||||
//We're good!
|
||||
// We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CommitSignature) String() string {
|
||||
//c.ChannelID,
|
||||
//c.CommitmentHeight,
|
||||
//c.RevocationHash,
|
||||
//c.UpdatedHTLCKeys,
|
||||
//c.Fee,
|
||||
//c.CommitSig,
|
||||
// c.ChannelID,
|
||||
// c.CommitmentHeight,
|
||||
// c.RevocationHash,
|
||||
// c.UpdatedHTLCKeys,
|
||||
// c.Fee,
|
||||
// c.CommitSig,
|
||||
var serializedSig []byte
|
||||
if &c.CommitSig != nil && c.CommitSig.R != nil {
|
||||
serializedSig = c.CommitSig.Serialize()
|
||||
|
@ -6,13 +6,13 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
//Need to to do this here
|
||||
// Need to to do this here
|
||||
_ = copy(revocationHash[:], revocationHashBytes)
|
||||
|
||||
commitSignature = &CommitSignature{
|
||||
ChannelID: uint64(12345678),
|
||||
CommitmentHeight: uint64(12345),
|
||||
//CommitterLastStaging: uint64(12345678),
|
||||
// CommitterLastStaging: uint64(12345678),
|
||||
UpdatedHTLCKeys: []uint64{1, 2, 3, 4, 5},
|
||||
RevocationHash: revocationHash,
|
||||
Fee: btcutil.Amount(10000),
|
||||
@ -23,19 +23,19 @@ var (
|
||||
)
|
||||
|
||||
func TestCommitSignatureEncodeDecode(t *testing.T) {
|
||||
//All of these types being passed are of the message interface type
|
||||
//Test serialization, runs: message.Encode(b, 0)
|
||||
//Returns bytes
|
||||
//Compares the expected serialized string from the original
|
||||
// All of these types being passed are of the message interface type
|
||||
// Test serialization, runs: message.Encode(b, 0)
|
||||
// Returns bytes
|
||||
// Compares the expected serialized string from the original
|
||||
s := SerializeTest(t, commitSignature, commitSignatureSerializedString, filename)
|
||||
|
||||
//Test deserialization, runs: message.Decode(s, 0)
|
||||
//Makes sure the deserialized struct is the same as the original
|
||||
// Test deserialization, runs: message.Decode(s, 0)
|
||||
// Makes sure the deserialized struct is the same as the original
|
||||
newMessage := NewCommitSignature()
|
||||
DeserializeTest(t, s, newMessage, commitSignature)
|
||||
|
||||
//Test message using Message interface
|
||||
//Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
//Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
// Test message using Message interface
|
||||
// Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
// Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
MessageSerializeDeserializeTest(t, commitSignature, commitSignatureSerializedMessage)
|
||||
}
|
||||
|
@ -5,19 +5,19 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
//Multiple Clearing Requests are possible by putting this inside an array of
|
||||
//clearing requests
|
||||
// Multiple Clearing Requests are possible by putting this inside an array of
|
||||
// clearing requests
|
||||
type ErrorGeneric struct {
|
||||
//We can use a different data type for this if necessary...
|
||||
// We can use a different data type for this if necessary...
|
||||
ChannelID uint64
|
||||
//Some kind of message
|
||||
//Max length 8192
|
||||
// Some kind of message
|
||||
// Max length 8192
|
||||
Problem string
|
||||
}
|
||||
|
||||
func (c *ErrorGeneric) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//Problem
|
||||
// ChannelID(8)
|
||||
// Problem
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.Problem,
|
||||
@ -29,13 +29,13 @@ func (c *ErrorGeneric) Decode(r io.Reader, pver uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new ErrorGeneric
|
||||
// Creates a new ErrorGeneric
|
||||
func NewErrorGeneric() *ErrorGeneric {
|
||||
return &ErrorGeneric{}
|
||||
}
|
||||
|
||||
//Serializes the item from the ErrorGeneric struct
|
||||
//Writes the data to w
|
||||
// Serializes the item from the ErrorGeneric struct
|
||||
// Writes the data to w
|
||||
func (c *ErrorGeneric) Encode(w io.Writer, pver uint32) error {
|
||||
err := writeElements(w,
|
||||
c.ChannelID,
|
||||
@ -53,16 +53,16 @@ func (c *ErrorGeneric) Command() uint32 {
|
||||
}
|
||||
|
||||
func (c *ErrorGeneric) MaxPayloadLength(uint32) uint32 {
|
||||
//8+8192
|
||||
// 8+8192
|
||||
return 8208
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *ErrorGeneric) Validate() error {
|
||||
if len(c.Problem) > 8192 {
|
||||
return fmt.Errorf("Problem string length too long")
|
||||
}
|
||||
//We're good!
|
||||
// We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -14,19 +14,19 @@ var (
|
||||
)
|
||||
|
||||
func TestErrorGenericEncodeDecode(t *testing.T) {
|
||||
//All of these types being passed are of the message interface type
|
||||
//Test serialization, runs: message.Encode(b, 0)
|
||||
//Returns bytes
|
||||
//Compares the expected serialized string from the original
|
||||
// All of these types being passed are of the message interface type
|
||||
// Test serialization, runs: message.Encode(b, 0)
|
||||
// Returns bytes
|
||||
// Compares the expected serialized string from the original
|
||||
s := SerializeTest(t, errorGeneric, errorGenericSerializedString, filename)
|
||||
|
||||
//Test deserialization, runs: message.Decode(s, 0)
|
||||
//Makes sure the deserialized struct is the same as the original
|
||||
// Test deserialization, runs: message.Decode(s, 0)
|
||||
// Makes sure the deserialized struct is the same as the original
|
||||
newMessage := NewErrorGeneric()
|
||||
DeserializeTest(t, s, newMessage, errorGeneric)
|
||||
|
||||
//Test message using Message interface
|
||||
//Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
//Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
// Test message using Message interface
|
||||
// Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
// Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
MessageSerializeDeserializeTest(t, errorGeneric, errorGenericSerializedMessage)
|
||||
}
|
||||
|
@ -17,62 +17,62 @@ type FundingRequest struct {
|
||||
RequesterReserveAmount btcutil.Amount
|
||||
MinFeePerKb btcutil.Amount
|
||||
|
||||
//The funding requester can request payment
|
||||
//This wallet only allows positive values,
|
||||
//which is a payment to the responder
|
||||
//(This can be used to fund the Reserve)
|
||||
//If the responder disagrees, then the funding request fails
|
||||
//THIS VALUE GOES INTO THE RESPONDER'S FUNDING AMOUNT
|
||||
//total requester input value = RequesterFundingAmount + PaymentAmount + "Total Change" + Fees(?)
|
||||
//RequesterFundingAmount = "Available Balance" + RequesterReserveAmount
|
||||
//Payment SHOULD NOT be acknowledged until the minimum confirmation has elapsed
|
||||
//(Due to double-spend risks the recipient will not want to acknolwedge confirmation until later)
|
||||
//This is to make a payment as part of opening the channel
|
||||
// The funding requester can request payment
|
||||
// This wallet only allows positive values,
|
||||
// which is a payment to the responder
|
||||
// (This can be used to fund the Reserve)
|
||||
// If the responder disagrees, then the funding request fails
|
||||
// THIS VALUE GOES INTO THE RESPONDER'S FUNDING AMOUNT
|
||||
// total requester input value = RequesterFundingAmount + PaymentAmount + "Total Change" + Fees(?)
|
||||
// RequesterFundingAmount = "Available Balance" + RequesterReserveAmount
|
||||
// Payment SHOULD NOT be acknowledged until the minimum confirmation has elapsed
|
||||
// (Due to double-spend risks the recipient will not want to acknolwedge confirmation until later)
|
||||
// This is to make a payment as part of opening the channel
|
||||
PaymentAmount btcutil.Amount
|
||||
|
||||
//Minimum number of confirmations to validate transaction
|
||||
// Minimum number of confirmations to validate transaction
|
||||
MinDepth uint32
|
||||
|
||||
//Should double-check the total funding later
|
||||
// Should double-check the total funding later
|
||||
MinTotalFundingAmount btcutil.Amount
|
||||
|
||||
//CLTV/CSV lock-time to use
|
||||
// CLTV/CSV lock-time to use
|
||||
LockTime uint32
|
||||
|
||||
//Who pays the fees
|
||||
//0: (default) channel initiator
|
||||
//1: split
|
||||
//2: channel responder
|
||||
// Who pays the fees
|
||||
// 0: (default) channel initiator
|
||||
// 1: split
|
||||
// 2: channel responder
|
||||
FeePayer uint8
|
||||
|
||||
RevocationHash [20]byte
|
||||
Pubkey *btcec.PublicKey
|
||||
DeliveryPkScript PkScript //*MUST* be either P2PKH or P2SH
|
||||
ChangePkScript PkScript //*MUST* be either P2PKH or P2SH
|
||||
DeliveryPkScript PkScript // *MUST* be either P2PKH or P2SH
|
||||
ChangePkScript PkScript // *MUST* be either P2PKH or P2SH
|
||||
|
||||
Inputs []*wire.TxIn
|
||||
}
|
||||
|
||||
func (c *FundingRequest) Decode(r io.Reader, pver uint32) error {
|
||||
//Reservation ID (8)
|
||||
//Channel Type (1)
|
||||
//Funding Amount (8)
|
||||
//Channel Minimum Capacity (8)
|
||||
//Revocation Hash (20)
|
||||
//Commitment Pubkey (32)
|
||||
//Reserve Amount (8)
|
||||
//Minimum Transaction Fee Per Kb (8)
|
||||
//PaymentAmount (8)
|
||||
//MinDepth (4)
|
||||
//LockTime (4)
|
||||
//FeePayer (1)
|
||||
//DeliveryPkScript (final delivery)
|
||||
// First byte length then pkscript
|
||||
//ChangePkScript (change for extra from inputs)
|
||||
// First byte length then pkscript
|
||||
//Inputs: Create the TxIns
|
||||
// First byte is number of inputs
|
||||
// For each input, it's 32bytes txin & 4bytes index
|
||||
// Reservation ID (8)
|
||||
// Channel Type (1)
|
||||
// Funding Amount (8)
|
||||
// Channel Minimum Capacity (8)
|
||||
// Revocation Hash (20)
|
||||
// Commitment Pubkey (32)
|
||||
// Reserve Amount (8)
|
||||
// Minimum Transaction Fee Per Kb (8)
|
||||
// PaymentAmount (8)
|
||||
// MinDepth (4)
|
||||
// LockTime (4)
|
||||
// FeePayer (1)
|
||||
// DeliveryPkScript (final delivery)
|
||||
// First byte length then pkscript
|
||||
// ChangePkScript (change for extra from inputs)
|
||||
// First byte length then pkscript
|
||||
// Inputs: Create the TxIns
|
||||
// First byte is number of inputs
|
||||
// For each input, it's 32bytes txin & 4bytes index
|
||||
err := readElements(r,
|
||||
&c.ReservationID,
|
||||
&c.ChannelType,
|
||||
@ -96,26 +96,26 @@ func (c *FundingRequest) Decode(r io.Reader, pver uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new FundingRequest
|
||||
// Creates a new FundingRequest
|
||||
func NewFundingRequest() *FundingRequest {
|
||||
return &FundingRequest{}
|
||||
}
|
||||
|
||||
//Serializes the item from the FundingRequest struct
|
||||
//Writes the data to w
|
||||
// Serializes the item from the FundingRequest struct
|
||||
// Writes the data to w
|
||||
func (c *FundingRequest) Encode(w io.Writer, pver uint32) error {
|
||||
//Channel Type
|
||||
//Funding Amont
|
||||
//Channel Minimum Capacity
|
||||
//Revocation Hash
|
||||
//Commitment Pubkey
|
||||
//Reserve Amount
|
||||
//Minimum Transaction Fee Per KB
|
||||
//LockTime
|
||||
//FeePayer
|
||||
//DeliveryPkScript
|
||||
//ChangePkScript
|
||||
//Inputs: Append the actual Txins
|
||||
// Channel Type
|
||||
// Funding Amont
|
||||
// Channel Minimum Capacity
|
||||
// Revocation Hash
|
||||
// Commitment Pubkey
|
||||
// Reserve Amount
|
||||
// Minimum Transaction Fee Per KB
|
||||
// LockTime
|
||||
// FeePayer
|
||||
// DeliveryPkScript
|
||||
// ChangePkScript
|
||||
// Inputs: Append the actual Txins
|
||||
err := writeElements(w,
|
||||
c.ReservationID,
|
||||
c.ChannelType,
|
||||
@ -144,15 +144,15 @@ func (c *FundingRequest) Command() uint32 {
|
||||
}
|
||||
|
||||
func (c *FundingRequest) MaxPayloadLength(uint32) uint32 {
|
||||
//110 (base size) + 26 (pkscript) + 26 (pkscript) + 1 (numTxes) + 127*36(127 inputs * sha256+idx)
|
||||
// 110 (base size) + 26 (pkscript) + 26 (pkscript) + 1 (numTxes) + 127*36(127 inputs * sha256+idx)
|
||||
return 4735
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *FundingRequest) Validate() error {
|
||||
var err error
|
||||
|
||||
//No negative values
|
||||
// No negative values
|
||||
if c.RequesterFundingAmount < 0 {
|
||||
return fmt.Errorf("RequesterFundingAmount cannot be negative")
|
||||
}
|
||||
@ -168,7 +168,7 @@ func (c *FundingRequest) Validate() error {
|
||||
return fmt.Errorf("MinTotalFundingAmount cannot be negative")
|
||||
}
|
||||
|
||||
//Validation of what makes sense...
|
||||
// Validation of what makes sense...
|
||||
if c.MinTotalFundingAmount < c.RequesterFundingAmount {
|
||||
return fmt.Errorf("Requester's minimum too low.")
|
||||
}
|
||||
@ -176,29 +176,29 @@ func (c *FundingRequest) Validate() error {
|
||||
return fmt.Errorf("Reserve must be below Funding Amount")
|
||||
}
|
||||
|
||||
//This wallet only allows payment from the requester to responder
|
||||
// This wallet only allows payment from the requester to responder
|
||||
if c.PaymentAmount < 0 {
|
||||
return fmt.Errorf("This wallet requieres payment to be greater than zero.")
|
||||
}
|
||||
|
||||
//Make sure there's not more than 127 inputs
|
||||
// Make sure there's not more than 127 inputs
|
||||
if len(c.Inputs) > 127 {
|
||||
return fmt.Errorf("Too many inputs")
|
||||
}
|
||||
|
||||
//DeliveryPkScript is either P2SH or P2PKH
|
||||
// DeliveryPkScript is either P2SH or P2PKH
|
||||
err = ValidatePkScript(c.DeliveryPkScript)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//ChangePkScript is either P2SH or P2PKH
|
||||
// ChangePkScript is either P2SH or P2PKH
|
||||
err = ValidatePkScript(c.ChangePkScript)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//We're good!
|
||||
// We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -6,10 +6,10 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
//Need to do this here
|
||||
// Need to do this here
|
||||
_ = copy(revocationHash[:], revocationHashBytes)
|
||||
|
||||
//funding request
|
||||
// funding request
|
||||
fundingRequest = &FundingRequest{
|
||||
ReservationID: uint64(12345678),
|
||||
ChannelType: uint8(0),
|
||||
@ -17,7 +17,7 @@ var (
|
||||
RequesterReserveAmount: btcutil.Amount(131072),
|
||||
MinFeePerKb: btcutil.Amount(20000),
|
||||
MinTotalFundingAmount: btcutil.Amount(150000000),
|
||||
LockTime: uint32(4320), //30 block-days
|
||||
LockTime: uint32(4320), // 30 block-days
|
||||
FeePayer: uint8(0),
|
||||
PaymentAmount: btcutil.Amount(1234567),
|
||||
MinDepth: uint32(6),
|
||||
@ -32,19 +32,19 @@ var (
|
||||
)
|
||||
|
||||
func TestFundingRequestEncodeDecode(t *testing.T) {
|
||||
//All of these types being passed are of the message interface type
|
||||
//Test serialization, runs: message.Encode(b, 0)
|
||||
//Returns bytes
|
||||
//Compares the expected serialized string from the original
|
||||
// All of these types being passed are of the message interface type
|
||||
// Test serialization, runs: message.Encode(b, 0)
|
||||
// Returns bytes
|
||||
// Compares the expected serialized string from the original
|
||||
s := SerializeTest(t, fundingRequest, fundingRequestSerializedString, filename)
|
||||
|
||||
//Test deserialization, runs: message.Decode(s, 0)
|
||||
//Makes sure the deserialized struct is the same as the original
|
||||
// Test deserialization, runs: message.Decode(s, 0)
|
||||
// Makes sure the deserialized struct is the same as the original
|
||||
newMessage := NewFundingRequest()
|
||||
DeserializeTest(t, s, newMessage, fundingRequest)
|
||||
|
||||
//Test message using Message interface
|
||||
//Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
//Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
// Test message using Message interface
|
||||
// Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
// Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
MessageSerializeDeserializeTest(t, fundingRequest, fundingRequestSerializedMessage)
|
||||
}
|
||||
|
@ -13,51 +13,51 @@ type FundingResponse struct {
|
||||
|
||||
ReservationID uint64
|
||||
|
||||
ResponderFundingAmount btcutil.Amount //Responder's funding amount
|
||||
ResponderReserveAmount btcutil.Amount //Responder's reserve amount
|
||||
MinFeePerKb btcutil.Amount //Lock-in min fee
|
||||
ResponderFundingAmount btcutil.Amount // Responder's funding amount
|
||||
ResponderReserveAmount btcutil.Amount // Responder's reserve amount
|
||||
MinFeePerKb btcutil.Amount // Lock-in min fee
|
||||
|
||||
//Minimum depth
|
||||
// Minimum depth
|
||||
MinDepth uint32
|
||||
|
||||
//CLTV/CSV lock-time to use
|
||||
// CLTV/CSV lock-time to use
|
||||
LockTime uint32
|
||||
|
||||
//Who pays the fees
|
||||
//0: (default) channel initiator
|
||||
//1: split
|
||||
//2: channel responder
|
||||
// Who pays the fees
|
||||
// 0: (default) channel initiator
|
||||
// 1: split
|
||||
// 2: channel responder
|
||||
FeePayer uint8
|
||||
|
||||
RevocationHash [20]byte
|
||||
Pubkey *btcec.PublicKey
|
||||
CommitSig *btcec.Signature //Requester's Commitment
|
||||
DeliveryPkScript PkScript //*MUST* be either P2PKH or P2SH
|
||||
ChangePkScript PkScript //*MUST* be either P2PKH or P2SH
|
||||
CommitSig *btcec.Signature // Requester's Commitment
|
||||
DeliveryPkScript PkScript // *MUST* be either P2PKH or P2SH
|
||||
ChangePkScript PkScript // *MUST* be either P2PKH or P2SH
|
||||
|
||||
Inputs []*wire.TxIn
|
||||
}
|
||||
|
||||
func (c *FundingResponse) Decode(r io.Reader, pver uint32) error {
|
||||
//ReservationID (8)
|
||||
//Channel Type (1)
|
||||
//Funding Amount (8)
|
||||
//Revocation Hash (20)
|
||||
//Commitment Pubkey (32)
|
||||
//Reserve Amount (8)
|
||||
//Minimum Transaction Fee Per Kb (8)
|
||||
//MinDepth (4)
|
||||
//LockTime (4)
|
||||
//FeePayer (1)
|
||||
//DeliveryPkScript (final delivery)
|
||||
// First byte length then pkscript
|
||||
//ChangePkScript (change for extra from inputs)
|
||||
// First byte length then pkscript
|
||||
//CommitSig
|
||||
// First byte length then sig
|
||||
//Inputs: Create the TxIns
|
||||
// First byte is number of inputs
|
||||
// For each input, it's 32bytes txin & 4bytes index
|
||||
// ReservationID (8)
|
||||
// Channel Type (1)
|
||||
// Funding Amount (8)
|
||||
// Revocation Hash (20)
|
||||
// Commitment Pubkey (32)
|
||||
// Reserve Amount (8)
|
||||
// Minimum Transaction Fee Per Kb (8)
|
||||
// MinDepth (4)
|
||||
// LockTime (4)
|
||||
// FeePayer (1)
|
||||
// DeliveryPkScript (final delivery)
|
||||
// First byte length then pkscript
|
||||
// ChangePkScript (change for extra from inputs)
|
||||
// First byte length then pkscript
|
||||
// CommitSig
|
||||
// First byte length then sig
|
||||
// Inputs: Create the TxIns
|
||||
// First byte is number of inputs
|
||||
// For each input, it's 32bytes txin & 4bytes index
|
||||
err := readElements(r,
|
||||
&c.ReservationID,
|
||||
&c.ChannelType,
|
||||
@ -80,27 +80,27 @@ func (c *FundingResponse) Decode(r io.Reader, pver uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new FundingResponse
|
||||
// Creates a new FundingResponse
|
||||
func NewFundingResponse() *FundingResponse {
|
||||
return &FundingResponse{}
|
||||
}
|
||||
|
||||
//Serializes the item from the FundingResponse struct
|
||||
//Writes the data to w
|
||||
// Serializes the item from the FundingResponse struct
|
||||
// Writes the data to w
|
||||
func (c *FundingResponse) Encode(w io.Writer, pver uint32) error {
|
||||
//ReservationID (8)
|
||||
//Channel Type (1)
|
||||
//Funding Amount (8)
|
||||
//Revocation Hash (20)
|
||||
//Commitment Pubkey (32)
|
||||
//Reserve Amount (8)
|
||||
//Minimum Transaction Fee Per Kb (8)
|
||||
//LockTime (4)
|
||||
//FeePayer (1)
|
||||
//DeliveryPkScript (final delivery)
|
||||
//ChangePkScript (change for extra from inputs)
|
||||
//CommitSig
|
||||
//Inputs
|
||||
// ReservationID (8)
|
||||
// Channel Type (1)
|
||||
// Funding Amount (8)
|
||||
// Revocation Hash (20)
|
||||
// Commitment Pubkey (32)
|
||||
// Reserve Amount (8)
|
||||
// Minimum Transaction Fee Per Kb (8)
|
||||
// LockTime (4)
|
||||
// FeePayer (1)
|
||||
// DeliveryPkScript (final delivery)
|
||||
// ChangePkScript (change for extra from inputs)
|
||||
// CommitSig
|
||||
// Inputs
|
||||
err := writeElements(w,
|
||||
c.ReservationID,
|
||||
c.ChannelType,
|
||||
@ -128,15 +128,15 @@ func (c *FundingResponse) Command() uint32 {
|
||||
}
|
||||
|
||||
func (c *FundingResponse) MaxPayloadLength(uint32) uint32 {
|
||||
//86 (base size) + 26 (pkscript) + 26 (pkscript) + 74sig + 1 (numTxes) + 127*36(127 inputs * sha256+idx)
|
||||
// 86 (base size) + 26 (pkscript) + 26 (pkscript) + 74sig + 1 (numTxes) + 127*36(127 inputs * sha256+idx)
|
||||
return 4785
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *FundingResponse) Validate() error {
|
||||
var err error
|
||||
|
||||
//No negative values
|
||||
// No negative values
|
||||
if c.ResponderFundingAmount < 0 {
|
||||
return fmt.Errorf("ResponderFundingAmount cannot be negative")
|
||||
}
|
||||
@ -149,29 +149,29 @@ func (c *FundingResponse) Validate() error {
|
||||
return fmt.Errorf("MinFeePerKb cannot be negative")
|
||||
}
|
||||
|
||||
//Validation of what makes sense...
|
||||
// Validation of what makes sense...
|
||||
if c.ResponderFundingAmount < c.ResponderReserveAmount {
|
||||
return fmt.Errorf("Reserve must be below Funding Amount")
|
||||
}
|
||||
|
||||
//Make sure there's not more than 127 inputs
|
||||
// Make sure there's not more than 127 inputs
|
||||
if len(c.Inputs) > 127 {
|
||||
return fmt.Errorf("Too many inputs")
|
||||
}
|
||||
|
||||
//Delivery PkScript is either P2SH or P2PKH
|
||||
// Delivery PkScript is either P2SH or P2PKH
|
||||
err = ValidatePkScript(c.DeliveryPkScript)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//Change PkScript is either P2SH or P2PKH
|
||||
// Change PkScript is either P2SH or P2PKH
|
||||
err = ValidatePkScript(c.ChangePkScript)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//We're good!
|
||||
// We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -6,10 +6,10 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
//Need to do this here
|
||||
// Need to do this here
|
||||
_ = copy(revocationHash[:], revocationHashBytes)
|
||||
|
||||
//funding response
|
||||
// funding response
|
||||
fundingResponse = &FundingResponse{
|
||||
ChannelType: uint8(1),
|
||||
ReservationID: uint64(12345678),
|
||||
@ -17,7 +17,7 @@ var (
|
||||
ResponderReserveAmount: btcutil.Amount(131072),
|
||||
MinFeePerKb: btcutil.Amount(20000),
|
||||
MinDepth: uint32(6),
|
||||
LockTime: uint32(4320), //30 block-days
|
||||
LockTime: uint32(4320), // 30 block-days
|
||||
FeePayer: uint8(1),
|
||||
RevocationHash: revocationHash,
|
||||
Pubkey: pubKey,
|
||||
@ -31,19 +31,19 @@ var (
|
||||
)
|
||||
|
||||
func TestFundingResponseEncodeDecode(t *testing.T) {
|
||||
//All of these types being passed are of the message interface type
|
||||
//Test serialization, runs: message.Encode(b, 0)
|
||||
//Returns bytes
|
||||
//Compares the expected serialized string from the original
|
||||
// All of these types being passed are of the message interface type
|
||||
// Test serialization, runs: message.Encode(b, 0)
|
||||
// Returns bytes
|
||||
// Compares the expected serialized string from the original
|
||||
s := SerializeTest(t, fundingResponse, fundingResponseSerializedString, filename)
|
||||
|
||||
//Test deserialization, runs: message.Decode(s, 0)
|
||||
//Makes sure the deserialized struct is the same as the original
|
||||
// Test deserialization, runs: message.Decode(s, 0)
|
||||
// Makes sure the deserialized struct is the same as the original
|
||||
newMessage := NewFundingResponse()
|
||||
DeserializeTest(t, s, newMessage, fundingResponse)
|
||||
|
||||
//Test message using Message interface
|
||||
//Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
//Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
// Test message using Message interface
|
||||
// Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
// Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
MessageSerializeDeserializeTest(t, fundingResponse, fundingResponseSerializedMessage)
|
||||
}
|
||||
|
@ -9,18 +9,18 @@ import (
|
||||
type FundingSignAccept struct {
|
||||
ReservationID uint64
|
||||
|
||||
CommitSig *btcec.Signature //Requester's Commitment
|
||||
CommitSig *btcec.Signature // Requester's Commitment
|
||||
FundingTXSigs []*btcec.Signature
|
||||
}
|
||||
|
||||
func (c *FundingSignAccept) Decode(r io.Reader, pver uint32) error {
|
||||
//ReservationID (8)
|
||||
//CommitSig (73)
|
||||
// First byte length then sig
|
||||
//FundingTXSigs
|
||||
// First byte is number of FundingTxSigs
|
||||
// Sorted list of the requester's input signatures
|
||||
// (originally provided in the Funding Request)
|
||||
// ReservationID (8)
|
||||
// CommitSig (73)
|
||||
// First byte length then sig
|
||||
// FundingTXSigs
|
||||
// First byte is number of FundingTxSigs
|
||||
// Sorted list of the requester's input signatures
|
||||
// (originally provided in the Funding Request)
|
||||
err := readElements(r,
|
||||
&c.ReservationID,
|
||||
&c.CommitSig,
|
||||
@ -32,17 +32,17 @@ func (c *FundingSignAccept) Decode(r io.Reader, pver uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new FundingSignAccept
|
||||
// Creates a new FundingSignAccept
|
||||
func NewFundingSignAccept() *FundingSignAccept {
|
||||
return &FundingSignAccept{}
|
||||
}
|
||||
|
||||
//Serializes the item from the FundingSignAccept struct
|
||||
//Writes the data to w
|
||||
// Serializes the item from the FundingSignAccept struct
|
||||
// Writes the data to w
|
||||
func (c *FundingSignAccept) Encode(w io.Writer, pver uint32) error {
|
||||
//ReservationID
|
||||
//CommitSig
|
||||
//FundingTxSigs
|
||||
// ReservationID
|
||||
// CommitSig
|
||||
// FundingTxSigs
|
||||
err := writeElements(w,
|
||||
c.ReservationID,
|
||||
c.CommitSig,
|
||||
@ -59,13 +59,13 @@ func (c *FundingSignAccept) Command() uint32 {
|
||||
}
|
||||
|
||||
func (c *FundingSignAccept) MaxPayloadLength(uint32) uint32 {
|
||||
//8 (base size) + 73 + (73maxSigSize*127maxInputs)
|
||||
// 8 (base size) + 73 + (73maxSigSize*127maxInputs)
|
||||
return 9352
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *FundingSignAccept) Validate() error {
|
||||
//We're good!
|
||||
// We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
//funding sign accept
|
||||
// funding sign accept
|
||||
fundingSignAccept = &FundingSignAccept{
|
||||
ReservationID: uint64(12345678),
|
||||
CommitSig: commitSig,
|
||||
@ -16,19 +16,19 @@ var (
|
||||
)
|
||||
|
||||
func TestFundingSignAcceptEncodeDecode(t *testing.T) {
|
||||
//All of these types being passed are of the message interface type
|
||||
//Test serialization, runs: message.Encode(b, 0)
|
||||
//Returns bytes
|
||||
//Compares the expected serialized string from the original
|
||||
// All of these types being passed are of the message interface type
|
||||
// Test serialization, runs: message.Encode(b, 0)
|
||||
// Returns bytes
|
||||
// Compares the expected serialized string from the original
|
||||
s := SerializeTest(t, fundingSignAccept, fundingSignAcceptSerializedString, filename)
|
||||
|
||||
//Test deserialization, runs: message.Decode(s, 0)
|
||||
//Makes sure the deserialized struct is the same as the original
|
||||
// Test deserialization, runs: message.Decode(s, 0)
|
||||
// Makes sure the deserialized struct is the same as the original
|
||||
newMessage := NewFundingSignAccept()
|
||||
DeserializeTest(t, s, newMessage, fundingSignAccept)
|
||||
|
||||
//Test message using Message interface
|
||||
//Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
//Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
// Test message using Message interface
|
||||
// Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
// Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
MessageSerializeDeserializeTest(t, fundingSignAccept, fundingSignAcceptSerializedMessage)
|
||||
}
|
||||
|
@ -15,12 +15,12 @@ type FundingSignComplete struct {
|
||||
}
|
||||
|
||||
func (c *FundingSignComplete) Decode(r io.Reader, pver uint32) error {
|
||||
//ReservationID (8)
|
||||
//TxID (32)
|
||||
//FundingTXSigs
|
||||
// First byte is number of FundingTxSigs
|
||||
// Sorted list of the requester's input signatures
|
||||
// (originally provided in the Funding Request)
|
||||
// ReservationID (8)
|
||||
// TxID (32)
|
||||
// FundingTXSigs
|
||||
// First byte is number of FundingTxSigs
|
||||
// Sorted list of the requester's input signatures
|
||||
// (originally provided in the Funding Request)
|
||||
err := readElements(r,
|
||||
&c.ReservationID,
|
||||
&c.TxID,
|
||||
@ -32,13 +32,13 @@ func (c *FundingSignComplete) Decode(r io.Reader, pver uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new FundingSignComplete
|
||||
// Creates a new FundingSignComplete
|
||||
func NewFundingSignComplete() *FundingSignComplete {
|
||||
return &FundingSignComplete{}
|
||||
}
|
||||
|
||||
//Serializes the item from the FundingSignComplete struct
|
||||
//Writes the data to w
|
||||
// Serializes the item from the FundingSignComplete struct
|
||||
// Writes the data to w
|
||||
func (c *FundingSignComplete) Encode(w io.Writer, pver uint32) error {
|
||||
err := writeElements(w,
|
||||
c.ReservationID,
|
||||
@ -56,13 +56,13 @@ func (c *FundingSignComplete) Command() uint32 {
|
||||
}
|
||||
|
||||
func (c *FundingSignComplete) MaxPayloadLength(uint32) uint32 {
|
||||
//8 (base size) + 32 + (73maxSigSize*127maxInputs)
|
||||
// 8 (base size) + 32 + (73maxSigSize*127maxInputs)
|
||||
return 9311
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *FundingSignComplete) Validate() error {
|
||||
//We're good!
|
||||
// We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
//funding response
|
||||
// funding response
|
||||
fundingSignComplete = &FundingSignComplete{
|
||||
ReservationID: uint64(12345678),
|
||||
TxID: txid,
|
||||
@ -16,19 +16,19 @@ var (
|
||||
)
|
||||
|
||||
func TestFundingSignCompleteEncodeDecode(t *testing.T) {
|
||||
//All of these types being passed are of the message interface type
|
||||
//Test serialization, runs: message.Encode(b, 0)
|
||||
//Returns bytes
|
||||
//Compares the expected serialized string from the original
|
||||
// All of these types being passed are of the message interface type
|
||||
// Test serialization, runs: message.Encode(b, 0)
|
||||
// Returns bytes
|
||||
// Compares the expected serialized string from the original
|
||||
s := SerializeTest(t, fundingSignComplete, fundingSignCompleteSerializedString, filename)
|
||||
|
||||
//Test deserialization, runs: message.Decode(s, 0)
|
||||
//Makes sure the deserialized struct is the same as the original
|
||||
// Test deserialization, runs: message.Decode(s, 0)
|
||||
// Makes sure the deserialized struct is the same as the original
|
||||
newMessage := NewFundingSignComplete()
|
||||
DeserializeTest(t, s, newMessage, fundingSignComplete)
|
||||
|
||||
//Test message using Message interface
|
||||
//Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
//Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
// Test message using Message interface
|
||||
// Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
// Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
MessageSerializeDeserializeTest(t, fundingSignComplete, fundingSignCompleteSerializedMessage)
|
||||
}
|
||||
|
@ -11,8 +11,8 @@ type HTLCAddAccept struct {
|
||||
}
|
||||
|
||||
func (c *HTLCAddAccept) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//HTLCKey(8)
|
||||
// ChannelID(8)
|
||||
// HTLCKey(8)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.HTLCKey,
|
||||
@ -24,13 +24,13 @@ func (c *HTLCAddAccept) Decode(r io.Reader, pver uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new HTLCAddAccept
|
||||
// Creates a new HTLCAddAccept
|
||||
func NewHTLCAddAccept() *HTLCAddAccept {
|
||||
return &HTLCAddAccept{}
|
||||
}
|
||||
|
||||
//Serializes the item from the HTLCAddAccept struct
|
||||
//Writes the data to w
|
||||
// Serializes the item from the HTLCAddAccept struct
|
||||
// Writes the data to w
|
||||
func (c *HTLCAddAccept) Encode(w io.Writer, pver uint32) error {
|
||||
err := writeElements(w,
|
||||
c.ChannelID,
|
||||
@ -49,13 +49,13 @@ func (c *HTLCAddAccept) Command() uint32 {
|
||||
}
|
||||
|
||||
func (c *HTLCAddAccept) MaxPayloadLength(uint32) uint32 {
|
||||
//16 base size
|
||||
// 16 base size
|
||||
return 16
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *HTLCAddAccept) Validate() error {
|
||||
//We're good!
|
||||
// We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -14,19 +14,19 @@ var (
|
||||
)
|
||||
|
||||
func TestHTLCAddAcceptEncodeDecode(t *testing.T) {
|
||||
//All of these types being passed are of the message interface type
|
||||
//Test serialization, runs: message.Encode(b, 0)
|
||||
//Returns bytes
|
||||
//Compares the expected serialized string from the original
|
||||
// All of these types being passed are of the message interface type
|
||||
// Test serialization, runs: message.Encode(b, 0)
|
||||
// Returns bytes
|
||||
// Compares the expected serialized string from the original
|
||||
s := SerializeTest(t, htlcAddAccept, htlcAddAcceptSerializedString, filename)
|
||||
|
||||
//Test deserialization, runs: message.Decode(s, 0)
|
||||
//Makes sure the deserialized struct is the same as the original
|
||||
// Test deserialization, runs: message.Decode(s, 0)
|
||||
// Makes sure the deserialized struct is the same as the original
|
||||
newMessage := NewHTLCAddAccept()
|
||||
DeserializeTest(t, s, newMessage, htlcAddAccept)
|
||||
|
||||
//Test message using Message interface
|
||||
//Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
//Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
// Test message using Message interface
|
||||
// Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
// Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
MessageSerializeDeserializeTest(t, htlcAddAccept, htlcAddAcceptSerializedMessage)
|
||||
}
|
||||
|
@ -11,11 +11,11 @@ type HTLCAddReject struct {
|
||||
}
|
||||
|
||||
func (c *HTLCAddReject) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//CommitmentHeight(8)
|
||||
//NextResponderCommitmentRevocationHash(20)
|
||||
//ResponderRevocationPreimage(20)
|
||||
//ResponderCommitSig(2+73max)
|
||||
// ChannelID(8)
|
||||
// CommitmentHeight(8)
|
||||
// NextResponderCommitmentRevocationHash(20)
|
||||
// ResponderRevocationPreimage(20)
|
||||
// ResponderCommitSig(2+73max)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.HTLCKey,
|
||||
@ -27,13 +27,13 @@ func (c *HTLCAddReject) Decode(r io.Reader, pver uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new HTLCAddReject
|
||||
// Creates a new HTLCAddReject
|
||||
func NewHTLCAddReject() *HTLCAddReject {
|
||||
return &HTLCAddReject{}
|
||||
}
|
||||
|
||||
//Serializes the item from the HTLCAddReject struct
|
||||
//Writes the data to w
|
||||
// Serializes the item from the HTLCAddReject struct
|
||||
// Writes the data to w
|
||||
func (c *HTLCAddReject) Encode(w io.Writer, pver uint32) error {
|
||||
err := writeElements(w,
|
||||
c.ChannelID,
|
||||
@ -52,13 +52,13 @@ func (c *HTLCAddReject) Command() uint32 {
|
||||
}
|
||||
|
||||
func (c *HTLCAddReject) MaxPayloadLength(uint32) uint32 {
|
||||
//16 base size
|
||||
// 16 base size
|
||||
return 16
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *HTLCAddReject) Validate() error {
|
||||
//We're good!
|
||||
// We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -14,19 +14,19 @@ var (
|
||||
)
|
||||
|
||||
func TestHTLCAddRejectEncodeDecode(t *testing.T) {
|
||||
//All of these types being passed are of the message interface type
|
||||
//Test serialization, runs: message.Encode(b, 0)
|
||||
//Returns bytes
|
||||
//Compares the expected serialized string from the original
|
||||
// All of these types being passed are of the message interface type
|
||||
// Test serialization, runs: message.Encode(b, 0)
|
||||
// Returns bytes
|
||||
// Compares the expected serialized string from the original
|
||||
s := SerializeTest(t, htlcAddReject, htlcAddRejectSerializedString, filename)
|
||||
|
||||
//Test deserialization, runs: message.Decode(s, 0)
|
||||
//Makes sure the deserialized struct is the same as the original
|
||||
// Test deserialization, runs: message.Decode(s, 0)
|
||||
// Makes sure the deserialized struct is the same as the original
|
||||
newMessage := NewHTLCAddReject()
|
||||
DeserializeTest(t, s, newMessage, htlcAddReject)
|
||||
|
||||
//Test message using Message interface
|
||||
//Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
//Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
// Test message using Message interface
|
||||
// Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
// Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
MessageSerializeDeserializeTest(t, htlcAddReject, htlcAddRejectSerializedMessage)
|
||||
}
|
||||
|
@ -5,46 +5,46 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
//Multiple Clearing Requests are possible by putting this inside an array of
|
||||
//clearing requests
|
||||
// Multiple Clearing Requests are possible by putting this inside an array of
|
||||
// clearing requests
|
||||
type HTLCAddRequest struct {
|
||||
//We can use a different data type for this if necessary...
|
||||
// We can use a different data type for this if necessary...
|
||||
ChannelID uint64
|
||||
|
||||
//ID of this request
|
||||
// ID of this request
|
||||
HTLCKey HTLCKey
|
||||
|
||||
//When the HTLC expires
|
||||
// When the HTLC expires
|
||||
Expiry uint32
|
||||
|
||||
//Amount to pay in the hop
|
||||
//Difference between hop and first item in blob is the fee to complete
|
||||
// Amount to pay in the hop
|
||||
// Difference between hop and first item in blob is the fee to complete
|
||||
Amount CreditsAmount
|
||||
|
||||
//RefundContext is for payment cancellation
|
||||
//TODO (j): not currently in use, add later
|
||||
// RefundContext is for payment cancellation
|
||||
// TODO (j): not currently in use, add later
|
||||
RefundContext HTLCKey
|
||||
|
||||
//Contract Type
|
||||
//first 4 bits is n, second for is m, in n-of-m "multisig"
|
||||
// Contract Type
|
||||
// first 4 bits is n, second for is m, in n-of-m "multisig"
|
||||
ContractType uint8
|
||||
|
||||
//Redemption Hashes
|
||||
// Redemption Hashes
|
||||
RedemptionHashes []*[20]byte
|
||||
|
||||
//Data to parse&pass on to the next node
|
||||
//Eventually, we need to make this into a group of 2 nested structs?
|
||||
// Data to parse&pass on to the next node
|
||||
// Eventually, we need to make this into a group of 2 nested structs?
|
||||
Blob []byte
|
||||
}
|
||||
|
||||
func (c *HTLCAddRequest) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//HTLCKey(8)
|
||||
//Expiry(4)
|
||||
//Amount(4)
|
||||
//ContractType(1)
|
||||
//RedemptionHashes (numOfHashes * 20 + numOfHashes)
|
||||
//Blob(2+blobsize)
|
||||
// ChannelID(8)
|
||||
// HTLCKey(8)
|
||||
// Expiry(4)
|
||||
// Amount(4)
|
||||
// ContractType(1)
|
||||
// RedemptionHashes (numOfHashes * 20 + numOfHashes)
|
||||
// Blob(2+blobsize)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.HTLCKey,
|
||||
@ -61,13 +61,13 @@ func (c *HTLCAddRequest) Decode(r io.Reader, pver uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new HTLCAddRequest
|
||||
// Creates a new HTLCAddRequest
|
||||
func NewHTLCAddRequest() *HTLCAddRequest {
|
||||
return &HTLCAddRequest{}
|
||||
}
|
||||
|
||||
//Serializes the item from the HTLCAddRequest struct
|
||||
//Writes the data to w
|
||||
// Serializes the item from the HTLCAddRequest struct
|
||||
// Writes the data to w
|
||||
func (c *HTLCAddRequest) Encode(w io.Writer, pver uint32) error {
|
||||
err := writeElements(w,
|
||||
c.ChannelID,
|
||||
@ -90,19 +90,19 @@ func (c *HTLCAddRequest) Command() uint32 {
|
||||
}
|
||||
|
||||
func (c *HTLCAddRequest) MaxPayloadLength(uint32) uint32 {
|
||||
//base size ~110, but blob can be variable.
|
||||
//shouldn't be bigger than 8K though...
|
||||
// base size ~110, but blob can be variable.
|
||||
// shouldn't be bigger than 8K though...
|
||||
return 8192
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *HTLCAddRequest) Validate() error {
|
||||
if c.Amount < 0 {
|
||||
//While fees can be negative, it's too confusing to allow
|
||||
//negative payments. Maybe for some wallets, but not this one!
|
||||
// While fees can be negative, it's too confusing to allow
|
||||
// negative payments. Maybe for some wallets, but not this one!
|
||||
return fmt.Errorf("Amount paid cannot be negative.")
|
||||
}
|
||||
//We're good!
|
||||
// We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
//Need to to do this here
|
||||
// Need to to do this here
|
||||
_ = copy(revocationHash[:], revocationHashBytes)
|
||||
_ = copy(redemptionHash[:], redemptionHashBytes)
|
||||
emptyRedemptionHashes = []*[20]byte{}
|
||||
@ -26,19 +26,19 @@ var (
|
||||
)
|
||||
|
||||
func TestHTLCAddRequestEncodeDecode(t *testing.T) {
|
||||
//All of these types being passed are of the message interface type
|
||||
//Test serialization, runs: message.Encode(b, 0)
|
||||
//Returns bytes
|
||||
//Compares the expected serialized string from the original
|
||||
// All of these types being passed are of the message interface type
|
||||
// Test serialization, runs: message.Encode(b, 0)
|
||||
// Returns bytes
|
||||
// Compares the expected serialized string from the original
|
||||
s := SerializeTest(t, htlcAddRequest, htlcAddRequestSerializedString, filename)
|
||||
|
||||
//Test deserialization, runs: message.Decode(s, 0)
|
||||
//Makes sure the deserialized struct is the same as the original
|
||||
// Test deserialization, runs: message.Decode(s, 0)
|
||||
// Makes sure the deserialized struct is the same as the original
|
||||
newMessage := NewHTLCAddRequest()
|
||||
DeserializeTest(t, s, newMessage, htlcAddRequest)
|
||||
|
||||
//Test message using Message interface
|
||||
//Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
//Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
// Test message using Message interface
|
||||
// Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
// Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
MessageSerializeDeserializeTest(t, htlcAddRequest, htlcAddRequestSerializedMessage)
|
||||
}
|
||||
|
@ -5,19 +5,19 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
//Multiple Clearing Requests are possible by putting this inside an array of
|
||||
//clearing requests
|
||||
// Multiple Clearing Requests are possible by putting this inside an array of
|
||||
// clearing requests
|
||||
type HTLCSettleAccept struct {
|
||||
//We can use a different data type for this if necessary...
|
||||
// We can use a different data type for this if necessary...
|
||||
ChannelID uint64
|
||||
|
||||
//ID of this request
|
||||
// ID of this request
|
||||
HTLCKey HTLCKey
|
||||
}
|
||||
|
||||
func (c *HTLCSettleAccept) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//HTLCKey(8)
|
||||
// ChannelID(8)
|
||||
// HTLCKey(8)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.HTLCKey,
|
||||
@ -29,13 +29,13 @@ func (c *HTLCSettleAccept) Decode(r io.Reader, pver uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new HTLCSettleAccept
|
||||
// Creates a new HTLCSettleAccept
|
||||
func NewHTLCSettleAccept() *HTLCSettleAccept {
|
||||
return &HTLCSettleAccept{}
|
||||
}
|
||||
|
||||
//Serializes the item from the HTLCSettleAccept struct
|
||||
//Writes the data to w
|
||||
// Serializes the item from the HTLCSettleAccept struct
|
||||
// Writes the data to w
|
||||
func (c *HTLCSettleAccept) Encode(w io.Writer, pver uint32) error {
|
||||
err := writeElements(w,
|
||||
c.ChannelID,
|
||||
@ -53,13 +53,13 @@ func (c *HTLCSettleAccept) Command() uint32 {
|
||||
}
|
||||
|
||||
func (c *HTLCSettleAccept) MaxPayloadLength(uint32) uint32 {
|
||||
//16
|
||||
// 16
|
||||
return 16
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *HTLCSettleAccept) Validate() error {
|
||||
//We're good!
|
||||
// We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -14,19 +14,19 @@ var (
|
||||
)
|
||||
|
||||
func TestHTLCSettleAcceptEncodeDecode(t *testing.T) {
|
||||
//All of these types being passed are of the message interface type
|
||||
//Test serialization, runs: message.Encode(b, 0)
|
||||
//Returns bytes
|
||||
//Compares the expected serialized string from the original
|
||||
// All of these types being passed are of the message interface type
|
||||
// Test serialization, runs: message.Encode(b, 0)
|
||||
// Returns bytes
|
||||
// Compares the expected serialized string from the original
|
||||
s := SerializeTest(t, htlcSettleAccept, htlcSettleAcceptSerializedString, filename)
|
||||
|
||||
//Test deserialization, runs: message.Decode(s, 0)
|
||||
//Makes sure the deserialized struct is the same as the original
|
||||
// Test deserialization, runs: message.Decode(s, 0)
|
||||
// Makes sure the deserialized struct is the same as the original
|
||||
newMessage := NewHTLCSettleAccept()
|
||||
DeserializeTest(t, s, newMessage, htlcSettleAccept)
|
||||
|
||||
//Test message using Message interface
|
||||
//Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
//Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
// Test message using Message interface
|
||||
// Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
// Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
MessageSerializeDeserializeTest(t, htlcSettleAccept, htlcSettleAcceptSerializedMessage)
|
||||
}
|
||||
|
@ -5,28 +5,28 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
//Multiple Clearing Requests are possible by putting this inside an array of
|
||||
//clearing requests
|
||||
// Multiple Clearing Requests are possible by putting this inside an array of
|
||||
// clearing requests
|
||||
type HTLCSettleRequest struct {
|
||||
//We can use a different data type for this if necessary...
|
||||
// We can use a different data type for this if necessary...
|
||||
ChannelID uint64
|
||||
|
||||
//ID of this request
|
||||
// ID of this request
|
||||
HTLCKey HTLCKey
|
||||
|
||||
//Redemption Proofs (R-Values)
|
||||
// Redemption Proofs (R-Values)
|
||||
RedemptionProofs []*[20]byte
|
||||
}
|
||||
|
||||
func (c *HTLCSettleRequest) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//HTLCKey(8)
|
||||
//Expiry(4)
|
||||
//Amount(4)
|
||||
//NextHop(20)
|
||||
//ContractType(1)
|
||||
//RedemptionHashes (numOfHashes * 20 + numOfHashes)
|
||||
//Blob(2+blobsize)
|
||||
// ChannelID(8)
|
||||
// HTLCKey(8)
|
||||
// Expiry(4)
|
||||
// Amount(4)
|
||||
// NextHop(20)
|
||||
// ContractType(1)
|
||||
// RedemptionHashes (numOfHashes * 20 + numOfHashes)
|
||||
// Blob(2+blobsize)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.HTLCKey,
|
||||
@ -39,13 +39,13 @@ func (c *HTLCSettleRequest) Decode(r io.Reader, pver uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new HTLCSettleRequest
|
||||
// Creates a new HTLCSettleRequest
|
||||
func NewHTLCSettleRequest() *HTLCSettleRequest {
|
||||
return &HTLCSettleRequest{}
|
||||
}
|
||||
|
||||
//Serializes the item from the HTLCSettleRequest struct
|
||||
//Writes the data to w
|
||||
// Serializes the item from the HTLCSettleRequest struct
|
||||
// Writes the data to w
|
||||
func (c *HTLCSettleRequest) Encode(w io.Writer, pver uint32) error {
|
||||
err := writeElements(w,
|
||||
c.ChannelID,
|
||||
@ -64,13 +64,13 @@ func (c *HTLCSettleRequest) Command() uint32 {
|
||||
}
|
||||
|
||||
func (c *HTLCSettleRequest) MaxPayloadLength(uint32) uint32 {
|
||||
//21*15+16
|
||||
// 21*15+16
|
||||
return 331
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *HTLCSettleRequest) Validate() error {
|
||||
//We're good!
|
||||
// We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
//Need to to do this here
|
||||
// Need to to do this here
|
||||
_ = copy(redemptionHash[:], redemptionHashBytes)
|
||||
emptyRedemptionProofs = []*[20]byte{}
|
||||
redemptionProofs = append(emptyRedemptionProofs, &redemptionHash)
|
||||
@ -20,19 +20,19 @@ var (
|
||||
)
|
||||
|
||||
func TestHTLCSettleRequestEncodeDecode(t *testing.T) {
|
||||
//All of these types being passed are of the message interface type
|
||||
//Test serialization, runs: message.Encode(b, 0)
|
||||
//Returns bytes
|
||||
//Compares the expected serialized string from the original
|
||||
// All of these types being passed are of the message interface type
|
||||
// Test serialization, runs: message.Encode(b, 0)
|
||||
// Returns bytes
|
||||
// Compares the expected serialized string from the original
|
||||
s := SerializeTest(t, htlcSettleRequest, htlcSettleRequestSerializedString, filename)
|
||||
|
||||
//Test deserialization, runs: message.Decode(s, 0)
|
||||
//Makes sure the deserialized struct is the same as the original
|
||||
// Test deserialization, runs: message.Decode(s, 0)
|
||||
// Makes sure the deserialized struct is the same as the original
|
||||
newMessage := NewHTLCSettleRequest()
|
||||
DeserializeTest(t, s, newMessage, htlcSettleRequest)
|
||||
|
||||
//Test message using Message interface
|
||||
//Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
//Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
// Test message using Message interface
|
||||
// Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
// Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
MessageSerializeDeserializeTest(t, htlcSettleRequest, htlcSettleRequestSerializedMessage)
|
||||
}
|
||||
|
@ -5,19 +5,19 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
//Multiple Clearing Requests are possible by putting this inside an array of
|
||||
//clearing requests
|
||||
// Multiple Clearing Requests are possible by putting this inside an array of
|
||||
// clearing requests
|
||||
type HTLCTimeoutAccept struct {
|
||||
//We can use a different data type for this if necessary...
|
||||
// We can use a different data type for this if necessary...
|
||||
ChannelID uint64
|
||||
|
||||
//ID of this request
|
||||
// ID of this request
|
||||
HTLCKey HTLCKey
|
||||
}
|
||||
|
||||
func (c *HTLCTimeoutAccept) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//HTLCKey(8)
|
||||
// ChannelID(8)
|
||||
// HTLCKey(8)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.HTLCKey,
|
||||
@ -29,13 +29,13 @@ func (c *HTLCTimeoutAccept) Decode(r io.Reader, pver uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new HTLCTimeoutAccept
|
||||
// Creates a new HTLCTimeoutAccept
|
||||
func NewHTLCTimeoutAccept() *HTLCTimeoutAccept {
|
||||
return &HTLCTimeoutAccept{}
|
||||
}
|
||||
|
||||
//Serializes the item from the HTLCTimeoutAccept struct
|
||||
//Writes the data to w
|
||||
// Serializes the item from the HTLCTimeoutAccept struct
|
||||
// Writes the data to w
|
||||
func (c *HTLCTimeoutAccept) Encode(w io.Writer, pver uint32) error {
|
||||
err := writeElements(w,
|
||||
c.ChannelID,
|
||||
@ -53,13 +53,13 @@ func (c *HTLCTimeoutAccept) Command() uint32 {
|
||||
}
|
||||
|
||||
func (c *HTLCTimeoutAccept) MaxPayloadLength(uint32) uint32 {
|
||||
//16
|
||||
// 16
|
||||
return 16
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *HTLCTimeoutAccept) Validate() error {
|
||||
//We're good!
|
||||
// We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -14,19 +14,19 @@ var (
|
||||
)
|
||||
|
||||
func TestHTLCTimeoutAcceptEncodeDecode(t *testing.T) {
|
||||
//All of these types being passed are of the message interface type
|
||||
//Test serialization, runs: message.Encode(b, 0)
|
||||
//Returns bytes
|
||||
//Compares the expected serialized string from the original
|
||||
// All of these types being passed are of the message interface type
|
||||
// Test serialization, runs: message.Encode(b, 0)
|
||||
// Returns bytes
|
||||
// Compares the expected serialized string from the original
|
||||
s := SerializeTest(t, htlcTimeoutAccept, htlcTimeoutAcceptSerializedString, filename)
|
||||
|
||||
//Test deserialization, runs: message.Decode(s, 0)
|
||||
//Makes sure the deserialized struct is the same as the original
|
||||
// Test deserialization, runs: message.Decode(s, 0)
|
||||
// Makes sure the deserialized struct is the same as the original
|
||||
newMessage := NewHTLCTimeoutAccept()
|
||||
DeserializeTest(t, s, newMessage, htlcTimeoutAccept)
|
||||
|
||||
//Test message using Message interface
|
||||
//Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
//Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
// Test message using Message interface
|
||||
// Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
// Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
MessageSerializeDeserializeTest(t, htlcTimeoutAccept, htlcTimeoutAcceptSerializedMessage)
|
||||
}
|
||||
|
@ -5,19 +5,19 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
//Multiple Clearing Requests are possible by putting this inside an array of
|
||||
//clearing requests
|
||||
// Multiple Clearing Requests are possible by putting this inside an array of
|
||||
// clearing requests
|
||||
type HTLCTimeoutRequest struct {
|
||||
//We can use a different data type for this if necessary...
|
||||
// We can use a different data type for this if necessary...
|
||||
ChannelID uint64
|
||||
|
||||
//ID of this request
|
||||
// ID of this request
|
||||
HTLCKey HTLCKey
|
||||
}
|
||||
|
||||
func (c *HTLCTimeoutRequest) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//HTLCKey(8)
|
||||
// ChannelID(8)
|
||||
// HTLCKey(8)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.HTLCKey,
|
||||
@ -29,13 +29,13 @@ func (c *HTLCTimeoutRequest) Decode(r io.Reader, pver uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new HTLCTimeoutRequest
|
||||
// Creates a new HTLCTimeoutRequest
|
||||
func NewHTLCTimeoutRequest() *HTLCTimeoutRequest {
|
||||
return &HTLCTimeoutRequest{}
|
||||
}
|
||||
|
||||
//Serializes the item from the HTLCTimeoutRequest struct
|
||||
//Writes the data to w
|
||||
// Serializes the item from the HTLCTimeoutRequest struct
|
||||
// Writes the data to w
|
||||
func (c *HTLCTimeoutRequest) Encode(w io.Writer, pver uint32) error {
|
||||
err := writeElements(w,
|
||||
c.ChannelID,
|
||||
@ -53,13 +53,13 @@ func (c *HTLCTimeoutRequest) Command() uint32 {
|
||||
}
|
||||
|
||||
func (c *HTLCTimeoutRequest) MaxPayloadLength(uint32) uint32 {
|
||||
//16
|
||||
// 16
|
||||
return 16
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *HTLCTimeoutRequest) Validate() error {
|
||||
//We're good!
|
||||
// We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -14,19 +14,19 @@ var (
|
||||
)
|
||||
|
||||
func TestHTLCTimeoutRequestEncodeDecode(t *testing.T) {
|
||||
//All of these types being passed are of the message interface type
|
||||
//Test serialization, runs: message.Encode(b, 0)
|
||||
//Returns bytes
|
||||
//Compares the expected serialized string from the original
|
||||
// All of these types being passed are of the message interface type
|
||||
// Test serialization, runs: message.Encode(b, 0)
|
||||
// Returns bytes
|
||||
// Compares the expected serialized string from the original
|
||||
s := SerializeTest(t, htlcTimeoutRequest, htlcTimeoutRequestSerializedString, filename)
|
||||
|
||||
//Test deserialization, runs: message.Decode(s, 0)
|
||||
//Makes sure the deserialized struct is the same as the original
|
||||
// Test deserialization, runs: message.Decode(s, 0)
|
||||
// Makes sure the deserialized struct is the same as the original
|
||||
newMessage := NewHTLCTimeoutRequest()
|
||||
DeserializeTest(t, s, newMessage, htlcTimeoutRequest)
|
||||
|
||||
//Test message using Message interface
|
||||
//Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
//Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
// Test message using Message interface
|
||||
// Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3)
|
||||
// Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3)
|
||||
MessageSerializeDeserializeTest(t, htlcTimeoutRequest, htlcTimeoutRequestSerializedMessage)
|
||||
}
|
||||
|
140
lnwire/lnwire.go
140
lnwire/lnwire.go
@ -13,31 +13,31 @@ import (
|
||||
|
||||
var MAX_SLICE_LENGTH = 65535
|
||||
|
||||
//Actual pkScript, not redeemScript
|
||||
// Actual pkScript, not redeemScript
|
||||
type PkScript []byte
|
||||
|
||||
type HTLCKey uint64
|
||||
type CommitHeight uint64
|
||||
|
||||
//Subsatoshi amount (Micro-Satoshi, 1/1000th)
|
||||
//Should be a signed int to account for negative fees
|
||||
//
|
||||
//"In any science-fiction movie, anywhere in the galaxy, currency is referred
|
||||
//to as 'credits.'"
|
||||
// --Sam Humphries. Ebert, Roger (1999). Ebert's bigger little movie
|
||||
// glossary. Andrews McMeel. p. 172.
|
||||
//
|
||||
//https://en.wikipedia.org/wiki/List_of_fictional_currencies
|
||||
//https://en.wikipedia.org/wiki/Fictional_currency#Trends_in_the_use_of_fictional_currencies
|
||||
//http://tvtropes.org/pmwiki/pmwiki.php/Main/WeWillSpendCreditsInTheFuture
|
||||
type CreditsAmount int32 //Credits (XCB, accountants should use XCB :^)
|
||||
//US Display format: 1 BTC = 100,000,000'000 XCB
|
||||
//Or in BTC = 1.00000000'000
|
||||
// Subsatoshi amount (Micro-Satoshi, 1/1000th)
|
||||
// Should be a signed int to account for negative fees
|
||||
//
|
||||
// "In any science-fiction movie, anywhere in the galaxy, currency is referred
|
||||
// to as 'credits.'"
|
||||
// --Sam Humphries. Ebert, Roger (1999). Ebert's bigger little movie
|
||||
// glossary. Andrews McMeel. p. 172.
|
||||
//
|
||||
// https:// en.wikipedia.org/wiki/List_of_fictional_currencies
|
||||
// https:// en.wikipedia.org/wiki/Fictional_currency#Trends_in_the_use_of_fictional_currencies
|
||||
// http:// tvtropes.org/pmwiki/pmwiki.php/Main/WeWillSpendCreditsInTheFuture
|
||||
type CreditsAmount int32 // Credits (XCB, accountants should use XCB :^)
|
||||
// US Display format: 1 BTC = 100,000,000'000 XCB
|
||||
// Or in BTC = 1.00000000'000
|
||||
|
||||
//Writes the big endian representation of element
|
||||
//Unified function to call when writing different types
|
||||
//Pre-allocate a byte-array of the correct size for cargo-cult security
|
||||
//More copies but whatever...
|
||||
// Writes the big endian representation of element
|
||||
// Unified function to call when writing different types
|
||||
// Pre-allocate a byte-array of the correct size for cargo-cult security
|
||||
// More copies but whatever...
|
||||
func writeElement(w io.Writer, element interface{}) error {
|
||||
var err error
|
||||
switch e := element.(type) {
|
||||
@ -107,12 +107,12 @@ func writeElement(w io.Writer, element interface{}) error {
|
||||
if numItems > 65535 {
|
||||
return fmt.Errorf("Too many []uint64s")
|
||||
}
|
||||
//Write the size
|
||||
// Write the size
|
||||
err = writeElement(w, uint16(numItems))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//Write the data
|
||||
// Write the data
|
||||
for i := 0; i < numItems; i++ {
|
||||
err = writeElement(w, e[i])
|
||||
if err != nil {
|
||||
@ -125,12 +125,12 @@ func writeElement(w io.Writer, element interface{}) error {
|
||||
if numSigs > 127 {
|
||||
return fmt.Errorf("Too many signatures!")
|
||||
}
|
||||
//Write the size
|
||||
// Write the size
|
||||
err = writeElement(w, uint8(numSigs))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//Write the data
|
||||
// Write the data
|
||||
for i := 0; i < numSigs; i++ {
|
||||
err = writeElement(w, e[i])
|
||||
if err != nil {
|
||||
@ -144,12 +144,12 @@ func writeElement(w io.Writer, element interface{}) error {
|
||||
if sigLength > 73 {
|
||||
return fmt.Errorf("Signature too long!")
|
||||
}
|
||||
//Write the size
|
||||
// Write the size
|
||||
err = writeElement(w, uint8(sigLength))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//Write the data
|
||||
// Write the data
|
||||
_, err = w.Write(sig)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -162,13 +162,13 @@ func writeElement(w io.Writer, element interface{}) error {
|
||||
}
|
||||
return nil
|
||||
case []*[20]byte:
|
||||
//Get size of slice and dump in slice
|
||||
// Get size of slice and dump in slice
|
||||
sliceSize := len(e)
|
||||
err = writeElement(w, uint16(sliceSize))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//Write in each sequentially
|
||||
// Write in each sequentially
|
||||
for _, element := range e {
|
||||
err = writeElement(w, &element)
|
||||
if err != nil {
|
||||
@ -200,12 +200,12 @@ func writeElement(w io.Writer, element interface{}) error {
|
||||
if sliceLength > MAX_SLICE_LENGTH {
|
||||
return fmt.Errorf("Slice length too long!")
|
||||
}
|
||||
//Write the size
|
||||
// Write the size
|
||||
err = writeElement(w, uint16(sliceLength))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//Write the data
|
||||
// Write the data
|
||||
_, err = w.Write(e)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -213,16 +213,16 @@ func writeElement(w io.Writer, element interface{}) error {
|
||||
return nil
|
||||
case PkScript:
|
||||
scriptLength := len(e)
|
||||
//Make sure it's P2PKH or P2SH size or less
|
||||
// Make sure it's P2PKH or P2SH size or less
|
||||
if scriptLength > 25 {
|
||||
return fmt.Errorf("PkScript too long!")
|
||||
}
|
||||
//Write the size (1-byte)
|
||||
// Write the size (1-byte)
|
||||
err = writeElement(w, uint8(scriptLength))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//Write the data
|
||||
// Write the data
|
||||
_, err = w.Write(e)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -233,19 +233,19 @@ func writeElement(w io.Writer, element interface{}) error {
|
||||
if strlen > 65535 {
|
||||
return fmt.Errorf("String too long!")
|
||||
}
|
||||
//Write the size (2-bytes)
|
||||
// Write the size (2-bytes)
|
||||
err = writeElement(w, uint16(strlen))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//Write the data
|
||||
// Write the data
|
||||
_, err = w.Write([]byte(e))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case []*wire.TxIn:
|
||||
//Append the unsigned(!!!) txins
|
||||
//Write the size (1-byte)
|
||||
// Append the unsigned(!!!) txins
|
||||
// Write the size (1-byte)
|
||||
if len(e) > 127 {
|
||||
return fmt.Errorf("Too many txins")
|
||||
}
|
||||
@ -253,8 +253,8 @@ func writeElement(w io.Writer, element interface{}) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//Append the actual TxIns (Size: NumOfTxins * 36)
|
||||
//Do not include the sequence number to eliminate funny business
|
||||
// Append the actual TxIns (Size: NumOfTxins * 36)
|
||||
// Do not include the sequence number to eliminate funny business
|
||||
for _, in := range e {
|
||||
err = writeElement(w, in)
|
||||
if err != nil {
|
||||
@ -263,14 +263,14 @@ func writeElement(w io.Writer, element interface{}) error {
|
||||
}
|
||||
return nil
|
||||
case *wire.TxIn:
|
||||
//Hash
|
||||
// Hash
|
||||
var h [32]byte
|
||||
copy(h[:], e.PreviousOutPoint.Hash.Bytes())
|
||||
_, err = w.Write(h[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//Index
|
||||
// Index
|
||||
var idx [4]byte
|
||||
binary.BigEndian.PutUint32(idx[:], e.PreviousOutPoint.Index)
|
||||
_, err = w.Write(idx[:])
|
||||
@ -381,11 +381,11 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//if numItems > 65535 {
|
||||
// return fmt.Errorf("Too many items in []uint64")
|
||||
//}
|
||||
// if numItems > 65535 {
|
||||
// return fmt.Errorf("Too many items in []uint64")
|
||||
// }
|
||||
|
||||
//Read the number of items
|
||||
// Read the number of items
|
||||
var items []uint64
|
||||
for i := uint16(0); i < numItems; i++ {
|
||||
var item uint64
|
||||
@ -407,7 +407,7 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
return fmt.Errorf("Too many signatures!")
|
||||
}
|
||||
|
||||
//Read that number of signatures
|
||||
// Read that number of signatures
|
||||
var sigs []*btcec.Signature
|
||||
for i := uint8(0); i < numSigs; i++ {
|
||||
sig := new(btcec.Signature)
|
||||
@ -430,7 +430,7 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
return fmt.Errorf("Signature too long!")
|
||||
}
|
||||
|
||||
//Read the sig length
|
||||
// Read the sig length
|
||||
l := io.LimitReader(r, int64(sigLength))
|
||||
sig, err := ioutil.ReadAll(l)
|
||||
if err != nil {
|
||||
@ -446,14 +446,14 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
*e = &*btcecSig
|
||||
return nil
|
||||
case *[]*[20]byte:
|
||||
//How many to read
|
||||
// How many to read
|
||||
var sliceSize uint16
|
||||
err = readElement(r, &sliceSize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var data []*[20]byte
|
||||
//Append the actual
|
||||
// Append the actual
|
||||
for i := uint16(0); i < sliceSize; i++ {
|
||||
var element [20]byte
|
||||
err = readElement(r, &element)
|
||||
@ -479,20 +479,20 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
*e = wire.BitcoinNet(binary.BigEndian.Uint32(b[:]))
|
||||
return nil
|
||||
case *[]byte:
|
||||
//Get the blob length first
|
||||
// Get the blob length first
|
||||
var blobLength uint16
|
||||
err = readElement(r, &blobLength)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//Shouldn't need to do this, since it's uint16, but we
|
||||
//might have a different value for MAX_SLICE_LENGTH...
|
||||
// Shouldn't need to do this, since it's uint16, but we
|
||||
// might have a different value for MAX_SLICE_LENGTH...
|
||||
if int(blobLength) > MAX_SLICE_LENGTH {
|
||||
return fmt.Errorf("Slice length too long!")
|
||||
}
|
||||
|
||||
//Read the slice length
|
||||
// Read the slice length
|
||||
l := io.LimitReader(r, int64(blobLength))
|
||||
*e, err = ioutil.ReadAll(l)
|
||||
if err != nil {
|
||||
@ -503,7 +503,7 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
}
|
||||
return nil
|
||||
case *PkScript:
|
||||
//Get the script length first
|
||||
// Get the script length first
|
||||
var scriptLength uint8
|
||||
err = readElement(r, &scriptLength)
|
||||
if err != nil {
|
||||
@ -514,7 +514,7 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
return fmt.Errorf("PkScript too long!")
|
||||
}
|
||||
|
||||
//Read the script length
|
||||
// Read the script length
|
||||
l := io.LimitReader(r, int64(scriptLength))
|
||||
*e, err = ioutil.ReadAll(l)
|
||||
if err != nil {
|
||||
@ -525,13 +525,13 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
}
|
||||
return nil
|
||||
case *string:
|
||||
//Get the string length first
|
||||
// Get the string length first
|
||||
var strlen uint16
|
||||
err = readElement(r, &strlen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//Read the string for the length
|
||||
// Read the string for the length
|
||||
l := io.LimitReader(r, int64(strlen))
|
||||
b, err := ioutil.ReadAll(l)
|
||||
if len(b) != int(strlen) {
|
||||
@ -543,7 +543,7 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
}
|
||||
return nil
|
||||
case *[]*wire.TxIn:
|
||||
//Read the size (1-byte number of txins)
|
||||
// Read the size (1-byte number of txins)
|
||||
var numScripts uint8
|
||||
err = readElement(r, &numScripts)
|
||||
if err != nil {
|
||||
@ -553,7 +553,7 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
return fmt.Errorf("Too many txins")
|
||||
}
|
||||
|
||||
//Append the actual TxIns
|
||||
// Append the actual TxIns
|
||||
var txins []*wire.TxIn
|
||||
for i := uint8(0); i < numScripts; i++ {
|
||||
outpoint := new(wire.OutPoint)
|
||||
@ -567,7 +567,7 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
*e = *&txins
|
||||
return nil
|
||||
case **wire.TxIn:
|
||||
//Hash
|
||||
// Hash
|
||||
var h [32]byte
|
||||
_, err = io.ReadFull(r, h[:])
|
||||
if err != nil {
|
||||
@ -578,7 +578,7 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
return err
|
||||
}
|
||||
(*e).PreviousOutPoint.Hash = *hash
|
||||
//Index
|
||||
// Index
|
||||
var idxBytes [4]byte
|
||||
_, err = io.ReadFull(r, idxBytes[:])
|
||||
if err != nil {
|
||||
@ -603,31 +603,31 @@ func readElements(r io.Reader, elements ...interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Validates whether a PkScript byte array is P2SH or P2PKH
|
||||
// Validates whether a PkScript byte array is P2SH or P2PKH
|
||||
func ValidatePkScript(pkScript PkScript) error {
|
||||
if &pkScript == nil {
|
||||
return fmt.Errorf("PkScript should not be empty!")
|
||||
}
|
||||
if len(pkScript) == 25 {
|
||||
//P2PKH
|
||||
//Begins with OP_DUP OP_HASH160 PUSHDATA(20)
|
||||
// P2PKH
|
||||
// Begins with OP_DUP OP_HASH160 PUSHDATA(20)
|
||||
if !bytes.Equal(pkScript[0:3], []byte{118, 169, 20}) ||
|
||||
//Ends with OP_EQUALVERIFY OP_CHECKSIG
|
||||
// Ends with OP_EQUALVERIFY OP_CHECKSIG
|
||||
!bytes.Equal(pkScript[23:25], []byte{136, 172}) {
|
||||
//If it's not correct, return error
|
||||
// If it's not correct, return error
|
||||
return fmt.Errorf("PkScript only allows P2SH or P2PKH")
|
||||
}
|
||||
} else if len(pkScript) == 23 {
|
||||
//P2SH
|
||||
//Begins with OP_HASH160 PUSHDATA(20)
|
||||
// P2SH
|
||||
// Begins with OP_HASH160 PUSHDATA(20)
|
||||
if !bytes.Equal(pkScript[0:2], []byte{169, 20}) ||
|
||||
//Ends with OP_EQUAL
|
||||
// Ends with OP_EQUAL
|
||||
!bytes.Equal(pkScript[22:23], []byte{135}) {
|
||||
//If it's not correct, return error
|
||||
// If it's not correct, return error
|
||||
return fmt.Errorf("PkScript only allows P2SH or P2PKH")
|
||||
}
|
||||
} else {
|
||||
//Length not 23 or 25
|
||||
// Length not 23 or 25
|
||||
return fmt.Errorf("PkScript only allows P2SH or P2PKH")
|
||||
}
|
||||
|
||||
|
@ -11,24 +11,24 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
//Common variables and functions for the message tests
|
||||
// Common variables and functions for the message tests
|
||||
|
||||
var (
|
||||
//For debugging, writes to /dev/shm/
|
||||
//Maybe in the future do it if you do "go test -v"
|
||||
// For debugging, writes to /dev/shm/
|
||||
// Maybe in the future do it if you do "go test -v"
|
||||
WRITE_FILE = true
|
||||
filename = "/dev/shm/serialized.raw"
|
||||
|
||||
//preimage: 9a2cbd088763db88dd8ba79e5726daa6aba4aa7e
|
||||
//echo -n | openssl sha256 | openssl ripemd160 | openssl sha256 | openssl ripemd160
|
||||
// preimage: 9a2cbd088763db88dd8ba79e5726daa6aba4aa7e
|
||||
// echo -n | openssl sha256 | openssl ripemd160 | openssl sha256 | openssl ripemd160
|
||||
revocationHashBytes, _ = hex.DecodeString("4132b6b48371f7b022a16eacb9b2b0ebee134d41")
|
||||
revocationHash [20]byte
|
||||
|
||||
//preimage: "hello world"
|
||||
// preimage: "hello world"
|
||||
redemptionHashBytes, _ = hex.DecodeString("5b315ebabb0d8c0d94281caa2dfee69a1a00436e")
|
||||
redemptionHash [20]byte
|
||||
|
||||
//preimage: "next hop"
|
||||
// preimage: "next hop"
|
||||
nextHopBytes, _ = hex.DecodeString("94a9ded5a30fc5944cb1e2cbcd980f30616a1440")
|
||||
nextHop [20]byte
|
||||
|
||||
@ -36,51 +36,51 @@ var (
|
||||
privKey, pubKey = btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes)
|
||||
address = pubKey
|
||||
|
||||
// Delivery PkScript
|
||||
//Privkey: f2c00ead9cbcfec63098dc0a5f152c0165aff40a2ab92feb4e24869a284c32a7
|
||||
//PKhash: n2fkWVphUzw3zSigzPsv9GuDyg9mohzKpz
|
||||
// Delivery PkScript
|
||||
// Privkey: f2c00ead9cbcfec63098dc0a5f152c0165aff40a2ab92feb4e24869a284c32a7
|
||||
// PKhash: n2fkWVphUzw3zSigzPsv9GuDyg9mohzKpz
|
||||
deliveryPkScript, _ = hex.DecodeString("76a914e8048c0fb75bdecc91ebfb99c174f4ece29ffbd488ac")
|
||||
|
||||
// Change PkScript
|
||||
//Privkey: 5b18f5049efd9d3aff1fb9a06506c0b809fb71562b6ecd02f6c5b3ab298f3b0f
|
||||
//PKhash: miky84cHvLuk6jcT6GsSbgHR8d7eZCu9Qc
|
||||
// Change PkScript
|
||||
// Privkey: 5b18f5049efd9d3aff1fb9a06506c0b809fb71562b6ecd02f6c5b3ab298f3b0f
|
||||
// PKhash: miky84cHvLuk6jcT6GsSbgHR8d7eZCu9Qc
|
||||
changePkScript, _ = hex.DecodeString("76a914238ee44bb5c8c1314dd03974a17ec6c406fdcb8388ac")
|
||||
|
||||
//echo -n | openssl sha256
|
||||
//This stuff gets reversed!!!
|
||||
// echo -n | openssl sha256
|
||||
// This stuff gets reversed!!!
|
||||
shaHash1Bytes, _ = hex.DecodeString("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
||||
shaHash1, _ = wire.NewShaHash(shaHash1Bytes)
|
||||
outpoint1 = wire.NewOutPoint(shaHash1, 0)
|
||||
//echo | openssl sha256
|
||||
//This stuff gets reversed!!!
|
||||
// echo | openssl sha256
|
||||
// This stuff gets reversed!!!
|
||||
shaHash2Bytes, _ = hex.DecodeString("01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b")
|
||||
shaHash2, _ = wire.NewShaHash(shaHash2Bytes)
|
||||
outpoint2 = wire.NewOutPoint(shaHash2, 1)
|
||||
//create inputs from outpoint1 and outpoint2
|
||||
// create inputs from outpoint1 and outpoint2
|
||||
inputs = []*wire.TxIn{wire.NewTxIn(outpoint1, nil), wire.NewTxIn(outpoint2, nil)}
|
||||
|
||||
//Commitment Signature
|
||||
// Commitment Signature
|
||||
tx = wire.NewMsgTx()
|
||||
emptybytes = new([]byte)
|
||||
sigStr, _ = txscript.RawTxInSignature(tx, 0, *emptybytes, txscript.SigHashAll, privKey)
|
||||
commitSig, _ = btcec.ParseSignature(sigStr, btcec.S256())
|
||||
|
||||
//Funding TX Sig 1
|
||||
// Funding TX Sig 1
|
||||
sig1privKeyBytes, _ = hex.DecodeString("927f5827d75dd2addeb532c0fa5ac9277565f981dd6d0d037b422be5f60bdbef")
|
||||
sig1privKey, _ = btcec.PrivKeyFromBytes(btcec.S256(), sig1privKeyBytes)
|
||||
sigStr1, _ = txscript.RawTxInSignature(tx, 0, *emptybytes, txscript.SigHashAll, sig1privKey)
|
||||
commitSig1, _ = btcec.ParseSignature(sigStr1, btcec.S256())
|
||||
//Funding TX Sig 2
|
||||
// Funding TX Sig 2
|
||||
sig2privKeyBytes, _ = hex.DecodeString("8a4ad188f6f4000495b765cfb6ffa591133a73019c45428ddd28f53bab551847")
|
||||
sig2privKey, _ = btcec.PrivKeyFromBytes(btcec.S256(), sig2privKeyBytes)
|
||||
sigStr2, _ = txscript.RawTxInSignature(tx, 0, *emptybytes, txscript.SigHashAll, sig2privKey)
|
||||
commitSig2, _ = btcec.ParseSignature(sigStr2, btcec.S256())
|
||||
//Slice of Funding TX Sigs
|
||||
// Slice of Funding TX Sigs
|
||||
ptrFundingTXSigs = append(*new([]*btcec.Signature), commitSig1, commitSig2)
|
||||
|
||||
//TxID
|
||||
// TxID
|
||||
txid = new(wire.ShaHash)
|
||||
//Reversed when displayed
|
||||
// Reversed when displayed
|
||||
txidBytes, _ = hex.DecodeString("fd95c6e5c9d5bcf9cfc7231b6a438e46c518c724d0b04b75cc8fddf84a254e3a")
|
||||
_ = copy(txid[:], txidBytes)
|
||||
)
|
||||
@ -95,12 +95,12 @@ func SerializeTest(t *testing.T, message Message, expectedString string, filenam
|
||||
t.Errorf(err.Error())
|
||||
} else {
|
||||
t.Logf("Encoded Bytes: %x\n", b.Bytes())
|
||||
//Check if we serialized correctly
|
||||
// Check if we serialized correctly
|
||||
if expectedString != hex.EncodeToString(b.Bytes()) {
|
||||
t.Error("Serialization does not match expected")
|
||||
}
|
||||
|
||||
//So I can do: hexdump -C /dev/shm/fundingRequest.raw
|
||||
// So I can do: hexdump -C /dev/shm/fundingRequest.raw
|
||||
if WRITE_FILE {
|
||||
err = ioutil.WriteFile(filename, b.Bytes(), 0644)
|
||||
if err != nil {
|
||||
@ -113,7 +113,7 @@ func SerializeTest(t *testing.T, message Message, expectedString string, filenam
|
||||
|
||||
func DeserializeTest(t *testing.T, buf *bytes.Buffer, message Message, originalMessage Message) {
|
||||
var err error
|
||||
//Make a new buffer just to be clean
|
||||
// Make a new buffer just to be clean
|
||||
c := new(bytes.Buffer)
|
||||
c.Write(buf.Bytes())
|
||||
|
||||
@ -125,7 +125,7 @@ func DeserializeTest(t *testing.T, buf *bytes.Buffer, message Message, originalM
|
||||
if !reflect.DeepEqual(message, originalMessage) {
|
||||
t.Error("Decoding does not match!")
|
||||
}
|
||||
//Show the struct
|
||||
// Show the struct
|
||||
t.Log(message.String())
|
||||
}
|
||||
}
|
||||
@ -139,7 +139,7 @@ func MessageSerializeDeserializeTest(t *testing.T, message Message, expectedStri
|
||||
if hex.EncodeToString(b.Bytes()) != expectedString {
|
||||
t.Error("Message encoding error")
|
||||
}
|
||||
//Deserialize/Decode
|
||||
// Deserialize/Decode
|
||||
c := new(bytes.Buffer)
|
||||
c.Write(b.Bytes())
|
||||
_, newMsg, _, err := ReadMessage(c, uint32(1), wire.TestNet3)
|
||||
|
@ -1,4 +1,4 @@
|
||||
//Code derived from https://github.com/btcsuite/btcd/blob/master/wire/message.go
|
||||
// Code derived from https:// github.com/btcsuite/btcd/blob/master/wire/message.go
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
@ -9,7 +9,7 @@ import (
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
)
|
||||
|
||||
// message type identifyer bytes
|
||||
// message type identifyer bytes
|
||||
const (
|
||||
MSGID_FUNDREQUEST = 0x30
|
||||
MSGID_FUNDRESPONSE = 0x31
|
||||
@ -23,52 +23,52 @@ const (
|
||||
MSGID_FWDAUTHREQ = 0x21
|
||||
)
|
||||
|
||||
//4-byte network + 4-byte message id + payload-length 4-byte
|
||||
// 4-byte network + 4-byte message id + payload-length 4-byte
|
||||
const MessageHeaderSize = 12
|
||||
|
||||
const MaxMessagePayload = 1024 * 1024 * 32 // 32MB
|
||||
const MaxMessagePayload = 1024 * 1024 * 32 // 32MB
|
||||
|
||||
const (
|
||||
//Funding channel open
|
||||
// Funding channel open
|
||||
CmdFundingRequest = uint32(200)
|
||||
CmdFundingResponse = uint32(210)
|
||||
CmdFundingSignAccept = uint32(220)
|
||||
CmdFundingSignComplete = uint32(230)
|
||||
|
||||
//Close channel
|
||||
// Close channel
|
||||
CmdCloseRequest = uint32(300)
|
||||
CmdCloseComplete = uint32(310)
|
||||
|
||||
//TODO Renumber to 1100
|
||||
//HTLC payment
|
||||
// TODO Renumber to 1100
|
||||
// HTLC payment
|
||||
CmdHTLCAddRequest = uint32(1000)
|
||||
CmdHTLCAddAccept = uint32(1010)
|
||||
CmdHTLCAddReject = uint32(1020)
|
||||
|
||||
//TODO Renumber to 1200
|
||||
//HTLC settlement
|
||||
// TODO Renumber to 1200
|
||||
// HTLC settlement
|
||||
CmdHTLCSettleRequest = uint32(1100)
|
||||
CmdHTLCSettleAccept = uint32(1110)
|
||||
|
||||
//HTLC timeout
|
||||
// HTLC timeout
|
||||
CmdHTLCTimeoutRequest = uint32(1300)
|
||||
CmdHTLCTimeoutAccept = uint32(1310)
|
||||
|
||||
//Commitments
|
||||
// Commitments
|
||||
CmdCommitSignature = uint32(2000)
|
||||
CmdCommitRevocation = uint32(2010)
|
||||
|
||||
//Error
|
||||
// Error
|
||||
CmdErrorGeneric = uint32(4000)
|
||||
)
|
||||
|
||||
//Every message has these functions:
|
||||
// Every message has these functions:
|
||||
type Message interface {
|
||||
Decode(io.Reader, uint32) error //(io, protocol version)
|
||||
Encode(io.Writer, uint32) error //(io, protocol version)
|
||||
Command() uint32 //returns ID of the message
|
||||
MaxPayloadLength(uint32) uint32 //(version) maxpayloadsize
|
||||
Validate() error //Validates the data struct
|
||||
Decode(io.Reader, uint32) error // (io, protocol version)
|
||||
Encode(io.Writer, uint32) error // (io, protocol version)
|
||||
Command() uint32 // returns ID of the message
|
||||
MaxPayloadLength(uint32) uint32 // (version) maxpayloadsize
|
||||
Validate() error // Validates the data struct
|
||||
String() string
|
||||
}
|
||||
|
||||
@ -116,10 +116,10 @@ func makeEmptyMessage(command uint32) (Message, error) {
|
||||
}
|
||||
|
||||
type messageHeader struct {
|
||||
//NOTE(j): We don't need to worry about the magic overlapping with
|
||||
//bitcoin since this is inside encrypted comms anyway, but maybe we
|
||||
//should use the XOR (^wire.TestNet3) just in case???
|
||||
magic wire.BitcoinNet //which Blockchain Technology(TM) to use
|
||||
// NOTE(j): We don't need to worry about the magic overlapping with
|
||||
// bitcoin since this is inside encrypted comms anyway, but maybe we
|
||||
// should use the XOR (^wire.TestNet3) just in case???
|
||||
magic wire.BitcoinNet // which Blockchain Technology(TM) to use
|
||||
command uint32
|
||||
length uint32
|
||||
}
|
||||
@ -145,12 +145,12 @@ func readMessageHeader(r io.Reader) (int, *messageHeader, error) {
|
||||
return n, &hdr, nil
|
||||
}
|
||||
|
||||
// discardInput reads n bytes from reader r in chunks and discards the read
|
||||
// bytes. This is used to skip payloads when various errors occur and helps
|
||||
// prevent rogue nodes from causing massive memory allocation through forging
|
||||
// header length.
|
||||
// discardInput reads n bytes from reader r in chunks and discards the read
|
||||
// bytes. This is used to skip payloads when various errors occur and helps
|
||||
// prevent rogue nodes from causing massive memory allocation through forging
|
||||
// header length.
|
||||
func discardInput(r io.Reader, n uint32) {
|
||||
maxSize := uint32(10 * 1024) //10k at a time
|
||||
maxSize := uint32(10 * 1024) // 10k at a time
|
||||
numReads := n / maxSize
|
||||
bytesRemaining := n % maxSize
|
||||
if n > 0 {
|
||||
@ -170,7 +170,7 @@ func WriteMessage(w io.Writer, msg Message, pver uint32, btcnet wire.BitcoinNet)
|
||||
|
||||
cmd := msg.Command()
|
||||
|
||||
//Encode the message payload
|
||||
// Encode the message payload
|
||||
var bw bytes.Buffer
|
||||
err := msg.Encode(&bw, pver)
|
||||
if err != nil {
|
||||
@ -179,37 +179,37 @@ func WriteMessage(w io.Writer, msg Message, pver uint32, btcnet wire.BitcoinNet)
|
||||
payload := bw.Bytes()
|
||||
lenp := len(payload)
|
||||
|
||||
//Enforce maximum overall message payload
|
||||
// Enforce maximum overall message payload
|
||||
if lenp > MaxMessagePayload {
|
||||
return totalBytes, fmt.Errorf("message payload is too large - encoded %d bytes, but maximum message payload is %d bytes", lenp, MaxMessagePayload)
|
||||
}
|
||||
|
||||
//Enforce maximum message payload on the message type
|
||||
// Enforce maximum message payload on the message type
|
||||
mpl := msg.MaxPayloadLength(pver)
|
||||
if uint32(lenp) > mpl {
|
||||
return totalBytes, fmt.Errorf("message payload is too large - encoded %d bytes, but maximum message payload of type %x is %d bytes", lenp, cmd, mpl)
|
||||
}
|
||||
|
||||
//Create header for the message
|
||||
// Create header for the message
|
||||
hdr := messageHeader{}
|
||||
hdr.magic = btcnet
|
||||
hdr.command = cmd
|
||||
hdr.length = uint32(lenp)
|
||||
|
||||
// Encode the header for the message. This is done to a buffer
|
||||
// rather than directly to the writer since writeElements doesn't
|
||||
// return the number of bytes written.
|
||||
// Encode the header for the message. This is done to a buffer
|
||||
// rather than directly to the writer since writeElements doesn't
|
||||
// return the number of bytes written.
|
||||
hw := bytes.NewBuffer(make([]byte, 0, MessageHeaderSize))
|
||||
writeElements(hw, hdr.magic, hdr.command, hdr.length)
|
||||
|
||||
//Write header
|
||||
// Write header
|
||||
n, err := w.Write(hw.Bytes())
|
||||
totalBytes += n
|
||||
if err != nil {
|
||||
return totalBytes, err
|
||||
}
|
||||
|
||||
//Write payload
|
||||
// Write payload
|
||||
n, err = w.Write(payload)
|
||||
totalBytes += n
|
||||
if err != nil {
|
||||
@ -227,18 +227,18 @@ func ReadMessage(r io.Reader, pver uint32, btcnet wire.BitcoinNet) (int, Message
|
||||
return totalBytes, nil, nil, err
|
||||
}
|
||||
|
||||
//Enforce maximum message payload
|
||||
// Enforce maximum message payload
|
||||
if hdr.length > MaxMessagePayload {
|
||||
return totalBytes, nil, nil, fmt.Errorf("message payload is too large - header indicates %d bytes, but max message payload is %d bytes.", hdr.length, MaxMessagePayload)
|
||||
}
|
||||
|
||||
//Check for messages in the wrong bitcoin network
|
||||
// Check for messages in the wrong bitcoin network
|
||||
if hdr.magic != btcnet {
|
||||
discardInput(r, hdr.length)
|
||||
return totalBytes, nil, nil, fmt.Errorf("message from other network [%v]", hdr.magic)
|
||||
}
|
||||
|
||||
//Create struct of appropriate message type based on the command
|
||||
// Create struct of appropriate message type based on the command
|
||||
command := hdr.command
|
||||
msg, err := makeEmptyMessage(command)
|
||||
if err != nil {
|
||||
@ -246,14 +246,14 @@ func ReadMessage(r io.Reader, pver uint32, btcnet wire.BitcoinNet) (int, Message
|
||||
return totalBytes, nil, nil, fmt.Errorf("ReadMessage %s", err.Error())
|
||||
}
|
||||
|
||||
//Check for maximum length based on the message type
|
||||
// Check for maximum length based on the message type
|
||||
mpl := msg.MaxPayloadLength(pver)
|
||||
if hdr.length > mpl {
|
||||
discardInput(r, hdr.length)
|
||||
return totalBytes, nil, nil, fmt.Errorf("payload exceeds max length. indicates %v bytes, but max of message type %v is %v.", hdr.length, command, mpl)
|
||||
}
|
||||
|
||||
//Read payload
|
||||
// Read payload
|
||||
payload := make([]byte, hdr.length)
|
||||
n, err = io.ReadFull(r, payload)
|
||||
totalBytes += n
|
||||
@ -261,19 +261,19 @@ func ReadMessage(r io.Reader, pver uint32, btcnet wire.BitcoinNet) (int, Message
|
||||
return totalBytes, nil, nil, err
|
||||
}
|
||||
|
||||
//Unmarshal message
|
||||
// Unmarshal message
|
||||
pr := bytes.NewBuffer(payload)
|
||||
err = msg.Decode(pr, pver)
|
||||
if err != nil {
|
||||
return totalBytes, nil, nil, err
|
||||
}
|
||||
|
||||
//Validate the data
|
||||
// Validate the data
|
||||
err = msg.Validate()
|
||||
if err != nil {
|
||||
return totalBytes, nil, nil, err
|
||||
}
|
||||
|
||||
//We're good!
|
||||
// We're good!
|
||||
return totalBytes, msg, payload, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user