Started working on state machine
* Added description in lnwire/README.md for state machine
* Figured out mutex stuff...
* Started the State Machine (using dummy functions for net/db)
* Minor corrections in wire protocol (changed some names/types)
- Renamed StagingID to HTLCKey of type HTLCKey (uint64)
This commit is contained in:
1 parent
0c304cbb2f
commit
1981001a29
20 files changed
+727
-80
No files matched your search
@@ -56,3 +56,184 @@ Close Complete
|
||||
Returns the Txid and sig as a courtesy. The counterparty might not send this if
|
||||
they're being non-cooperative.
|
||||
|
||||
Commitments and HTLCs
|
||||
=====================
|
||||
|
||||
This is designed to be non-blocking where there can be multiple Commitments per
|
||||
person and the Commitments do not need to match. A HTLC is only believed to be
|
||||
added when it's in both parties' most recent Commitment (same with
|
||||
timeout/settle).
|
||||
|
||||
As a result, there can easily be hundreds of state updates/payments per second
|
||||
per channel.
|
||||
|
||||
Commitment States
|
||||
-----------------
|
||||
|
||||
Commitments:
|
||||
1. HTLCs, can be modified. Any add/settlement/timeout/etc. gets added to
|
||||
staging.
|
||||
2. Signed, only one signed state at a time can exist per party. Takes HTLCs
|
||||
staging and locks it in, can now be broadcast on-chain by the counterparty.
|
||||
3. Completed and Revoked, other party sends their revocation accepting this
|
||||
Commitment. Sending a revocation means you *ACCEPT* the Commitment. There
|
||||
should never be a case where a Commitment Signature happens and the client
|
||||
refusees to revoke -- instead the client should immediately close out the
|
||||
channel.
|
||||
4. Deprecated, a commitment is old, marked as deprecated when there is a new
|
||||
Commitment and this one is revoked. These commitments never be broadcasted.
|
||||
5. Invalid, close out channel immediately.
|
||||
|
||||
There can be multiple commitments going at a time per party (currently limits a
|
||||
total of 16 possible in-flight that can be broadcast for sanity, but there's no
|
||||
real limit).
|
||||
|
||||
For validity, all you do is ensure that the changes from the old commitment are
|
||||
legit (based on your HTLC/staging data)
|
||||
COMMIT\_STAGING
|
||||
COMMIT\_SIGNED
|
||||
COMMIT\_COMPLETE
|
||||
|
||||
Messages:
|
||||
CommitSignature: Signature to establish COMMIT\_SIGNED state
|
||||
CommitRevocation: Revoke prior states
|
||||
|
||||
ADD HTLCs
|
||||
---------
|
||||
|
||||
Requester Add HTLC states (Adding HTLCs):
|
||||
1. Pre-staged, don't know if the other person wants it
|
||||
2. Staged, both parties agree to add this HTLC. If a staging request packet is
|
||||
received, then BOTH PARTIES will have it in their next Commitment. Nothing
|
||||
is guaranteed here, but violations are treated as immediate channel closure.
|
||||
3. Signed and sent the Commitment Tx to the counterparty, one should now assume
|
||||
that there's a possibility that this HTLC will be boradcast on-chain.
|
||||
4. Completed and Revoked, *counterparty* has included this in the Commitment
|
||||
they're broadcasting and revoked their prior state. This means the
|
||||
*Requeseter* can continue to take action, since the Commitment they have,
|
||||
the HTLC doesn't exist (no payment), and the *Responder* will broadcast with
|
||||
the payment to the *Responder*. However, the *Responder* cannot treat the
|
||||
HTLC as cleared.
|
||||
5. Cleared. Both parties have signed and revoked. Responder can continue
|
||||
routing. Make sure it's included in *BOTH COMMITMENTS and ALL PREVIOUS
|
||||
REVOKED*
|
||||
6. Staging Reject, removal request, tx rejected, begin flow to reject HTLC from
|
||||
other channels, can only be sent during the *pre-staging* state
|
||||
|
||||
In the event that an HTLC stays in "Completed and Revoked" and it is timed out,
|
||||
and the counterparty refuses to add it into a new Commitment, the channel is
|
||||
*closed out on-chain*. In other words, when checking which ones to send a
|
||||
settle/timeout notification, do it for anything which is
|
||||
ADD\_SIGNING\_AND\_REVOKING, *or* ADD\_COMPLETE (AND ALL OTHER PRE-COMPLETE
|
||||
STAGES, e.g. in timeout or settlement).
|
||||
|
||||
As part of moving to any further stage, check if it's timed out.
|
||||
|
||||
If there is a request to stage and it's already staged, treat it as accepting.
|
||||
|
||||
When it has cleared and timed out, a timeout notification is sent.
|
||||
|
||||
HTLC ID numbers are uint64 and each counterparty is responsible to only make
|
||||
sequential/incremental, and each party can only make evens/odds (odd channel
|
||||
creation responder, evens channel creation initiator)
|
||||
|
||||
State is for *YOUR* signatures (what kind of action you need to do in the future)
|
||||
ADD\_PRESTAGE
|
||||
ADD\_STAGED
|
||||
ADD\_SIGNING\_AND\_REVOKING
|
||||
ADD\_COMPLETE
|
||||
ADD\_REJECTED
|
||||
|
||||
Messages:
|
||||
HTLCAddRequest: Request to add to staging
|
||||
HTLCAddAccept: Add to staging (both parties have added when recv)
|
||||
HTLCAddReject: Deny add to staging (both parties don't have in staging)
|
||||
|
||||
HTLC Settle (payment success)
|
||||
-----------------------------
|
||||
|
||||
Requester Settle HTLC states (Fulfill HTLCs):
|
||||
1. Pre-staged, don't know if the other person will agree to settle
|
||||
2. Staged, both parties agree to settle this HTLC
|
||||
3. Signed and sent Commitment Tx to the counterparty, there is now the
|
||||
possibility that the HTLC does not exist on-chain (of course, the Commitment
|
||||
includes the payment so there's no real loss of funds). In the event that it
|
||||
does not complete past this step, then one *must* close out on-chain as if
|
||||
it was never staged/signed in the first place and the counterparty went
|
||||
offline.
|
||||
4. Both parties have signed and revoked, the settlement is complete (there is
|
||||
no intermediate step of Revoked because this is only reliable and actionable
|
||||
if BOTH PARTIES have updated their settlement state).
|
||||
|
||||
This has one less state because when adding, you're encumbering yourself. With
|
||||
removing, both parties are potentially encumbered, so they cannot take action
|
||||
until it's fully settled.
|
||||
|
||||
State is for *your* signatures
|
||||
SETTLE\_PRESTAGE
|
||||
SETTLE\_STAGED
|
||||
SETTLE\_SIGNING\_AND\_REVOKING
|
||||
SETTLE\_COMPLETE
|
||||
|
||||
Message:
|
||||
HTLCSettleRequest: Request to add to staging the removal from Commitment.
|
||||
HTLCSettleAccept: Add to staging the removal from Commitment.
|
||||
(There is no HTLCSettleReject as the counterparty should immediately close out
|
||||
or at worst ignore if it's getting garbage requests)
|
||||
|
||||
Timeout (falure/refund)
|
||||
-----------------------
|
||||
|
||||
Requester Timeout HTLC States:
|
||||
1. Pre-staged
|
||||
2. Staged, both parties agree to time out the HTLC and refund the money
|
||||
3. Signe dnad sent commitment to the counterparty, there is now the possibility
|
||||
that the transaction will no longer exist on-chain (of course, they can be
|
||||
redeemed either way). In the even that it does not complete past this step,
|
||||
then one *must* close out on-chain as if it was never staged/signed in the
|
||||
first place adn the counterparty was offline.
|
||||
4. Both parties have signed and revoked, the settlement is complete (there is no
|
||||
intermediate step of Revoked because there is only reliable and actionable if
|
||||
BOTH PARTIES have updated their settlement state).
|
||||
|
||||
Similar to HTLC Settlement, there is one less state.
|
||||
|
||||
State is for *your* signatures
|
||||
TIMEOUT\_PRESTAGE
|
||||
TIMEOUT\_STAGED
|
||||
TIMEOUT\_SIGNING\_AND\_REVOKING
|
||||
TIMEOUT\_COMPLETE
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
Adding a single HTLC process:
|
||||
1. Requester flags as pre-staged, and sends an "add requeset"
|
||||
2. Responder decides whether to add. If they don't, they invalidate it. If they
|
||||
do, they send a message accepting the staging request. It is now marked as
|
||||
staged on both sides and is ready to be accepted into a Commitment.
|
||||
3. When a party wants to update with a new Commitment, they send a new signed
|
||||
Commitment, this includes data that the HTLC is part of it. Let's say it's
|
||||
the Requester that sends this new Commitment. As a result, the HTLC is
|
||||
marked *BY THE RESPONDER* as Signed. It's only when the Responder includes a
|
||||
transaction including the new HTLC in a new Commitment that the Requester
|
||||
marks it as Signed.
|
||||
4. Upon the Responder receiving the new Commitment, they send the revocation
|
||||
for the old Commitment, and commit to broadcasting only the new one.
|
||||
5. The *Requester* marks the HTLC as complete, but the *Responder* waits until
|
||||
they receive a Commitment (and the old one is revoked) before marking it as
|
||||
complete on the Responder's end.
|
||||
6. When both parties have the new Commitments and the old ones are revoked,
|
||||
then the HTLC is marked as complete
|
||||
|
||||
The two Commitment Transactions may not be completely in sync, but that's OK!
|
||||
What's added in both (and removed in both) are regarded as valid and locked-in.
|
||||
If it's only added to one, then it's regarded as in-transit and can go either
|
||||
way.
|
||||
|
||||
The behavior is to sign after all additions/removals/cancellations, but there
|
||||
may be multiple in the staging buffer.
|
||||
|
||||
Each party has their own revocation height (*for the other party to use*), and
|
||||
they may be different.
|
||||
+12
-17
@@ -21,12 +21,8 @@ type CommitSignature struct {
|
||||
//each part of the Commitment.
|
||||
CommitmentHeight uint64
|
||||
|
||||
//The last staging included by both parties
|
||||
//Basically, the state is updated to this point on both parties'
|
||||
//staging
|
||||
//Staging inclusion is in order.
|
||||
CommitterLastStaging uint64
|
||||
ReceiverLastStaging uint64
|
||||
//List of HTLC Keys which are updated from all parties
|
||||
UpdatedHTLCKeys []uint64
|
||||
|
||||
//Hash of the revocation to use
|
||||
RevocationHash [20]byte
|
||||
@@ -41,16 +37,14 @@ type CommitSignature struct {
|
||||
func (c *CommitSignature) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//CommitmentHeight(8)
|
||||
//CommiterLastStaging(8)
|
||||
//ReceiverLastStaging(8)
|
||||
//c.UpdatedHTLCKeys(8*1000max)
|
||||
//RevocationHash(20)
|
||||
//Fee(8)
|
||||
//RequesterCommitSig(73max+2)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.CommitmentHeight,
|
||||
&c.CommitterLastStaging,
|
||||
&c.ReceiverLastStaging,
|
||||
&c.UpdatedHTLCKeys,
|
||||
&c.RevocationHash,
|
||||
&c.Fee,
|
||||
&c.CommitSig,
|
||||
@@ -73,8 +67,7 @@ func (c *CommitSignature) Encode(w io.Writer, pver uint32) error {
|
||||
err := writeElements(w,
|
||||
c.ChannelID,
|
||||
c.CommitmentHeight,
|
||||
c.CommitterLastStaging,
|
||||
c.ReceiverLastStaging,
|
||||
c.UpdatedHTLCKeys,
|
||||
c.RevocationHash,
|
||||
c.Fee,
|
||||
c.CommitSig,
|
||||
@@ -91,7 +84,7 @@ func (c *CommitSignature) Command() uint32 {
|
||||
}
|
||||
|
||||
func (c *CommitSignature) MaxPayloadLength(uint32) uint32 {
|
||||
return 135
|
||||
return 8192
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
@@ -108,21 +101,23 @@ func (c *CommitSignature) Validate() error {
|
||||
func (c *CommitSignature) String() string {
|
||||
//c.ChannelID,
|
||||
//c.CommitmentHeight,
|
||||
//c.CommitterLastStaging,
|
||||
//c.ReceiverLastStaging,
|
||||
//c.RevocationHash,
|
||||
//c.UpdatedHTLCKeys,
|
||||
//c.Fee,
|
||||
//c.CommitSig,
|
||||
var serializedSig []byte
|
||||
if &c.CommitSig != nil && c.CommitSig.R != nil {
|
||||
serializedSig = c.CommitSig.Serialize()
|
||||
}
|
||||
var items string
|
||||
for i := 0; i < len(c.UpdatedHTLCKeys); i++ {
|
||||
items += fmt.Sprintf("%d ", c.UpdatedHTLCKeys[i])
|
||||
}
|
||||
|
||||
return fmt.Sprintf("\n--- Begin CommitSignature ---\n") +
|
||||
fmt.Sprintf("ChannelID:\t\t%d\n", c.ChannelID) +
|
||||
fmt.Sprintf("CommitmentHeight:\t%d\n", c.CommitmentHeight) +
|
||||
fmt.Sprintf("CommitterLastStaging:\t%d\n", c.CommitterLastStaging) +
|
||||
fmt.Sprintf("ReceiverLastStaging:\t%d\n", c.ReceiverLastStaging) +
|
||||
fmt.Sprintf("UpdatedHTLCKeys:\t%s\n", items) +
|
||||
fmt.Sprintf("RevocationHash:\t\t%x\n", c.RevocationHash) +
|
||||
fmt.Sprintf("Fee:\t\t\t%s\n", c.Fee.String()) +
|
||||
fmt.Sprintf("CommitSig:\t\t%x\n", serializedSig) +
|
||||
|
||||
@@ -10,16 +10,16 @@ var (
|
||||
_ = copy(revocationHash[:], revocationHashBytes)
|
||||
|
||||
commitSignature = &CommitSignature{
|
||||
ChannelID: uint64(12345678),
|
||||
CommitmentHeight: uint64(12345),
|
||||
CommitterLastStaging: uint64(12345678),
|
||||
ReceiverLastStaging: uint64(87654321),
|
||||
RevocationHash: revocationHash,
|
||||
Fee: btcutil.Amount(10000),
|
||||
CommitSig: commitSig,
|
||||
ChannelID: uint64(12345678),
|
||||
CommitmentHeight: uint64(12345),
|
||||
//CommitterLastStaging: uint64(12345678),
|
||||
UpdatedHTLCKeys: []uint64{1, 2, 3, 4, 5},
|
||||
RevocationHash: revocationHash,
|
||||
Fee: btcutil.Amount(10000),
|
||||
CommitSig: commitSig,
|
||||
}
|
||||
commitSignatureSerializedString = "0000000000bc614e00000000000030390000000000bc614e0000000005397fb14132b6b48371f7b022a16eacb9b2b0ebee134d4100000000000027104630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df"
|
||||
commitSignatureSerializedMessage = "0709110b000007d0000000830000000000bc614e00000000000030390000000000bc614e0000000005397fb14132b6b48371f7b022a16eacb9b2b0ebee134d4100000000000027104630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df"
|
||||
commitSignatureSerializedString = "0000000000bc614e00000000000030390005000000000000000100000000000000020000000000000003000000000000000400000000000000054132b6b48371f7b022a16eacb9b2b0ebee134d4100000000000027104630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df"
|
||||
commitSignatureSerializedMessage = "0709110b000007d00000009d0000000000bc614e00000000000030390005000000000000000100000000000000020000000000000003000000000000000400000000000000054132b6b48371f7b022a16eacb9b2b0ebee134d4100000000000027104630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df"
|
||||
)
|
||||
|
||||
func TestCommitSignatureEncodeDecode(t *testing.T) {
|
||||
|
||||
@@ -7,18 +7,15 @@ import (
|
||||
|
||||
type HTLCAddAccept struct {
|
||||
ChannelID uint64
|
||||
StagingID uint64
|
||||
HTLCKey HTLCKey
|
||||
}
|
||||
|
||||
func (c *HTLCAddAccept) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//CommitmentHeight(8)
|
||||
//NextResponderCommitmentRevocationHash(20)
|
||||
//ResponderRevocationPreimage(20)
|
||||
//ResponderCommitSig(2+73max)
|
||||
//HTLCKey(8)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.StagingID,
|
||||
&c.HTLCKey,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -37,7 +34,7 @@ func NewHTLCAddAccept() *HTLCAddAccept {
|
||||
func (c *HTLCAddAccept) Encode(w io.Writer, pver uint32) error {
|
||||
err := writeElements(w,
|
||||
c.ChannelID,
|
||||
c.StagingID,
|
||||
c.HTLCKey,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
@@ -65,6 +62,6 @@ func (c *HTLCAddAccept) Validate() error {
|
||||
func (c *HTLCAddAccept) String() string {
|
||||
return fmt.Sprintf("\n--- Begin HTLCAddAccept ---\n") +
|
||||
fmt.Sprintf("ChannelID:\t\t%d\n", c.ChannelID) +
|
||||
fmt.Sprintf("StagingID:\t\t%d\n", c.StagingID) +
|
||||
fmt.Sprintf("HTLCKey:\t\t%d\n", c.HTLCKey) +
|
||||
fmt.Sprintf("--- End HTLCAddAccept ---\n")
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
var (
|
||||
htlcAddAccept = &HTLCAddAccept{
|
||||
ChannelID: uint64(12345678),
|
||||
StagingID: uint64(12345),
|
||||
HTLCKey: HTLCKey(12345),
|
||||
}
|
||||
htlcAddAcceptSerializedString = "0000000000bc614e0000000000003039"
|
||||
htlcAddAcceptSerializedMessage = "0709110b000003f2000000100000000000bc614e0000000000003039"
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
type HTLCAddReject struct {
|
||||
ChannelID uint64
|
||||
StagingID uint64
|
||||
HTLCKey HTLCKey
|
||||
}
|
||||
|
||||
func (c *HTLCAddReject) Decode(r io.Reader, pver uint32) error {
|
||||
@@ -18,7 +18,7 @@ func (c *HTLCAddReject) Decode(r io.Reader, pver uint32) error {
|
||||
//ResponderCommitSig(2+73max)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.StagingID,
|
||||
&c.HTLCKey,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -37,7 +37,7 @@ func NewHTLCAddReject() *HTLCAddReject {
|
||||
func (c *HTLCAddReject) Encode(w io.Writer, pver uint32) error {
|
||||
err := writeElements(w,
|
||||
c.ChannelID,
|
||||
c.StagingID,
|
||||
c.HTLCKey,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
@@ -65,6 +65,6 @@ func (c *HTLCAddReject) Validate() error {
|
||||
func (c *HTLCAddReject) String() string {
|
||||
return fmt.Sprintf("\n--- Begin HTLCAddReject ---\n") +
|
||||
fmt.Sprintf("ChannelID:\t\t%d\n", c.ChannelID) +
|
||||
fmt.Sprintf("StagingID:\t\t%d\n", c.StagingID) +
|
||||
fmt.Sprintf("HTLCKey:\t\t%d\n", c.HTLCKey) +
|
||||
fmt.Sprintf("--- End HTLCAddReject ---\n")
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
var (
|
||||
htlcAddReject = &HTLCAddReject{
|
||||
ChannelID: uint64(12345678),
|
||||
StagingID: uint64(12345),
|
||||
HTLCKey: HTLCKey(12345),
|
||||
}
|
||||
htlcAddRejectSerializedString = "0000000000bc614e0000000000003039"
|
||||
htlcAddRejectSerializedMessage = "0709110b000003fc000000100000000000bc614e0000000000003039"
|
||||
|
||||
@@ -12,7 +12,7 @@ type HTLCAddRequest struct {
|
||||
ChannelID uint64
|
||||
|
||||
//ID of this request
|
||||
StagingID uint64
|
||||
HTLCKey HTLCKey
|
||||
|
||||
//When the HTLC expires
|
||||
Expiry uint32
|
||||
@@ -21,8 +21,9 @@ type HTLCAddRequest struct {
|
||||
//Difference between hop and first item in blob is the fee to complete
|
||||
Amount CreditsAmount
|
||||
|
||||
//Hash160 address of the next hop.
|
||||
NextHop [20]byte
|
||||
//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"
|
||||
@@ -38,19 +39,17 @@ type HTLCAddRequest struct {
|
||||
|
||||
func (c *HTLCAddRequest) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//StagingID(8)
|
||||
//HTLCKey(8)
|
||||
//Expiry(4)
|
||||
//Amount(4)
|
||||
//NextHop(20)
|
||||
//ContractType(1)
|
||||
//RedemptionHashes (numOfHashes * 20 + numOfHashes)
|
||||
//Blob(2+blobsize)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.StagingID,
|
||||
&c.HTLCKey,
|
||||
&c.Expiry,
|
||||
&c.Amount,
|
||||
&c.NextHop,
|
||||
&c.ContractType,
|
||||
&c.RedemptionHashes,
|
||||
&c.Blob,
|
||||
@@ -72,10 +71,9 @@ func NewHTLCAddRequest() *HTLCAddRequest {
|
||||
func (c *HTLCAddRequest) Encode(w io.Writer, pver uint32) error {
|
||||
err := writeElements(w,
|
||||
c.ChannelID,
|
||||
c.StagingID,
|
||||
c.HTLCKey,
|
||||
c.Expiry,
|
||||
c.Amount,
|
||||
c.NextHop,
|
||||
c.ContractType,
|
||||
c.RedemptionHashes,
|
||||
c.Blob,
|
||||
@@ -117,10 +115,9 @@ func (c *HTLCAddRequest) String() string {
|
||||
|
||||
return fmt.Sprintf("\n--- Begin HTLCAddRequest ---\n") +
|
||||
fmt.Sprintf("ChannelID:\t%d\n", c.ChannelID) +
|
||||
fmt.Sprintf("StagingID:\t%d\n", c.StagingID) +
|
||||
fmt.Sprintf("HTLCKey:\t%d\n", c.HTLCKey) +
|
||||
fmt.Sprintf("Expiry:\t\t%d\n", c.Expiry) +
|
||||
fmt.Sprintf("Amount\t\t%d\n", c.Amount) +
|
||||
fmt.Sprintf("NextHop\t\t%x\n", c.NextHop) +
|
||||
fmt.Sprintf("ContractType:\t%d (%b)\n", c.ContractType, c.ContractType) +
|
||||
fmt.Sprintf("RedemptionHashes:") +
|
||||
redemptionHashes +
|
||||
|
||||
@@ -8,23 +8,21 @@ var (
|
||||
//Need to to do this here
|
||||
_ = copy(revocationHash[:], revocationHashBytes)
|
||||
_ = copy(redemptionHash[:], redemptionHashBytes)
|
||||
_ = copy(nextHop[:], nextHopBytes)
|
||||
emptyRedemptionHashes = []*[20]byte{}
|
||||
redemptionHashes = append(emptyRedemptionHashes, &redemptionHash)
|
||||
|
||||
htlcAddRequest = &HTLCAddRequest{
|
||||
ChannelID: uint64(12345678),
|
||||
StagingID: uint64(12345),
|
||||
HTLCKey: HTLCKey(12345),
|
||||
Expiry: uint32(144),
|
||||
Amount: CreditsAmount(123456000),
|
||||
NextHop: nextHop,
|
||||
ContractType: uint8(17),
|
||||
RedemptionHashes: redemptionHashes,
|
||||
|
||||
Blob: []byte{255, 0, 255, 0, 255, 0, 255, 0},
|
||||
}
|
||||
htlcAddRequestSerializedString = "0000000000bc614e000000000000303900000090075bca0094a9ded5a30fc5944cb1e2cbcd980f30616a14401100015b315ebabb0d8c0d94281caa2dfee69a1a00436e0008ff00ff00ff00ff00"
|
||||
htlcAddRequestSerializedMessage = "0709110b000003e80000004d0000000000bc614e000000000000303900000090075bca0094a9ded5a30fc5944cb1e2cbcd980f30616a14401100015b315ebabb0d8c0d94281caa2dfee69a1a00436e0008ff00ff00ff00ff00"
|
||||
htlcAddRequestSerializedString = "0000000000bc614e000000000000303900000090075bca001100015b315ebabb0d8c0d94281caa2dfee69a1a00436e0008ff00ff00ff00ff00"
|
||||
htlcAddRequestSerializedMessage = "0709110b000003e8000000390000000000bc614e000000000000303900000090075bca001100015b315ebabb0d8c0d94281caa2dfee69a1a00436e0008ff00ff00ff00ff00"
|
||||
)
|
||||
|
||||
func TestHTLCAddRequestEncodeDecode(t *testing.T) {
|
||||
|
||||
@@ -12,15 +12,15 @@ type HTLCSettleAccept struct {
|
||||
ChannelID uint64
|
||||
|
||||
//ID of this request
|
||||
StagingID uint64
|
||||
HTLCKey HTLCKey
|
||||
}
|
||||
|
||||
func (c *HTLCSettleAccept) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//StagingID(8)
|
||||
//HTLCKey(8)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.StagingID,
|
||||
&c.HTLCKey,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -39,7 +39,7 @@ func NewHTLCSettleAccept() *HTLCSettleAccept {
|
||||
func (c *HTLCSettleAccept) Encode(w io.Writer, pver uint32) error {
|
||||
err := writeElements(w,
|
||||
c.ChannelID,
|
||||
c.StagingID,
|
||||
c.HTLCKey,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -66,6 +66,6 @@ func (c *HTLCSettleAccept) Validate() error {
|
||||
func (c *HTLCSettleAccept) String() string {
|
||||
return fmt.Sprintf("\n--- Begin HTLCSettleAccept ---\n") +
|
||||
fmt.Sprintf("ChannelID:\t%d\n", c.ChannelID) +
|
||||
fmt.Sprintf("StagingID:\t%d\n", c.StagingID) +
|
||||
fmt.Sprintf("HTLCKey:\t%d\n", c.HTLCKey) +
|
||||
fmt.Sprintf("--- End HTLCSettleAccept ---\n")
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
var (
|
||||
htlcSettleAccept = &HTLCSettleAccept{
|
||||
ChannelID: uint64(12345678),
|
||||
StagingID: uint64(12345),
|
||||
HTLCKey: HTLCKey(12345),
|
||||
}
|
||||
htlcSettleAcceptSerializedString = "0000000000bc614e0000000000003039"
|
||||
htlcSettleAcceptSerializedMessage = "0709110b00000456000000100000000000bc614e0000000000003039"
|
||||
|
||||
@@ -12,7 +12,7 @@ type HTLCSettleRequest struct {
|
||||
ChannelID uint64
|
||||
|
||||
//ID of this request
|
||||
StagingID uint64
|
||||
HTLCKey HTLCKey
|
||||
|
||||
//Redemption Proofs (R-Values)
|
||||
RedemptionProofs []*[20]byte
|
||||
@@ -20,7 +20,7 @@ type HTLCSettleRequest struct {
|
||||
|
||||
func (c *HTLCSettleRequest) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//StagingID(8)
|
||||
//HTLCKey(8)
|
||||
//Expiry(4)
|
||||
//Amount(4)
|
||||
//NextHop(20)
|
||||
@@ -29,7 +29,7 @@ func (c *HTLCSettleRequest) Decode(r io.Reader, pver uint32) error {
|
||||
//Blob(2+blobsize)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.StagingID,
|
||||
&c.HTLCKey,
|
||||
&c.RedemptionProofs,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -49,7 +49,7 @@ func NewHTLCSettleRequest() *HTLCSettleRequest {
|
||||
func (c *HTLCSettleRequest) Encode(w io.Writer, pver uint32) error {
|
||||
err := writeElements(w,
|
||||
c.ChannelID,
|
||||
c.StagingID,
|
||||
c.HTLCKey,
|
||||
c.RedemptionProofs,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -83,7 +83,7 @@ func (c *HTLCSettleRequest) String() string {
|
||||
|
||||
return fmt.Sprintf("\n--- Begin HTLCSettleRequest ---\n") +
|
||||
fmt.Sprintf("ChannelID:\t%d\n", c.ChannelID) +
|
||||
fmt.Sprintf("StagingID:\t%d\n", c.StagingID) +
|
||||
fmt.Sprintf("HTLCKey:\t%d\n", c.HTLCKey) +
|
||||
fmt.Sprintf("RedemptionHashes:") +
|
||||
redemptionProofs +
|
||||
fmt.Sprintf("--- End HTLCSettleRequest ---\n")
|
||||
|
||||
@@ -12,7 +12,7 @@ var (
|
||||
|
||||
htlcSettleRequest = &HTLCSettleRequest{
|
||||
ChannelID: uint64(12345678),
|
||||
StagingID: uint64(12345),
|
||||
HTLCKey: HTLCKey(12345),
|
||||
RedemptionProofs: redemptionProofs,
|
||||
}
|
||||
htlcSettleRequestSerializedString = "0000000000bc614e000000000000303900015b315ebabb0d8c0d94281caa2dfee69a1a00436e"
|
||||
|
||||
@@ -12,15 +12,15 @@ type HTLCTimeoutAccept struct {
|
||||
ChannelID uint64
|
||||
|
||||
//ID of this request
|
||||
StagingID uint64
|
||||
HTLCKey HTLCKey
|
||||
}
|
||||
|
||||
func (c *HTLCTimeoutAccept) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//StagingID(8)
|
||||
//HTLCKey(8)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.StagingID,
|
||||
&c.HTLCKey,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -39,7 +39,7 @@ func NewHTLCTimeoutAccept() *HTLCTimeoutAccept {
|
||||
func (c *HTLCTimeoutAccept) Encode(w io.Writer, pver uint32) error {
|
||||
err := writeElements(w,
|
||||
c.ChannelID,
|
||||
c.StagingID,
|
||||
c.HTLCKey,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -66,6 +66,6 @@ func (c *HTLCTimeoutAccept) Validate() error {
|
||||
func (c *HTLCTimeoutAccept) String() string {
|
||||
return fmt.Sprintf("\n--- Begin HTLCTimeoutAccept ---\n") +
|
||||
fmt.Sprintf("ChannelID:\t%d\n", c.ChannelID) +
|
||||
fmt.Sprintf("StagingID:\t%d\n", c.StagingID) +
|
||||
fmt.Sprintf("HTLCKey:\t%d\n", c.HTLCKey) +
|
||||
fmt.Sprintf("--- End HTLCTimeoutAccept ---\n")
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
var (
|
||||
htlcTimeoutAccept = &HTLCTimeoutAccept{
|
||||
ChannelID: uint64(12345678),
|
||||
StagingID: uint64(12345),
|
||||
HTLCKey: HTLCKey(12345),
|
||||
}
|
||||
htlcTimeoutAcceptSerializedString = "0000000000bc614e0000000000003039"
|
||||
htlcTimeoutAcceptSerializedMessage = "0709110b0000051e000000100000000000bc614e0000000000003039"
|
||||
|
||||
@@ -12,15 +12,15 @@ type HTLCTimeoutRequest struct {
|
||||
ChannelID uint64
|
||||
|
||||
//ID of this request
|
||||
StagingID uint64
|
||||
HTLCKey HTLCKey
|
||||
}
|
||||
|
||||
func (c *HTLCTimeoutRequest) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//StagingID(8)
|
||||
//HTLCKey(8)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.StagingID,
|
||||
&c.HTLCKey,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -39,7 +39,7 @@ func NewHTLCTimeoutRequest() *HTLCTimeoutRequest {
|
||||
func (c *HTLCTimeoutRequest) Encode(w io.Writer, pver uint32) error {
|
||||
err := writeElements(w,
|
||||
c.ChannelID,
|
||||
c.StagingID,
|
||||
c.HTLCKey,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -66,6 +66,6 @@ func (c *HTLCTimeoutRequest) Validate() error {
|
||||
func (c *HTLCTimeoutRequest) String() string {
|
||||
return fmt.Sprintf("\n--- Begin HTLCTimeoutRequest ---\n") +
|
||||
fmt.Sprintf("ChannelID:\t%d\n", c.ChannelID) +
|
||||
fmt.Sprintf("StagingID:\t%d\n", c.StagingID) +
|
||||
fmt.Sprintf("HTLCKey:\t%d\n", c.HTLCKey) +
|
||||
fmt.Sprintf("--- End HTLCTimeoutRequest ---\n")
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
var (
|
||||
htlcTimeoutRequest = &HTLCTimeoutRequest{
|
||||
ChannelID: uint64(12345678),
|
||||
StagingID: uint64(12345),
|
||||
HTLCKey: HTLCKey(12345),
|
||||
}
|
||||
htlcTimeoutRequestSerializedString = "0000000000bc614e0000000000003039"
|
||||
htlcTimeoutRequestSerializedMessage = "0709110b00000514000000100000000000bc614e0000000000003039"
|
||||
|
||||
@@ -16,6 +16,9 @@ var MAX_SLICE_LENGTH = 65535
|
||||
//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
|
||||
//
|
||||
@@ -76,6 +79,11 @@ func writeElement(w io.Writer, element interface{}) error {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
case HTLCKey:
|
||||
err = writeElement(w, uint64(e))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case btcutil.Amount:
|
||||
err = binary.Write(w, binary.BigEndian, int64(e))
|
||||
if err != nil {
|
||||
@@ -94,6 +102,24 @@ func writeElement(w io.Writer, element interface{}) error {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
case []uint64:
|
||||
numItems := len(e)
|
||||
if numItems > 65535 {
|
||||
return fmt.Errorf("Too many []uint64s")
|
||||
}
|
||||
//Write the size
|
||||
err = writeElement(w, uint16(numItems))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//Write the data
|
||||
for i := 0; i < numItems; i++ {
|
||||
err = writeElement(w, e[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
case []*btcec.Signature:
|
||||
numSigs := len(e)
|
||||
if numSigs > 127 {
|
||||
@@ -313,6 +339,14 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
}
|
||||
*e = binary.BigEndian.Uint64(b[:])
|
||||
return nil
|
||||
case *HTLCKey:
|
||||
var b [8]byte
|
||||
_, err = io.ReadFull(r, b[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*e = HTLCKey(binary.BigEndian.Uint64(b[:]))
|
||||
return nil
|
||||
case *btcutil.Amount:
|
||||
var b [8]byte
|
||||
_, err = io.ReadFull(r, b[:])
|
||||
@@ -341,6 +375,28 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
}
|
||||
*e = &*x
|
||||
return nil
|
||||
case *[]uint64:
|
||||
var numItems uint16
|
||||
err = readElement(r, &numItems)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//if numItems > 65535 {
|
||||
// return fmt.Errorf("Too many items in []uint64")
|
||||
//}
|
||||
|
||||
//Read the number of items
|
||||
var items []uint64
|
||||
for i := uint16(0); i < numItems; i++ {
|
||||
var item uint64
|
||||
err = readElement(r, &item)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
items = append(items, item)
|
||||
}
|
||||
*e = *&items
|
||||
return nil
|
||||
case *[]*btcec.Signature:
|
||||
var numSigs uint8
|
||||
err = readElement(r, &numSigs)
|
||||
|
||||
Reference in new issue
Block a user