Beispiel #1
0
func putChanCommitTxns(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
	var bc bytes.Buffer
	if err := writeOutpoint(&bc, channel.ChanID); err != nil {
		return err
	}
	txnsKey := make([]byte, len(commitTxnsKey)+bc.Len())
	copy(txnsKey[:3], commitTxnsKey)
	copy(txnsKey[3:], bc.Bytes())

	var b bytes.Buffer

	if err := channel.OurCommitTx.Serialize(&b); err != nil {
		return err
	}

	if err := wire.WriteVarBytes(&b, 0, channel.OurCommitSig); err != nil {
		return err
	}

	// TODO(roasbeef): should move this into putChanFundingInfo
	scratch := make([]byte, 4)
	byteOrder.PutUint32(scratch, channel.LocalCsvDelay)
	if _, err := b.Write(scratch); err != nil {
		return err
	}
	byteOrder.PutUint32(scratch, channel.RemoteCsvDelay)
	if _, err := b.Write(scratch); err != nil {
		return err
	}

	return nodeChanBucket.Put(txnsKey, b.Bytes())
}
Beispiel #2
0
func putChanDeliveryScripts(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
	var bc bytes.Buffer
	if err := writeOutpoint(&bc, channel.ChanID); err != nil {
		return err
	}
	deliveryKey := make([]byte, len(deliveryScriptsKey)+bc.Len())
	copy(deliveryKey[:3], deliveryScriptsKey)
	copy(deliveryKey[3:], bc.Bytes())

	var b bytes.Buffer
	if err := wire.WriteVarBytes(&b, 0, channel.OurDeliveryScript); err != nil {
		return err
	}
	if err := wire.WriteVarBytes(&b, 0, channel.TheirDeliveryScript); err != nil {
		return err
	}

	return nodeChanBucket.Put(deliveryScriptsKey, b.Bytes())
}
Beispiel #3
0
func putChanElkremState(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
	var bc bytes.Buffer
	if err := writeOutpoint(&bc, channel.ChanID); err != nil {
		return err
	}

	elkremKey := make([]byte, len(elkremStateKey)+bc.Len())
	copy(elkremKey[:3], elkremStateKey)
	copy(elkremKey[3:], bc.Bytes())

	var b bytes.Buffer

	revKey := channel.TheirCurrentRevocation.SerializeCompressed()
	if err := wire.WriteVarBytes(&b, 0, revKey); err != nil {
		return err
	}

	if _, err := b.Write(channel.TheirCurrentRevocationHash[:]); err != nil {
		return err
	}

	// TODO(roasbeef): shouldn't be storing on disk, should re-derive as
	// needed
	senderBytes := channel.LocalElkrem.ToBytes()
	if err := wire.WriteVarBytes(&b, 0, senderBytes); err != nil {
		return err
	}

	reciverBytes, err := channel.RemoteElkrem.ToBytes()
	if err != nil {
		return err
	}
	if err := wire.WriteVarBytes(&b, 0, reciverBytes); err != nil {
		return err
	}

	return nodeChanBucket.Put(elkremKey, b.Bytes())
}
Beispiel #4
0
func putChanFundingInfo(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
	var bc bytes.Buffer
	if err := writeOutpoint(&bc, channel.ChanID); err != nil {
		return err
	}
	fundTxnKey := make([]byte, len(fundingTxnKey)+bc.Len())
	copy(fundTxnKey[:3], fundingTxnKey)
	copy(fundTxnKey[3:], bc.Bytes())

	var b bytes.Buffer

	if err := writeOutpoint(&b, channel.FundingOutpoint); err != nil {
		return err
	}

	ourSerKey := channel.OurMultiSigKey.SerializeCompressed()
	if err := wire.WriteVarBytes(&b, 0, ourSerKey); err != nil {
		return err
	}
	theirSerKey := channel.TheirMultiSigKey.SerializeCompressed()
	if err := wire.WriteVarBytes(&b, 0, theirSerKey); err != nil {
		return err
	}

	if err := wire.WriteVarBytes(&b, 0, channel.FundingWitnessScript[:]); err != nil {
		return err
	}

	scratch := make([]byte, 8)
	byteOrder.PutUint64(scratch, uint64(channel.CreationTime.Unix()))

	if _, err := b.Write(scratch); err != nil {
		return err
	}

	return nodeChanBucket.Put(fundTxnKey, b.Bytes())
}
Beispiel #5
0
func serializeInvoice(w io.Writer, i *Invoice) error {
	if err := wire.WriteVarBytes(w, 0, i.Memo[:]); err != nil {
		return err
	}
	if err := wire.WriteVarBytes(w, 0, i.Receipt[:]); err != nil {
		return err
	}

	birthBytes, err := i.CreationDate.MarshalBinary()
	if err != nil {
		return err
	}
	if err := wire.WriteVarBytes(w, 0, birthBytes); err != nil {
		return err
	}

	if _, err := w.Write(i.Terms.PaymentPreimage[:]); err != nil {
		return err
	}

	var scratch [8]byte
	byteOrder.PutUint64(scratch[:], uint64(i.Terms.Value))
	if _, err := w.Write(scratch[:]); err != nil {
		return err
	}

	var settleByte [1]byte
	if i.Terms.Settled {
		settleByte[0] = 1
	}
	if _, err := w.Write(settleByte[:]); err != nil {
		return err
	}

	return nil
}
Beispiel #6
0
func writeOutpoint(w io.Writer, o *wire.OutPoint) error {
	// TODO(roasbeef): make all scratch buffers on the stack
	scratch := make([]byte, 4)

	// TODO(roasbeef): write raw 32 bytes instead of wasting the extra
	// byte.
	if err := wire.WriteVarBytes(w, 0, o.Hash[:]); err != nil {
		return err
	}

	byteOrder.PutUint32(scratch, o.Index)
	if _, err := w.Write(scratch); err != nil {
		return err
	}

	return nil
}
Beispiel #7
0
// writeElement is a one-stop shop to write the big endian representation of
// any element which is to be serialized for the wire protocol. The passed
// io.Writer should be backed by an appropriatly sized byte slice, or be able
// to dynamically expand to accomdate additional data.
//
// TODO(roasbeef): this should eventually draw from a buffer pool for
// serialization.
// TODO(roasbeef): switch to var-ints for all?
func writeElement(w io.Writer, element interface{}) error {
	switch e := element.(type) {
	case uint8:
		var b [1]byte
		b[0] = byte(e)
		if _, err := w.Write(b[:]); err != nil {
			return err
		}
	case uint16:
		var b [2]byte
		binary.BigEndian.PutUint16(b[:], uint16(e))
		if _, err := w.Write(b[:]); err != nil {
			return err
		}
	case ErrorCode:
		var b [2]byte
		binary.BigEndian.PutUint16(b[:], uint16(e))
		if _, err := w.Write(b[:]); err != nil {
			return err
		}
	case CreditsAmount:
		if err := binary.Write(w, binary.BigEndian, int64(e)); err != nil {
			return err
		}
	case uint32:
		var b [4]byte
		binary.BigEndian.PutUint32(b[:], uint32(e))
		if _, err := w.Write(b[:]); err != nil {
			return err
		}
	case uint64:
		var b [8]byte
		binary.BigEndian.PutUint64(b[:], uint64(e))
		if _, err := w.Write(b[:]); err != nil {
			return err
		}
	case HTLCKey:
		if err := binary.Write(w, binary.BigEndian, int64(e)); err != nil {
			return err
		}
	case btcutil.Amount:
		if err := binary.Write(w, binary.BigEndian, int64(e)); err != nil {
			return err
		}
	case *btcec.PublicKey:
		var b [33]byte
		serializedPubkey := e.SerializeCompressed()
		copy(b[:], serializedPubkey)
		// TODO(roasbeef): use WriteVarBytes here?
		if _, err := w.Write(b[:]); err != nil {
			return err
		}
	case []uint64:
		// Enforce a max number of elements in a uint64 slice.
		numItems := len(e)
		if numItems > 65535 {
			return fmt.Errorf("Too many []uint64s")
		}

		// First write out the the number of elements in the slice as a
		// length prefix.
		if err := writeElement(w, uint16(numItems)); err != nil {
			return err
		}

		// After the prefix detailing the number of elements, write out
		// each uint64 in series.
		for i := 0; i < numItems; i++ {
			if err := writeElement(w, e[i]); err != nil {
				return err
			}
		}
	case []*btcec.Signature:
		// Enforce a sane number for the maximum number of signatures.
		numSigs := len(e)
		if numSigs > 127 {
			return fmt.Errorf("Too many signatures!")
		}

		// First write out the the number of elements in the slice as a
		// length prefix.
		if err := writeElement(w, uint8(numSigs)); err != nil {
			return err
		}

		// After the prefix detailing the number of elements, write out
		// each signature in series.
		for i := 0; i < numSigs; i++ {
			if err := writeElement(w, e[i]); err != nil {
				return err
			}
		}
	case *btcec.Signature:
		sig := e.Serialize()
		if len(sig) > 73 {
			return fmt.Errorf("Signature too long!")
		}

		if err := wire.WriteVarBytes(w, 0, sig); err != nil {
			return err
		}
	case *wire.ShaHash:
		if _, err := w.Write(e[:]); err != nil {
			return err
		}
	case [][32]byte:
		// First write out the number of elements in the slice.
		sliceSize := len(e)
		if err := writeElement(w, uint16(sliceSize)); err != nil {
			return err
		}

		// Then write each out sequentially.
		for _, element := range e {
			if err := writeElement(w, element); err != nil {
				return err
			}
		}
	case [32]byte:
		// TODO(roasbeef): should be factor out to caller logic...
		if _, err := w.Write(e[:]); err != nil {
			return err
		}
	case wire.BitcoinNet:
		var b [4]byte
		binary.BigEndian.PutUint32(b[:], uint32(e))
		if _, err := w.Write(b[:]); err != nil {
			return err
		}
	case []byte:
		// Enforce the maxmium length of all slices used in the wire
		// protocol.
		sliceLength := len(e)
		if sliceLength > MaxSliceLength {
			return fmt.Errorf("Slice length too long!")
		}

		if err := wire.WriteVarBytes(w, 0, e); err != nil {
			return err
		}
	case PkScript:
		// Make sure it's P2PKH or P2SH size or less.
		scriptLength := len(e)
		if scriptLength > 25 {
			return fmt.Errorf("PkScript too long!")
		}

		if err := wire.WriteVarBytes(w, 0, e); err != nil {
			return err
		}
	case string:
		strlen := len(e)
		if strlen > MaxSliceLength {
			return fmt.Errorf("String too long!")
		}

		if err := wire.WriteVarString(w, 0, e); err != nil {
			return err
		}
	case []*wire.TxIn:
		// Write the size (1-byte)
		if len(e) > 127 {
			return fmt.Errorf("Too many txins")
		}

		// Write out the number of txins.
		if err := writeElement(w, uint8(len(e))); err != nil {
			return err
		}

		// Append the actual TxIns (Size: NumOfTxins * 36)
		// During serialization we leave out the sequence number to
		// eliminate any funny business.
		for _, in := range e {
			if err := writeElement(w, in); err != nil {
				return err
			}
		}
	case *wire.TxIn:
		// First write out the previous txid.
		var h [32]byte
		copy(h[:], e.PreviousOutPoint.Hash[:])
		if _, err := w.Write(h[:]); err != nil {
			return err
		}

		// Then the exact index of the previous out point.
		var idx [4]byte
		binary.BigEndian.PutUint32(idx[:], e.PreviousOutPoint.Index)
		if _, err := w.Write(idx[:]); err != nil {
			return err
		}
	case *wire.OutPoint:
		// TODO(roasbeef): consolidate with above
		// First write out the previous txid.
		var h [32]byte
		copy(h[:], e.Hash[:])
		if _, err := w.Write(h[:]); err != nil {
			return err
		}

		// Then the exact index of this output.
		var idx [4]byte
		binary.BigEndian.PutUint32(idx[:], e.Index)
		if _, err := w.Write(idx[:]); err != nil {
			return err
		}
		// TODO(roasbeef): *MsgTx
	default:
		return fmt.Errorf("Unknown type in writeElement: %T", e)
	}

	return nil
}