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:
Joseph Poon authored and Olaoluwa Osuntokun committed 2016-01-14 23:58:04 -08:00
1 parent 0c304cbb2f
commit 1981001a29
20 files changed
+727 -80

No files matched your search

+181
View File
@@ -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
View File
@@ -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) +
+9 -9
View File
@@ -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) {
+5 -8
View File
@@ -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")
}
+1 -1
View File
@@ -7,7 +7,7 @@ import (
var (
htlcAddAccept = &HTLCAddAccept{
ChannelID: uint64(12345678),
StagingID: uint64(12345),
HTLCKey: HTLCKey(12345),
}
htlcAddAcceptSerializedString = "0000000000bc614e0000000000003039"
htlcAddAcceptSerializedMessage = "0709110b000003f2000000100000000000bc614e0000000000003039"
+4 -4
View File
@@ -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")
}
+1 -1
View File
@@ -7,7 +7,7 @@ import (
var (
htlcAddReject = &HTLCAddReject{
ChannelID: uint64(12345678),
StagingID: uint64(12345),
HTLCKey: HTLCKey(12345),
}
htlcAddRejectSerializedString = "0000000000bc614e0000000000003039"
htlcAddRejectSerializedMessage = "0709110b000003fc000000100000000000bc614e0000000000003039"
+8 -11
View File
@@ -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 +
+3 -5
View File
@@ -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) {
+5 -5
View File
@@ -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")
}
+1 -1
View File
@@ -7,7 +7,7 @@ import (
var (
htlcSettleAccept = &HTLCSettleAccept{
ChannelID: uint64(12345678),
StagingID: uint64(12345),
HTLCKey: HTLCKey(12345),
}
htlcSettleAcceptSerializedString = "0000000000bc614e0000000000003039"
htlcSettleAcceptSerializedMessage = "0709110b00000456000000100000000000bc614e0000000000003039"
+5 -5
View File
@@ -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")
+1 -1
View File
@@ -12,7 +12,7 @@ var (
htlcSettleRequest = &HTLCSettleRequest{
ChannelID: uint64(12345678),
StagingID: uint64(12345),
HTLCKey: HTLCKey(12345),
RedemptionProofs: redemptionProofs,
}
htlcSettleRequestSerializedString = "0000000000bc614e000000000000303900015b315ebabb0d8c0d94281caa2dfee69a1a00436e"
+5 -5
View File
@@ -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")
}
+1 -1
View File
@@ -7,7 +7,7 @@ import (
var (
htlcTimeoutAccept = &HTLCTimeoutAccept{
ChannelID: uint64(12345678),
StagingID: uint64(12345),
HTLCKey: HTLCKey(12345),
}
htlcTimeoutAcceptSerializedString = "0000000000bc614e0000000000003039"
htlcTimeoutAcceptSerializedMessage = "0709110b0000051e000000100000000000bc614e0000000000003039"
+5 -5
View File
@@ -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")
}
+1 -1
View File
@@ -7,7 +7,7 @@ import (
var (
htlcTimeoutRequest = &HTLCTimeoutRequest{
ChannelID: uint64(12345678),
StagingID: uint64(12345),
HTLCKey: HTLCKey(12345),
}
htlcTimeoutRequestSerializedString = "0000000000bc614e0000000000003039"
htlcTimeoutRequestSerializedMessage = "0709110b00000514000000100000000000bc614e0000000000003039"
+56
View File
@@ -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)