diff --git a/blockheader.go b/blockheader.go index 2b74fcc9..12b53013 100644 --- a/blockheader.go +++ b/blockheader.go @@ -107,7 +107,7 @@ func readBlockHeader(r io.Reader, pver uint32, bh *BlockHeader) error { // writeBlockHeader writes a bitcoin block header to w. func writeBlockHeader(w io.Writer, pver uint32, bh *BlockHeader) error { sec := uint32(bh.Timestamp.Unix()) - err := writeElements(w, bh.Version, bh.PrevBlock, bh.MerkleRoot, + err := writeElements(w, bh.Version, &bh.PrevBlock, &bh.MerkleRoot, sec, bh.Bits, bh.Nonce) if err != nil { return err diff --git a/common.go b/common.go index 4822db07..299b9f6f 100644 --- a/common.go +++ b/common.go @@ -17,9 +17,7 @@ import ( const maxVarIntPayload = 9 // readElement reads the next sequence of bytes from r using little endian -// depending on the concrete type of element pointed to. It also accepts a -// scratch buffer that is used for the primitive values rather than creating -// a new buffer on every call. +// depending on the concrete type of element pointed to. func readElement(r io.Reader, element interface{}) error { var scratch [8]byte @@ -140,6 +138,106 @@ func readElements(r io.Reader, elements ...interface{}) error { // writeElement writes the little endian representation of element to w. func writeElement(w io.Writer, element interface{}) error { + var scratch [8]byte + + // Attempt to read the element based on the concrete type via fast + // type assertions first. + switch e := element.(type) { + case int32: + b := scratch[0:4] + binary.LittleEndian.PutUint32(b, uint32(e)) + _, err := w.Write(b) + if err != nil { + return err + } + return nil + + case uint32: + b := scratch[0:4] + binary.LittleEndian.PutUint32(b, e) + _, err := w.Write(b) + if err != nil { + return err + } + return nil + + case int64: + b := scratch[0:8] + binary.LittleEndian.PutUint64(b, uint64(e)) + _, err := w.Write(b) + if err != nil { + return err + } + return nil + + case uint64: + b := scratch[0:8] + binary.LittleEndian.PutUint64(b, e) + _, err := w.Write(b) + if err != nil { + return err + } + return nil + + // Message header checksum. + case [4]byte: + _, err := w.Write(e[:]) + if err != nil { + return err + } + return nil + + // Message header command. + case [commandSize]uint8: + _, err := w.Write(e[:]) + if err != nil { + return err + } + return nil + + // IP address. + case [16]byte: + _, err := w.Write(e[:]) + if err != nil { + return err + } + return nil + + case *ShaHash: + _, err := w.Write(e[:]) + if err != nil { + return err + } + return nil + + case ServiceFlag: + b := scratch[0:8] + binary.LittleEndian.PutUint64(b, uint64(e)) + _, err := w.Write(b) + if err != nil { + return err + } + return nil + + case InvType: + b := scratch[0:4] + binary.LittleEndian.PutUint32(b, uint32(e)) + _, err := w.Write(b) + if err != nil { + return err + } + return nil + + case BitcoinNet: + b := scratch[0:4] + binary.LittleEndian.PutUint32(b, uint32(e)) + _, err := w.Write(b) + if err != nil { + return err + } + return nil + } + return binary.Write(w, binary.LittleEndian, element) } diff --git a/invvect.go b/invvect.go index 1cac91b5..a45cfbde 100644 --- a/invvect.go +++ b/invvect.go @@ -72,7 +72,7 @@ func readInvVect(r io.Reader, pver uint32, iv *InvVect) error { // writeInvVect serializes an InvVect to w depending on the protocol version. func writeInvVect(w io.Writer, pver uint32, iv *InvVect) error { - err := writeElements(w, iv.Type, iv.Hash) + err := writeElements(w, iv.Type, &iv.Hash) if err != nil { return err } diff --git a/msggetblocks.go b/msggetblocks.go index 9f083630..848fe159 100644 --- a/msggetblocks.go +++ b/msggetblocks.go @@ -110,7 +110,7 @@ func (msg *MsgGetBlocks) BtcEncode(w io.Writer, pver uint32) error { } } - err = writeElement(w, msg.HashStop) + err = writeElement(w, &msg.HashStop) if err != nil { return err } diff --git a/msggetheaders.go b/msggetheaders.go index b360203a..e0c91146 100644 --- a/msggetheaders.go +++ b/msggetheaders.go @@ -108,7 +108,7 @@ func (msg *MsgGetHeaders) BtcEncode(w io.Writer, pver uint32) error { } } - err = writeElement(w, msg.HashStop) + err = writeElement(w, &msg.HashStop) if err != nil { return err }