Skip to content

Commit

Permalink
Merge pull request #379 from delbonis/refactor/qchanserdes2
Browse files Browse the repository at this point in the history
Refactor Qchan serialization to store data as flat JSON
  • Loading branch information
adiabat committed Oct 16, 2018
2 parents 3aaa90b + 4f3f2f5 commit c691d1d
Show file tree
Hide file tree
Showing 17 changed files with 287 additions and 964 deletions.
54 changes: 27 additions & 27 deletions elkrem/elkrem.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ const maxHeight = uint8(47)
// You can calculate h from i but I can't figure out how without taking
// O(i) ops. Feels like there should be a clever O(h) way. 1 byte, whatever.
type ElkremNode struct {
h uint8 // height of this node
i uint64 // index (i'th node)
sha *chainhash.Hash // hash
H uint8 `json:"h"` // height of this node
I uint64 `json:"i"` // index (i'th node)
Sha *chainhash.Hash `json:"hash"` // hash
}
type ElkremSender struct {
root *chainhash.Hash // root hash of the tree
}
type ElkremReceiver struct {
s []ElkremNode // store of received hashes
Nodes []ElkremNode `json:"nodes"` // store of received hashes
}

func LeftSha(in chainhash.Hash) chainhash.Hash {
Expand Down Expand Up @@ -103,54 +103,54 @@ func (e *ElkremSender) AtIndex(w uint64) (*chainhash.Hash, error) {
func (e *ElkremReceiver) AddNext(sha *chainhash.Hash) error {
// note: careful about atomicity / disk writes here
var n ElkremNode
n.sha = sha
t := len(e.s) - 1 // top of stack
if t >= 0 { // if this is not the first hash (>= because we -1'd)
n.i = e.s[t].i + 1 // incoming index is tip of stack index + 1
n.Sha = sha
t := len(e.Nodes) - 1 // top of stack
if t >= 0 { // if this is not the first hash (>= because we -1'd)
n.I = e.Nodes[t].I + 1 // incoming index is tip of stack index + 1
}
if t > 0 && e.s[t-1].h == e.s[t].h { // top 2 elements are equal height
if t > 0 && e.Nodes[t-1].H == e.Nodes[t].H { // top 2 elements are equal height
// next node must be parent; verify and remove children
n.h = e.s[t].h + 1 // assign height
l := LeftSha(*sha) // calc l child
r := RightSha(*sha) // calc r child
if !e.s[t-1].sha.IsEqual(&l) { // test l child
n.H = e.Nodes[t].H + 1 // assign height
l := LeftSha(*sha) // calc l child
r := RightSha(*sha) // calc r child
if !e.Nodes[t-1].Sha.IsEqual(&l) { // test l child
return fmt.Errorf("left child doesn't match, expect %s got %s",
e.s[t-1].sha.String(), l.String())
e.Nodes[t-1].Sha.String(), l.String())
}
if !e.s[t].sha.IsEqual(&r) { // test r child
if !e.Nodes[t].Sha.IsEqual(&r) { // test r child
return fmt.Errorf("right child doesn't match, expect %s got %s",
e.s[t].sha.String(), r.String())
e.Nodes[t].Sha.String(), r.String())
}
e.s = e.s[:len(e.s)-2] // l and r children OK, remove them
e.Nodes = e.Nodes[:len(e.Nodes)-2] // l and r children OK, remove them
} // if that didn't happen, height defaults to 0
e.s = append(e.s, n) // append new node to stack
e.Nodes = append(e.Nodes, n) // append new node to stack
return nil
}

// AtIndex returns the w'th hash in the receiver.
func (e *ElkremReceiver) AtIndex(w uint64) (*chainhash.Hash, error) {
if e == nil || e.s == nil {
if e == nil || e.Nodes == nil {
return nil, fmt.Errorf("nil elkrem receiver")
}
var out ElkremNode // node we will eventually return
for _, n := range e.s { // go through stack
if w <= n.i { // found one bigger than or equal to what we want
var out ElkremNode // node we will eventually return
for _, n := range e.Nodes { // go through stack
if w <= n.I { // found one bigger than or equal to what we want
out = n
break
}
}
if out.sha == nil { // didn't find anything
if out.Sha == nil { // didn't find anything
return nil, fmt.Errorf("receiver has max %d, less than requested %d",
e.s[len(e.s)-1].i, w)
e.Nodes[len(e.Nodes)-1].I, w)
}
sha, err := descend(w, out.i, out.h, *out.sha)
sha, err := descend(w, out.I, out.H, *out.Sha)
return &sha, err
}

// UpTo tells you what the receiver can go up to.
func (e *ElkremReceiver) UpTo() uint64 {
if len(e.s) < 1 {
if len(e.Nodes) < 1 {
return 0
}
return e.s[len(e.s)-1].i
return e.Nodes[len(e.Nodes)-1].I
}
8 changes: 4 additions & 4 deletions elkrem/elkrem_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ func TestElkremBig(t *testing.T) {
}
if n%1000 == 999 {
t.Logf("stack with %d received hashes\n", n+1)
for i, n := range rcv.s {
for i, n := range rcv.Nodes {
t.Logf("Stack element %d: index %d height %d %s\n",
i, n.i, n.h, n.sha.String())
i, n.I, n.H, n.Sha.String())
}
}
}
Expand Down Expand Up @@ -54,9 +54,9 @@ func TestElkremLess(t *testing.T) {
}
if n%1000 == 999 {
t.Logf("stack with %d received hashes\n", n+1)
for i, n := range rcv.s {
for i, n := range rcv.Nodes {
t.Logf("Stack element %d: index %d height %d %s\n",
i, n.i, n.h, n.sha.String())
i, n.I, n.H, n.Sha.String())
}
}
}
Expand Down
38 changes: 19 additions & 19 deletions elkrem/serdes.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ prepended with the total number of hashes, so the total max size is 1969 bytes.
// first the number of nodes (1 byte), then a series of 41 byte long
// serialized nodes, which are 1 byte height, 8 byte index, 32 byte hash.
func (e *ElkremReceiver) ToBytes() ([]byte, error) {
numOfNodes := uint8(len(e.s))
numOfNodes := uint8(len(e.Nodes))
// 0 element receiver also OK. Just an empty slice.
if numOfNodes == 0 {
return nil, nil
}
if numOfNodes > maxHeight+1 {
return nil, fmt.Errorf("Broken ElkremReceiver has %d nodes, max 64",
len(e.s))
len(e.Nodes))
}
var buf bytes.Buffer // create buffer

Expand All @@ -34,22 +34,22 @@ func (e *ElkremReceiver) ToBytes() ([]byte, error) {
if err != nil {
return nil, err
}
for _, node := range e.s {
for _, node := range e.Nodes {
// write 1 byte height
err = binary.Write(&buf, binary.BigEndian, node.h)
err = binary.Write(&buf, binary.BigEndian, node.H)
if err != nil {
return nil, err
}
// write 8 byte index
err = binary.Write(&buf, binary.BigEndian, node.i)
err = binary.Write(&buf, binary.BigEndian, node.I)
if err != nil {
return nil, err
}
if node.sha == nil {
return nil, fmt.Errorf("node %d has nil hash", node.i)
if node.Sha == nil {
return nil, fmt.Errorf("node %d has nil hash", node.I)
}
// write 32 byte sha hash
n, err := buf.Write(node.sha.CloneBytes())
n, err := buf.Write(node.Sha.CloneBytes())
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -83,37 +83,37 @@ func ElkremReceiverFromBytes(b []byte) (*ElkremReceiver, error) {
(numOfNodes * 41), buf.Len())
}

e.s = make([]ElkremNode, numOfNodes)
e.Nodes = make([]ElkremNode, numOfNodes)

for j, _ := range e.s {
e.s[j].sha = new(chainhash.Hash)
for j, _ := range e.Nodes {
e.Nodes[j].Sha = new(chainhash.Hash)
// read 1 byte height
err := binary.Read(buf, binary.BigEndian, &e.s[j].h)
err := binary.Read(buf, binary.BigEndian, &e.Nodes[j].H)
if err != nil {
return nil, err
}
// read 8 byte index
err = binary.Read(buf, binary.BigEndian, &e.s[j].i)
err = binary.Read(buf, binary.BigEndian, &e.Nodes[j].I)
if err != nil {
return nil, err
}
// read 32 byte sha hash
err = e.s[j].sha.SetBytes(buf.Next(32))
err = e.Nodes[j].Sha.SetBytes(buf.Next(32))
if err != nil {
return nil, err
}
// sanity check. Note that this doesn't check that index and height
// match. Could add that but it's slow.
if e.s[j].h > maxHeight { // check for super high nodes
return nil, fmt.Errorf("Read invalid node height %d", e.s[j].h)
if e.Nodes[j].H > maxHeight { // check for super high nodes
return nil, fmt.Errorf("Read invalid node height %d", e.Nodes[j].H)
}
if e.s[j].i > maxIndex { // check for index higher than height allows
if e.Nodes[j].I > maxIndex { // check for index higher than height allows
return nil, fmt.Errorf("Node claims index %d; %d max at height %d",
e.s[j].i, maxIndex, e.s[j].h)
e.Nodes[j].I, maxIndex, e.Nodes[j].H)
}

if j > 0 { // check that node heights are descending
if e.s[j-1].h < e.s[j].h {
if e.Nodes[j-1].H < e.Nodes[j].H {
return nil, fmt.Errorf("Node heights out of order")
}
}
Expand Down
4 changes: 2 additions & 2 deletions elkrem/serdes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ func ReceiverSerdesTest(t *testing.T, rcv *ElkremReceiver) {
if err != nil {
t.Fatal(err)
}
t.Logf("rcv2 has len %d\n", len(rcv.s))
t.Logf("rcv2 has len %d\n", len(rcv.Nodes))
t.Logf("Serialized receiver; %d bytes, hex:\n%x\n", len(b), b)

rcv2, err := ElkremReceiverFromBytes(b)
if err != nil {
t.Fatal(err)
}
t.Logf("rcv2 has len %d\n", len(rcv2.s))
t.Logf("rcv2 has len %d\n", len(rcv2.Nodes))
b2, err := rcv2.ToBytes()
if err != nil {
t.Fatal(err)
Expand Down
1 change: 1 addition & 0 deletions litrpc/chancmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ func (r *LitRPC) Push(args PushArgs, reply *PushReply) error {

err = r.Node.PushChannel(qc, uint32(args.Amt), args.Data)
if err != nil {
logging.Errorf("Push error: %s\n", err.Error())
return err
}

Expand Down
4 changes: 2 additions & 2 deletions qln/close.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import (
"fmt"
"time"

"github.com/mit-dci/lit/crypto/koblitz"
"github.com/mit-dci/lit/btcutil/chaincfg/chainhash"
"github.com/mit-dci/lit/btcutil/txscript"
"github.com/mit-dci/lit/crypto/fastsha256"
"github.com/mit-dci/lit/crypto/koblitz"
"github.com/mit-dci/lit/lnutil"
"github.com/mit-dci/lit/logging"
"github.com/mit-dci/lit/portxo"
Expand Down Expand Up @@ -82,8 +82,8 @@ func (nd *LitNode) CoopClose(q *Qchan) error {
// we don't accept payments on this channel anymore.

outMsg := lnutil.NewCloseReqMsg(q.Peer(), q.Op, signature)

nd.tmpSendLitMsg(outMsg)

return nil
}

Expand Down
2 changes: 1 addition & 1 deletion qln/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ func (nd *LitNode) OpenDB(filename string) error {
}
// create buckets if they're not already there
err = nd.LitDB.Update(func(btx *bolt.Tx) error {
_, err := btx.CreateBucketIfNotExists(BKTChannel)
_, err := btx.CreateBucketIfNotExists(BKTChannelData)
if err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions qln/justicetx.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ func (nd *LitNode) BuildJusticeSig(q *Qchan) error {

jtxid := justiceTx.TxHash()
logging.Infof("made justice tx %s\n", jtxid.String())

// get hashcache for signing
hCache := txscript.NewTxSigHashes(justiceTx)

Expand Down
Loading

0 comments on commit c691d1d

Please sign in to comment.