diff --git a/wire/blockheader.go b/wire/blockheader.go index 941d40a54..e017fc96f 100644 --- a/wire/blockheader.go +++ b/wire/blockheader.go @@ -115,13 +115,11 @@ func NewBlockHeader(prevHash *ShaHash, merkleRootHash *ShaHash, bits uint32, // decoding block headers stored to disk, such as in a database, as opposed to // decoding from the wire. func readBlockHeader(r io.Reader, pver uint32, bh *BlockHeader) error { - var sec uint32 - err := readElements(r, &bh.Version, &bh.PrevBlock, &bh.MerkleRoot, &sec, - &bh.Bits, &bh.Nonce) + err := readElements(r, &bh.Version, &bh.PrevBlock, &bh.MerkleRoot, + (*uint32Time)(&bh.Timestamp), &bh.Bits, &bh.Nonce) if err != nil { return err } - bh.Timestamp = time.Unix(int64(sec), 0) return nil } diff --git a/wire/common.go b/wire/common.go index 033d3dad4..ca8aa280c 100644 --- a/wire/common.go +++ b/wire/common.go @@ -10,6 +10,7 @@ import ( "fmt" "io" "math" + "time" "github.com/btcsuite/fastsha256" ) @@ -175,6 +176,16 @@ var binarySerializer binaryFreeList = make(chan []byte, binaryFreeListMaxItems) var errNonCanonicalVarInt = "non-canonical varint %x - discriminant %x must " + "encode a value greater than %x" +// uint32Time represents a unix timestamp encoded with a uint32. It is used as +// a way to signal the readElement function how to decode a timestamp into a Go +// time.Time since it is otherwise ambiguous. +type uint32Time time.Time + +// int64Time represents a unix timestamp encoded with an int64. It is used as +// a way to signal the readElement function how to decode a timestamp into a Go +// time.Time since it is otherwise ambiguous. +type int64Time time.Time + // readElement reads the next sequence of bytes from r using little endian // depending on the concrete type of element pointed to. func readElement(r io.Reader, element interface{}) error { @@ -225,6 +236,24 @@ func readElement(r io.Reader, element interface{}) error { } return nil + // Unix timestamp encoded as a uint32. + case *uint32Time: + rv, err := binarySerializer.Uint32(r, binary.LittleEndian) + if err != nil { + return err + } + *e = uint32Time(time.Unix(int64(rv), 0)) + return nil + + // Unix timestamp encoded as an int64. + case *int64Time: + rv, err := binarySerializer.Uint64(r, binary.LittleEndian) + if err != nil { + return err + } + *e = int64Time(time.Unix(int64(rv), 0)) + return nil + // Message header checksum. case *[4]byte: _, err := io.ReadFull(r, e[:]) diff --git a/wire/msgversion.go b/wire/msgversion.go index 6fd3fc6b0..b8e96d253 100644 --- a/wire/msgversion.go +++ b/wire/msgversion.go @@ -84,12 +84,11 @@ func (msg *MsgVersion) BtcDecode(r io.Reader, pver uint32) error { "*bytes.Buffer") } - var sec int64 - err := readElements(buf, &msg.ProtocolVersion, &msg.Services, &sec) + err := readElements(buf, &msg.ProtocolVersion, &msg.Services, + (*int64Time)(&msg.Timestamp)) if err != nil { return err } - msg.Timestamp = time.Unix(sec, 0) err = readNetAddress(buf, pver, &msg.AddrYou, false) if err != nil { diff --git a/wire/netaddress.go b/wire/netaddress.go index bd58a9c12..6c3e65a1a 100644 --- a/wire/netaddress.go +++ b/wire/netaddress.go @@ -105,7 +105,6 @@ func NewNetAddress(addr net.Addr, services ServiceFlag) (*NetAddress, error) { // version and whether or not the timestamp is included per ts. Some messages // like version do not include the timestamp. func readNetAddress(r io.Reader, pver uint32, na *NetAddress, ts bool) error { - var timestamp time.Time var services ServiceFlag var ip [16]byte @@ -113,12 +112,10 @@ func readNetAddress(r io.Reader, pver uint32, na *NetAddress, ts bool) error { // stop working somewhere around 2106. Also timestamp wasn't added until // protocol version >= NetAddressTimeVersion if ts && pver >= NetAddressTimeVersion { - var stamp uint32 - err := readElement(r, &stamp) + err := readElement(r, (*uint32Time)(&na.Timestamp)) if err != nil { return err } - timestamp = time.Unix(int64(stamp), 0) } err := readElements(r, &services, &ip) @@ -131,7 +128,6 @@ func readNetAddress(r io.Reader, pver uint32, na *NetAddress, ts bool) error { return err } - na.Timestamp = timestamp na.Services = services na.SetAddress(net.IP(ip[:]), port) return nil