mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 01:43:16 +01:00
Structs for Wire Protocol HTLCs and Commitments
* Structs and wire messages for HTLCs * Wire protocol for a state machine with no blocking(!!!) (I will write the state machine) TL;DR: Can do multiple HTLC modifications in-flight, dead simple wire protocol. Both sides can update their Commitments unliaterally without waiting for the other party's signature. Will have basic/preliminary notes in the README * Added **swp to .gitignore because of vim annoyances
This commit is contained in:
parent
58f0bfe252
commit
f3849f5c10
3
.gitignore
vendored
3
.gitignore
vendored
@ -34,3 +34,6 @@ cmd/lncli/lncli
|
||||
cmd/lnshell/lnshell
|
||||
|
||||
test_wal/*
|
||||
|
||||
# vim
|
||||
**.swp
|
||||
|
82
lnwire/commit_revocation.go
Normal file
82
lnwire/commit_revocation.go
Normal file
@ -0,0 +1,82 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
//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...
|
||||
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.
|
||||
CommitmentHeight uint64
|
||||
|
||||
//Revocation to use
|
||||
RevocationProof [20]byte
|
||||
}
|
||||
|
||||
func (c *CommitRevocation) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//CommitmentHeight(8)
|
||||
//RevocationProof(20)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.CommitmentHeight,
|
||||
&c.RevocationProof,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new CommitRevocation
|
||||
func NewCommitRevocation() *CommitRevocation {
|
||||
return &CommitRevocation{}
|
||||
}
|
||||
|
||||
//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,
|
||||
c.CommitmentHeight,
|
||||
c.RevocationProof,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CommitRevocation) Command() uint32 {
|
||||
return CmdCommitRevocation
|
||||
}
|
||||
|
||||
func (c *CommitRevocation) MaxPayloadLength(uint32) uint32 {
|
||||
return 36
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *CommitRevocation) Validate() error {
|
||||
//We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CommitRevocation) String() string {
|
||||
return fmt.Sprintf("\n--- Begin CommitRevocation ---\n") +
|
||||
fmt.Sprintf("ChannelID:\t\t%d\n", c.ChannelID) +
|
||||
fmt.Sprintf("CommitmentHeight:\t%d\n", c.CommitmentHeight) +
|
||||
fmt.Sprintf("RevocationProof:\t%x\n", c.RevocationProof) +
|
||||
fmt.Sprintf("--- End CommitRevocation ---\n")
|
||||
}
|
36
lnwire/commit_revocation_test.go
Normal file
36
lnwire/commit_revocation_test.go
Normal file
@ -0,0 +1,36 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
//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
|
||||
}
|
||||
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
|
||||
s := SerializeTest(t, commitRevocation, commitRevocationSerializedString, filename)
|
||||
|
||||
//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)
|
||||
MessageSerializeDeserializeTest(t, commitRevocation, commitRevocationSerializedMessage)
|
||||
}
|
130
lnwire/commit_signature.go
Normal file
130
lnwire/commit_signature.go
Normal file
@ -0,0 +1,130 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"io"
|
||||
)
|
||||
|
||||
//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...
|
||||
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.
|
||||
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
|
||||
|
||||
//Hash of the revocation to use
|
||||
RevocationHash [20]byte
|
||||
|
||||
//Total miners' fee that was used
|
||||
Fee btcutil.Amount
|
||||
|
||||
//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)
|
||||
//CommiterLastStaging(8)
|
||||
//ReceiverLastStaging(8)
|
||||
//RevocationHash(20)
|
||||
//Fee(8)
|
||||
//RequesterCommitSig(73max+2)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.CommitmentHeight,
|
||||
&c.CommitterLastStaging,
|
||||
&c.ReceiverLastStaging,
|
||||
&c.RevocationHash,
|
||||
&c.Fee,
|
||||
&c.CommitSig,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new CommitSignature
|
||||
func NewCommitSignature() *CommitSignature {
|
||||
return &CommitSignature{}
|
||||
}
|
||||
|
||||
//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,
|
||||
c.CommitmentHeight,
|
||||
c.CommitterLastStaging,
|
||||
c.ReceiverLastStaging,
|
||||
c.RevocationHash,
|
||||
c.Fee,
|
||||
c.CommitSig,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CommitSignature) Command() uint32 {
|
||||
return CmdCommitSignature
|
||||
}
|
||||
|
||||
func (c *CommitSignature) MaxPayloadLength(uint32) uint32 {
|
||||
return 135
|
||||
}
|
||||
|
||||
//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!
|
||||
return fmt.Errorf("Amount paid cannot be negative.")
|
||||
}
|
||||
//We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CommitSignature) String() string {
|
||||
//c.ChannelID,
|
||||
//c.CommitmentHeight,
|
||||
//c.CommitterLastStaging,
|
||||
//c.ReceiverLastStaging,
|
||||
//c.RevocationHash,
|
||||
//c.Fee,
|
||||
//c.CommitSig,
|
||||
var serializedSig []byte
|
||||
if &c.CommitSig != nil && c.CommitSig.R != nil {
|
||||
serializedSig = c.CommitSig.Serialize()
|
||||
}
|
||||
|
||||
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("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) +
|
||||
fmt.Sprintf("--- End CommitSignature ---\n")
|
||||
}
|
41
lnwire/commit_signature_test.go
Normal file
41
lnwire/commit_signature_test.go
Normal file
@ -0,0 +1,41 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btcutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
//Need to to do this here
|
||||
_ = 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,
|
||||
}
|
||||
commitSignatureSerializedString = "0000000000bc614e00000000000030390000000000bc614e0000000005397fb14132b6b48371f7b022a16eacb9b2b0ebee134d4100000000000027104630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df"
|
||||
commitSignatureSerializedMessage = "0709110b000007d0000000830000000000bc614e00000000000030390000000000bc614e0000000005397fb14132b6b48371f7b022a16eacb9b2b0ebee134d4100000000000027104630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df"
|
||||
)
|
||||
|
||||
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
|
||||
s := SerializeTest(t, commitSignature, commitSignatureSerializedString, filename)
|
||||
|
||||
//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)
|
||||
MessageSerializeDeserializeTest(t, commitSignature, commitSignatureSerializedMessage)
|
||||
}
|
70
lnwire/htlc_addaccept.go
Normal file
70
lnwire/htlc_addaccept.go
Normal file
@ -0,0 +1,70 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
type HTLCAddAccept struct {
|
||||
ChannelID uint64
|
||||
StagingID uint64
|
||||
}
|
||||
|
||||
func (c *HTLCAddAccept) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//CommitmentHeight(8)
|
||||
//NextResponderCommitmentRevocationHash(20)
|
||||
//ResponderRevocationPreimage(20)
|
||||
//ResponderCommitSig(2+73max)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.StagingID,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new HTLCAddAccept
|
||||
func NewHTLCAddAccept() *HTLCAddAccept {
|
||||
return &HTLCAddAccept{}
|
||||
}
|
||||
|
||||
//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,
|
||||
c.StagingID,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *HTLCAddAccept) Command() uint32 {
|
||||
return CmdHTLCAddAccept
|
||||
}
|
||||
|
||||
func (c *HTLCAddAccept) MaxPayloadLength(uint32) uint32 {
|
||||
//16 base size
|
||||
return 16
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *HTLCAddAccept) Validate() error {
|
||||
//We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
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("--- End HTLCAddAccept ---\n")
|
||||
}
|
32
lnwire/htlc_addaccept_test.go
Normal file
32
lnwire/htlc_addaccept_test.go
Normal file
@ -0,0 +1,32 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
htlcAddAccept = &HTLCAddAccept{
|
||||
ChannelID: uint64(12345678),
|
||||
StagingID: uint64(12345),
|
||||
}
|
||||
htlcAddAcceptSerializedString = "0000000000bc614e0000000000003039"
|
||||
htlcAddAcceptSerializedMessage = "0709110b000003f2000000100000000000bc614e0000000000003039"
|
||||
)
|
||||
|
||||
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
|
||||
s := SerializeTest(t, htlcAddAccept, htlcAddAcceptSerializedString, filename)
|
||||
|
||||
//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)
|
||||
MessageSerializeDeserializeTest(t, htlcAddAccept, htlcAddAcceptSerializedMessage)
|
||||
}
|
70
lnwire/htlc_addreject.go
Normal file
70
lnwire/htlc_addreject.go
Normal file
@ -0,0 +1,70 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
type HTLCAddReject struct {
|
||||
ChannelID uint64
|
||||
StagingID uint64
|
||||
}
|
||||
|
||||
func (c *HTLCAddReject) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//CommitmentHeight(8)
|
||||
//NextResponderCommitmentRevocationHash(20)
|
||||
//ResponderRevocationPreimage(20)
|
||||
//ResponderCommitSig(2+73max)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.StagingID,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new HTLCAddReject
|
||||
func NewHTLCAddReject() *HTLCAddReject {
|
||||
return &HTLCAddReject{}
|
||||
}
|
||||
|
||||
//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,
|
||||
c.StagingID,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *HTLCAddReject) Command() uint32 {
|
||||
return CmdHTLCAddReject
|
||||
}
|
||||
|
||||
func (c *HTLCAddReject) MaxPayloadLength(uint32) uint32 {
|
||||
//16 base size
|
||||
return 16
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *HTLCAddReject) Validate() error {
|
||||
//We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
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("--- End HTLCAddReject ---\n")
|
||||
}
|
32
lnwire/htlc_addreject_test.go
Normal file
32
lnwire/htlc_addreject_test.go
Normal file
@ -0,0 +1,32 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
htlcAddReject = &HTLCAddReject{
|
||||
ChannelID: uint64(12345678),
|
||||
StagingID: uint64(12345),
|
||||
}
|
||||
htlcAddRejectSerializedString = "0000000000bc614e0000000000003039"
|
||||
htlcAddRejectSerializedMessage = "0709110b000003fc000000100000000000bc614e0000000000003039"
|
||||
)
|
||||
|
||||
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
|
||||
s := SerializeTest(t, htlcAddReject, htlcAddRejectSerializedString, filename)
|
||||
|
||||
//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)
|
||||
MessageSerializeDeserializeTest(t, htlcAddReject, htlcAddRejectSerializedMessage)
|
||||
}
|
129
lnwire/htlc_addrequest.go
Normal file
129
lnwire/htlc_addrequest.go
Normal file
@ -0,0 +1,129 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
//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...
|
||||
ChannelID uint64
|
||||
|
||||
//ID of this request
|
||||
StagingID uint64
|
||||
|
||||
//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 CreditsAmount
|
||||
|
||||
//Hash160 address of the next hop.
|
||||
NextHop [20]byte
|
||||
|
||||
//Contract Type
|
||||
//first 4 bits is n, second for is m, in n-of-m "multisig"
|
||||
ContractType uint8
|
||||
|
||||
//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?
|
||||
Blob []byte
|
||||
}
|
||||
|
||||
func (c *HTLCAddRequest) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//StagingID(8)
|
||||
//Expiry(4)
|
||||
//Amount(4)
|
||||
//NextHop(20)
|
||||
//ContractType(1)
|
||||
//RedemptionHashes (numOfHashes * 20 + numOfHashes)
|
||||
//Blob(2+blobsize)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.StagingID,
|
||||
&c.Expiry,
|
||||
&c.Amount,
|
||||
&c.NextHop,
|
||||
&c.ContractType,
|
||||
&c.RedemptionHashes,
|
||||
&c.Blob,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new HTLCAddRequest
|
||||
func NewHTLCAddRequest() *HTLCAddRequest {
|
||||
return &HTLCAddRequest{}
|
||||
}
|
||||
|
||||
//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,
|
||||
c.StagingID,
|
||||
c.Expiry,
|
||||
c.Amount,
|
||||
c.NextHop,
|
||||
c.ContractType,
|
||||
c.RedemptionHashes,
|
||||
c.Blob,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *HTLCAddRequest) Command() uint32 {
|
||||
return CmdHTLCAddRequest
|
||||
}
|
||||
|
||||
func (c *HTLCAddRequest) MaxPayloadLength(uint32) uint32 {
|
||||
//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)
|
||||
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!
|
||||
return fmt.Errorf("Amount paid cannot be negative.")
|
||||
}
|
||||
//We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *HTLCAddRequest) String() string {
|
||||
var redemptionHashes string
|
||||
for i, rh := range c.RedemptionHashes {
|
||||
redemptionHashes += fmt.Sprintf("\n\tSlice\t%d\n", i)
|
||||
redemptionHashes += fmt.Sprintf("\t\tRedemption Hash: %x\n", *rh)
|
||||
}
|
||||
|
||||
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("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 +
|
||||
fmt.Sprintf("Blob:\t\t\t\t%x\n", c.Blob) +
|
||||
fmt.Sprintf("--- End HTLCAddRequest ---\n")
|
||||
}
|
46
lnwire/htlc_addrequest_test.go
Normal file
46
lnwire/htlc_addrequest_test.go
Normal file
@ -0,0 +1,46 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
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),
|
||||
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"
|
||||
)
|
||||
|
||||
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
|
||||
s := SerializeTest(t, htlcAddRequest, htlcAddRequestSerializedString, filename)
|
||||
|
||||
//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)
|
||||
MessageSerializeDeserializeTest(t, htlcAddRequest, htlcAddRequestSerializedMessage)
|
||||
}
|
77
lnwire/htlc_settleaccept.go
Normal file
77
lnwire/htlc_settleaccept.go
Normal file
@ -0,0 +1,77 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
//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...
|
||||
ChannelID uint64
|
||||
|
||||
//ID of this request
|
||||
StagingID uint64
|
||||
}
|
||||
|
||||
func (c *HTLCSettleAccept) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//StagingID(8)
|
||||
//Expiry(4)
|
||||
//Amount(4)
|
||||
//NextHop(20)
|
||||
//ContractType(1)
|
||||
//RedemptionHashes (numOfHashes * 20 + numOfHashes)
|
||||
//Blob(2+blobsize)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.StagingID,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new HTLCSettleAccept
|
||||
func NewHTLCSettleAccept() *HTLCSettleAccept {
|
||||
return &HTLCSettleAccept{}
|
||||
}
|
||||
|
||||
//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,
|
||||
c.StagingID,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *HTLCSettleAccept) Command() uint32 {
|
||||
return CmdHTLCSettleAccept
|
||||
}
|
||||
|
||||
func (c *HTLCSettleAccept) MaxPayloadLength(uint32) uint32 {
|
||||
//16
|
||||
return 16
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *HTLCSettleAccept) Validate() error {
|
||||
//We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
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("--- End HTLCSettleAccept ---\n")
|
||||
}
|
32
lnwire/htlc_settleaccept_test.go
Normal file
32
lnwire/htlc_settleaccept_test.go
Normal file
@ -0,0 +1,32 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
htlcSettleAccept = &HTLCSettleAccept{
|
||||
ChannelID: uint64(12345678),
|
||||
StagingID: uint64(12345),
|
||||
}
|
||||
htlcSettleAcceptSerializedString = "0000000000bc614e0000000000003039"
|
||||
htlcSettleAcceptSerializedMessage = "0709110b00000456000000100000000000bc614e0000000000003039"
|
||||
)
|
||||
|
||||
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
|
||||
s := SerializeTest(t, htlcSettleAccept, htlcSettleAcceptSerializedString, filename)
|
||||
|
||||
//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)
|
||||
MessageSerializeDeserializeTest(t, htlcSettleAccept, htlcSettleAcceptSerializedMessage)
|
||||
}
|
90
lnwire/htlc_settlerequest.go
Normal file
90
lnwire/htlc_settlerequest.go
Normal file
@ -0,0 +1,90 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
//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...
|
||||
ChannelID uint64
|
||||
|
||||
//ID of this request
|
||||
StagingID uint64
|
||||
|
||||
//Redemption Proofs (R-Values)
|
||||
RedemptionProofs []*[20]byte
|
||||
}
|
||||
|
||||
func (c *HTLCSettleRequest) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//StagingID(8)
|
||||
//Expiry(4)
|
||||
//Amount(4)
|
||||
//NextHop(20)
|
||||
//ContractType(1)
|
||||
//RedemptionHashes (numOfHashes * 20 + numOfHashes)
|
||||
//Blob(2+blobsize)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.StagingID,
|
||||
&c.RedemptionProofs,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new HTLCSettleRequest
|
||||
func NewHTLCSettleRequest() *HTLCSettleRequest {
|
||||
return &HTLCSettleRequest{}
|
||||
}
|
||||
|
||||
//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,
|
||||
c.StagingID,
|
||||
c.RedemptionProofs,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *HTLCSettleRequest) Command() uint32 {
|
||||
return CmdHTLCSettleRequest
|
||||
}
|
||||
|
||||
func (c *HTLCSettleRequest) MaxPayloadLength(uint32) uint32 {
|
||||
//21*15+16
|
||||
return 331
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *HTLCSettleRequest) Validate() error {
|
||||
//We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *HTLCSettleRequest) String() string {
|
||||
var redemptionProofs string
|
||||
for i, rh := range c.RedemptionProofs {
|
||||
redemptionProofs += fmt.Sprintf("\n\tSlice\t%d\n", i)
|
||||
redemptionProofs += fmt.Sprintf("\t\tRedemption Proof: %x\n", *rh)
|
||||
}
|
||||
|
||||
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("RedemptionHashes:") +
|
||||
redemptionProofs +
|
||||
fmt.Sprintf("--- End HTLCSettleRequest ---\n")
|
||||
}
|
38
lnwire/htlc_settlerequest_test.go
Normal file
38
lnwire/htlc_settlerequest_test.go
Normal file
@ -0,0 +1,38 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
//Need to to do this here
|
||||
_ = copy(redemptionHash[:], redemptionHashBytes)
|
||||
emptyRedemptionProofs = []*[20]byte{}
|
||||
redemptionProofs = append(emptyRedemptionProofs, &redemptionHash)
|
||||
|
||||
htlcSettleRequest = &HTLCSettleRequest{
|
||||
ChannelID: uint64(12345678),
|
||||
StagingID: uint64(12345),
|
||||
RedemptionProofs: redemptionProofs,
|
||||
}
|
||||
htlcSettleRequestSerializedString = "0000000000bc614e000000000000303900015b315ebabb0d8c0d94281caa2dfee69a1a00436e"
|
||||
htlcSettleRequestSerializedMessage = "0709110b0000044c000000260000000000bc614e000000000000303900015b315ebabb0d8c0d94281caa2dfee69a1a00436e"
|
||||
)
|
||||
|
||||
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
|
||||
s := SerializeTest(t, htlcSettleRequest, htlcSettleRequestSerializedString, filename)
|
||||
|
||||
//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)
|
||||
MessageSerializeDeserializeTest(t, htlcSettleRequest, htlcSettleRequestSerializedMessage)
|
||||
}
|
71
lnwire/htlc_timeoutaccept.go
Normal file
71
lnwire/htlc_timeoutaccept.go
Normal file
@ -0,0 +1,71 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
//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...
|
||||
ChannelID uint64
|
||||
|
||||
//ID of this request
|
||||
StagingID uint64
|
||||
}
|
||||
|
||||
func (c *HTLCTimeoutAccept) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//StagingID(8)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.StagingID,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new HTLCTimeoutAccept
|
||||
func NewHTLCTimeoutAccept() *HTLCTimeoutAccept {
|
||||
return &HTLCTimeoutAccept{}
|
||||
}
|
||||
|
||||
//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,
|
||||
c.StagingID,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *HTLCTimeoutAccept) Command() uint32 {
|
||||
return CmdHTLCTimeoutAccept
|
||||
}
|
||||
|
||||
func (c *HTLCTimeoutAccept) MaxPayloadLength(uint32) uint32 {
|
||||
//16
|
||||
return 16
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *HTLCTimeoutAccept) Validate() error {
|
||||
//We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
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("--- End HTLCTimeoutAccept ---\n")
|
||||
}
|
32
lnwire/htlc_timeoutaccept_test.go
Normal file
32
lnwire/htlc_timeoutaccept_test.go
Normal file
@ -0,0 +1,32 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
htlcTimeoutAccept = &HTLCTimeoutAccept{
|
||||
ChannelID: uint64(12345678),
|
||||
StagingID: uint64(12345),
|
||||
}
|
||||
htlcTimeoutAcceptSerializedString = "0000000000bc614e0000000000003039"
|
||||
htlcTimeoutAcceptSerializedMessage = "0709110b0000051e000000100000000000bc614e0000000000003039"
|
||||
)
|
||||
|
||||
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
|
||||
s := SerializeTest(t, htlcTimeoutAccept, htlcTimeoutAcceptSerializedString, filename)
|
||||
|
||||
//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)
|
||||
MessageSerializeDeserializeTest(t, htlcTimeoutAccept, htlcTimeoutAcceptSerializedMessage)
|
||||
}
|
71
lnwire/htlc_timeoutrequest.go
Normal file
71
lnwire/htlc_timeoutrequest.go
Normal file
@ -0,0 +1,71 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
//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...
|
||||
ChannelID uint64
|
||||
|
||||
//ID of this request
|
||||
StagingID uint64
|
||||
}
|
||||
|
||||
func (c *HTLCTimeoutRequest) Decode(r io.Reader, pver uint32) error {
|
||||
//ChannelID(8)
|
||||
//StagingID(8)
|
||||
err := readElements(r,
|
||||
&c.ChannelID,
|
||||
&c.StagingID,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//Creates a new HTLCTimeoutRequest
|
||||
func NewHTLCTimeoutRequest() *HTLCTimeoutRequest {
|
||||
return &HTLCTimeoutRequest{}
|
||||
}
|
||||
|
||||
//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,
|
||||
c.StagingID,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *HTLCTimeoutRequest) Command() uint32 {
|
||||
return CmdHTLCTimeoutRequest
|
||||
}
|
||||
|
||||
func (c *HTLCTimeoutRequest) MaxPayloadLength(uint32) uint32 {
|
||||
//16
|
||||
return 16
|
||||
}
|
||||
|
||||
//Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts)
|
||||
func (c *HTLCTimeoutRequest) Validate() error {
|
||||
//We're good!
|
||||
return nil
|
||||
}
|
||||
|
||||
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("--- End HTLCTimeoutRequest ---\n")
|
||||
}
|
32
lnwire/htlc_timeoutrequest_test.go
Normal file
32
lnwire/htlc_timeoutrequest_test.go
Normal file
@ -0,0 +1,32 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
htlcTimeoutRequest = &HTLCTimeoutRequest{
|
||||
ChannelID: uint64(12345678),
|
||||
StagingID: uint64(12345),
|
||||
}
|
||||
htlcTimeoutRequestSerializedString = "0000000000bc614e0000000000003039"
|
||||
htlcTimeoutRequestSerializedMessage = "0709110b00000514000000100000000000bc614e0000000000003039"
|
||||
)
|
||||
|
||||
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
|
||||
s := SerializeTest(t, htlcTimeoutRequest, htlcTimeoutRequestSerializedString, filename)
|
||||
|
||||
//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)
|
||||
MessageSerializeDeserializeTest(t, htlcTimeoutRequest, htlcTimeoutRequestSerializedMessage)
|
||||
}
|
133
lnwire/lnwire.go
133
lnwire/lnwire.go
@ -11,11 +11,25 @@ import (
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
var MAX_SLICE_LENGTH = 65535
|
||||
|
||||
//Actual pkScript, not redeemScript
|
||||
type PkScript []byte
|
||||
|
||||
//Subsatoshi amount
|
||||
type MicroSatoshi int32
|
||||
//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
|
||||
@ -32,6 +46,20 @@ func writeElement(w io.Writer, element interface{}) error {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
case uint16:
|
||||
var b [2]byte
|
||||
binary.BigEndian.PutUint16(b[:], uint16(e))
|
||||
_, err = w.Write(b[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
case CreditsAmount:
|
||||
err = binary.Write(w, binary.BigEndian, int32(e))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
case uint32:
|
||||
var b [4]byte
|
||||
binary.BigEndian.PutUint32(b[:], uint32(e))
|
||||
@ -107,6 +135,26 @@ func writeElement(w io.Writer, element interface{}) error {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
case []*[20]byte:
|
||||
//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
|
||||
for _, element := range e {
|
||||
err = writeElement(w, &element)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
case **[20]byte:
|
||||
_, err = w.Write((*e)[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case [20]byte:
|
||||
_, err = w.Write(e[:])
|
||||
if err != nil {
|
||||
@ -121,6 +169,22 @@ func writeElement(w io.Writer, element interface{}) error {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
case []byte:
|
||||
sliceLength := len(e)
|
||||
if sliceLength > MAX_SLICE_LENGTH {
|
||||
return fmt.Errorf("Slice length too long!")
|
||||
}
|
||||
//Write the size
|
||||
err = writeElement(w, uint16(sliceLength))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//Write the data
|
||||
_, err = w.Write(e)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
case PkScript:
|
||||
scriptLength := len(e)
|
||||
//Make sure it's P2PKH or P2SH size or less
|
||||
@ -202,6 +266,22 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
}
|
||||
*e = b[0]
|
||||
return nil
|
||||
case *uint16:
|
||||
var b [2]byte
|
||||
_, err = io.ReadFull(r, b[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*e = binary.BigEndian.Uint16(b[:])
|
||||
return nil
|
||||
case *CreditsAmount:
|
||||
var b [4]byte
|
||||
_, err = io.ReadFull(r, b[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*e = CreditsAmount(int32(binary.BigEndian.Uint32(b[:])))
|
||||
return nil
|
||||
case *uint32:
|
||||
var b [4]byte
|
||||
_, err = io.ReadFull(r, b[:])
|
||||
@ -294,6 +374,25 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
}
|
||||
*e = &*btcecSig
|
||||
return nil
|
||||
case *[]*[20]byte:
|
||||
//How many to read
|
||||
var sliceSize uint16
|
||||
err = readElement(r, &sliceSize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var data []*[20]byte
|
||||
//Append the actual
|
||||
for i := uint16(0); i < sliceSize; i++ {
|
||||
var element [20]byte
|
||||
err = readElement(r, &element)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data = append(data, &element)
|
||||
}
|
||||
*e = data
|
||||
return nil
|
||||
case *[20]byte:
|
||||
_, err = io.ReadFull(r, e[:])
|
||||
if err != nil {
|
||||
@ -308,6 +407,30 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
}
|
||||
*e = wire.BitcoinNet(binary.BigEndian.Uint32(b[:]))
|
||||
return nil
|
||||
case *[]byte:
|
||||
//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...
|
||||
if int(blobLength) > MAX_SLICE_LENGTH {
|
||||
return fmt.Errorf("Slice length too long!")
|
||||
}
|
||||
|
||||
//Read the slice length
|
||||
l := io.LimitReader(r, int64(blobLength))
|
||||
*e, err = ioutil.ReadAll(l)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(*e) != int(blobLength) {
|
||||
return fmt.Errorf("EOF: Slice length mismatch.")
|
||||
}
|
||||
return nil
|
||||
case *PkScript:
|
||||
//Get the script length first
|
||||
var scriptLength uint8
|
||||
@ -323,12 +446,12 @@ func readElement(r io.Reader, element interface{}) error {
|
||||
//Read the script length
|
||||
l := io.LimitReader(r, int64(scriptLength))
|
||||
*e, err = ioutil.ReadAll(l)
|
||||
if len(*e) != int(scriptLength) {
|
||||
return fmt.Errorf("EOF: Signature length mismatch.")
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(*e) != int(scriptLength) {
|
||||
return fmt.Errorf("EOF: Signature length mismatch.")
|
||||
}
|
||||
return nil
|
||||
case *[]*wire.TxIn:
|
||||
//Read the size (1-byte number of txins)
|
||||
|
@ -24,8 +24,17 @@ var (
|
||||
revocationHashBytes, _ = hex.DecodeString("4132b6b48371f7b022a16eacb9b2b0ebee134d41")
|
||||
revocationHash [20]byte
|
||||
|
||||
//preimage: "hello world"
|
||||
redemptionHashBytes, _ = hex.DecodeString("5b315ebabb0d8c0d94281caa2dfee69a1a00436e")
|
||||
redemptionHash [20]byte
|
||||
|
||||
//preimage: "next hop"
|
||||
nextHopBytes, _ = hex.DecodeString("94a9ded5a30fc5944cb1e2cbcd980f30616a1440")
|
||||
nextHop [20]byte
|
||||
|
||||
privKeyBytes, _ = hex.DecodeString("9fa1d55217f57019a3c37f49465896b15836f54cb8ef6963870a52926420a2dd")
|
||||
privKey, pubKey = btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes)
|
||||
address = pubKey
|
||||
|
||||
// Delivery PkScript
|
||||
//Privkey: f2c00ead9cbcfec63098dc0a5f152c0165aff40a2ab92feb4e24869a284c32a7
|
||||
|
@ -39,7 +39,24 @@ const (
|
||||
CmdCloseRequest = uint32(300)
|
||||
CmdCloseComplete = uint32(310)
|
||||
|
||||
//TODO Renumber to 1100
|
||||
//HTLC payment
|
||||
CmdHTLCAddRequest = uint32(1000)
|
||||
CmdHTLCAddAccept = uint32(1010)
|
||||
CmdHTLCAddReject = uint32(1020)
|
||||
|
||||
//TODO Renumber to 1200
|
||||
//HTLC settlement
|
||||
CmdHTLCSettleRequest = uint32(1100)
|
||||
CmdHTLCSettleAccept = uint32(1110)
|
||||
|
||||
//HTLC timeout
|
||||
CmdHTLCTimeoutRequest = uint32(1300)
|
||||
CmdHTLCTimeoutAccept = uint32(1310)
|
||||
|
||||
//Commitments
|
||||
CmdCommitSignature = uint32(2000)
|
||||
CmdCommitRevocation = uint32(2010)
|
||||
)
|
||||
|
||||
//Every message has these functions:
|
||||
@ -68,6 +85,24 @@ func makeEmptyMessage(command uint32) (Message, error) {
|
||||
msg = &CloseRequest{}
|
||||
case CmdCloseComplete:
|
||||
msg = &CloseComplete{}
|
||||
case CmdHTLCAddRequest:
|
||||
msg = &HTLCAddRequest{}
|
||||
case CmdHTLCAddAccept:
|
||||
msg = &HTLCAddAccept{}
|
||||
case CmdHTLCAddReject:
|
||||
msg = &HTLCAddReject{}
|
||||
case CmdHTLCSettleRequest:
|
||||
msg = &HTLCSettleRequest{}
|
||||
case CmdHTLCSettleAccept:
|
||||
msg = &HTLCSettleAccept{}
|
||||
case CmdHTLCTimeoutRequest:
|
||||
msg = &HTLCTimeoutRequest{}
|
||||
case CmdHTLCTimeoutAccept:
|
||||
msg = &HTLCTimeoutAccept{}
|
||||
case CmdCommitSignature:
|
||||
msg = &CommitSignature{}
|
||||
case CmdCommitRevocation:
|
||||
msg = &CommitRevocation{}
|
||||
default:
|
||||
return nil, fmt.Errorf("unhandled command [%d]", command)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user