From 25c0c41f51e398cf57e36bb035be08c80f65b4f5 Mon Sep 17 00:00:00 2001 From: noface Date: Wed, 22 Feb 2023 02:40:40 +0100 Subject: [PATCH] test blocksig read and write convert tx timestamp to time.Time --- blockchain/validate.go | 15 +++++++-------- chaincfg/genesis.go | 4 +++- wire/bench_test.go | 2 +- wire/blockheader.go | 21 +++++++++++++++------ wire/blockheader_test.go | 2 +- wire/msgblock.go | 31 +++++++++++++++++++++++-------- wire/msgheaders.go | 24 ++++++++++++++++++++++-- wire/msgmerkleblock.go | 2 +- wire/msgtx.go | 14 ++++++++------ 9 files changed, 81 insertions(+), 34 deletions(-) diff --git a/blockchain/validate.go b/blockchain/validate.go index ccab3ca404f..b460afd8a37 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -203,7 +203,6 @@ func CalcBlockSubsidy(height int32, chainParams *chaincfg.Params) int64 { // CheckTransactionSanity performs some preliminary checks on a transaction to // ensure it is sane. These checks are context free. func CheckTransactionSanity(tx *btcutil.Tx) error { - return nil // todo ppc // A transaction must have at least one input. msgTx := tx.MsgTx() if len(msgTx.TxIn) == 0 { @@ -514,8 +513,6 @@ func checkBlockSanity(block *btcutil.Block, powLimit *big.Int, timeSource Median } } - return nil // todo ppc - // Do some preliminary checks on each transaction to ensure they are // sane before continuing. for _, tx := range transactions { @@ -646,12 +643,12 @@ func checkSerializedHeight(coinbaseTx *btcutil.Tx, wantHeight int32) error { // // This function MUST be called with the chain state lock held (for writes). func (b *BlockChain) checkBlockHeaderContext(header *wire.BlockHeader, prevNode *blockNode, flags BehaviorFlags) error { - return nil // todo ppc fastAdd := flags&BFFastAdd == BFFastAdd if !fastAdd { // Ensure the difficulty specified in the block header matches // the calculated difficulty based on the previous block and // difficulty retarget rules. + /* todo ppc expectedDifficulty, err := b.calcNextRequiredDifficulty(prevNode, header.Timestamp) if err != nil { @@ -663,6 +660,7 @@ func (b *BlockChain) checkBlockHeaderContext(header *wire.BlockHeader, prevNode str = fmt.Sprintf(str, blockDifficulty, expectedDifficulty) return ruleError(ErrUnexpectedDifficulty, str) } + */ // Ensure the timestamp for the block header is after the // median time of the last several blocks (medianTimeBlocks). @@ -704,6 +702,7 @@ func (b *BlockChain) checkBlockHeaderContext(header *wire.BlockHeader, prevNode // Reject outdated block versions once a majority of the network // has upgraded. These were originally voted on by BIP0034, // BIP0065, and BIP0066. + /* todo ppc params := b.chainParams if header.Version < 2 && blockHeight >= params.BIP0034Height || header.Version < 3 && blockHeight >= params.BIP0066Height || @@ -713,6 +712,7 @@ func (b *BlockChain) checkBlockHeaderContext(header *wire.BlockHeader, prevNode str = fmt.Sprintf(str, header.Version) return ruleError(ErrBlockVersionTooOld, str) } + */ return nil } @@ -957,14 +957,12 @@ func CheckTransactionInputs(tx *btcutil.Tx, txHeight int32, utxoView *UtxoViewpo } // Ensure the transaction does not spend more than its inputs. - /* todo ppc if totalSatoshiIn < totalSatoshiOut { str := fmt.Sprintf("total value of all transaction inputs for "+ "transaction %v is %v which is less than the amount "+ "spent of %v", tx.Hash(), totalSatoshiIn, totalSatoshiOut) return 0, ruleError(ErrSpendTooHigh, str) } - */ // NOTE: bitcoind checks if the transaction fees are < 0 here, but that // is an impossible condition because of the check above that ensures @@ -1105,9 +1103,9 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, vi // against all the inputs when the signature operations are out of // bounds. // todo ppc - var totalFees int64 + // var totalFees int64 for _, tx := range transactions { - // todo ppc + /* todo ppc txFee, err := CheckTransactionInputs(tx, node.height, view, b.chainParams) if err != nil { @@ -1122,6 +1120,7 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, vi return ruleError(ErrBadFees, "total fees for block "+ "overflows accumulator") } + */ // Add all of the outputs for this transaction which are not // provably unspendable as available utxos. Also, the passed diff --git a/chaincfg/genesis.go b/chaincfg/genesis.go index b2086aaac9b..55e3a68611e 100644 --- a/chaincfg/genesis.go +++ b/chaincfg/genesis.go @@ -57,7 +57,7 @@ var genesisCoinbaseTx = wire.MsgTx{ var genesisCoinbaseTxPPC = wire.MsgTx{ Version: 1, - Timestamp: 0x502c59a2, // todo ppc change to time.Time? + Timestamp: time.Unix(0x502c59a2, 0), TxIn: []*wire.TxIn{ { PreviousOutPoint: wire.OutPoint{ @@ -128,6 +128,7 @@ var genesisBlock = wire.MsgBlock{ Nonce: 0x7c2bac1d, // 2083236893 }, Transactions: []*wire.MsgTx{&genesisCoinbaseTx}, + Signature: []byte{}, } var genesisBlockPPC = wire.MsgBlock{ @@ -217,6 +218,7 @@ var testNet3GenesisBlockPPC = wire.MsgBlock{ Nonce: 0x07533a5a, }, Transactions: []*wire.MsgTx{&genesisCoinbaseTxPPC}, + Signature: []byte{}, } // simNetGenesisHash is the hash of the first block in the block chain for the diff --git a/wire/bench_test.go b/wire/bench_test.go index 5176c962e80..c18798cb55d 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -374,7 +374,7 @@ func BenchmarkReadBlockHeader(b *testing.B) { func BenchmarkWriteBlockHeader(b *testing.B) { header := blockOne.Header for i := 0; i < b.N; i++ { - writeBlockHeader(ioutil.Discard, 0, &header) + writeBlockHeader(ioutil.Discard, 0, &header, true) } } diff --git a/wire/blockheader.go b/wire/blockheader.go index 9c9c2237e63..79174be609b 100644 --- a/wire/blockheader.go +++ b/wire/blockheader.go @@ -38,6 +38,9 @@ type BlockHeader struct { // Nonce used to generate the block. Nonce uint32 + + // peercoin: proof-of-stake related block index fields. + Flags uint32 } // blockHeaderLen is a constant that represents the number of bytes for a block @@ -51,7 +54,7 @@ func (h *BlockHeader) BlockHash() chainhash.Hash { // encode could fail except being out of memory which would cause a // run-time panic. buf := bytes.NewBuffer(make([]byte, 0, MaxBlockHeaderPayload)) - _ = writeBlockHeader(buf, 0, h) + _ = writeBlockHeader(buf, 0, h, false) return chainhash.DoubleHashH(buf.Bytes()) } @@ -69,7 +72,7 @@ func (h *BlockHeader) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) e // See Serialize for encoding block headers to be stored to disk, such as in a // database, as opposed to encoding block headers for the wire. func (h *BlockHeader) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error { - return writeBlockHeader(w, pver, h) + return writeBlockHeader(w, pver, h, true) } // Deserialize decodes a block header from r into the receiver using a format @@ -89,7 +92,7 @@ func (h *BlockHeader) Serialize(w io.Writer) error { // At the current time, there is no difference between the wire encoding // at protocol version 0 and the stable long-term storage format. As // a result, make use of writeBlockHeader. - return writeBlockHeader(w, 0, h) + return writeBlockHeader(w, 0, h, true) } // NewBlockHeader returns a new BlockHeader using the provided version, previous @@ -107,6 +110,7 @@ func NewBlockHeader(version int32, prevHash, merkleRootHash *chainhash.Hash, Timestamp: time.Unix(time.Now().Unix(), 0), Bits: bits, Nonce: nonce, + Flags: 0, // todo ppc } } @@ -115,14 +119,19 @@ func NewBlockHeader(version int32, prevHash, merkleRootHash *chainhash.Hash, // decoding from the wire. func readBlockHeader(r io.Reader, pver uint32, bh *BlockHeader) error { return readElements(r, &bh.Version, &bh.PrevBlock, &bh.MerkleRoot, - (*uint32Time)(&bh.Timestamp), &bh.Bits, &bh.Nonce) + (*uint32Time)(&bh.Timestamp), &bh.Bits, &bh.Nonce, &bh.Flags) } // writeBlockHeader writes a bitcoin block header to w. See Serialize for // encoding block headers to be stored to disk, such as in a database, as // opposed to encoding for the wire. -func writeBlockHeader(w io.Writer, pver uint32, bh *BlockHeader) error { +func writeBlockHeader(w io.Writer, pver uint32, bh *BlockHeader, sFlag bool) error { sec := uint32(bh.Timestamp.Unix()) - return writeElements(w, bh.Version, &bh.PrevBlock, &bh.MerkleRoot, + err := writeElements(w, bh.Version, &bh.PrevBlock, &bh.MerkleRoot, sec, bh.Bits, bh.Nonce) + if sFlag { + // todo ppc this is experimental. remove sFlag and write meta flags elsewhere + err = writeElement(w, bh.Flags) + } + return err } diff --git a/wire/blockheader_test.go b/wire/blockheader_test.go index fef069679fc..7bb896b7cd0 100644 --- a/wire/blockheader_test.go +++ b/wire/blockheader_test.go @@ -135,7 +135,7 @@ func TestBlockHeaderWire(t *testing.T) { for i, test := range tests { // Encode to wire format. var buf bytes.Buffer - err := writeBlockHeader(&buf, test.pver, test.in) + err := writeBlockHeader(&buf, test.pver, test.in, true) if err != nil { t.Errorf("writeBlockHeader #%d error %v", i, err) continue diff --git a/wire/msgblock.go b/wire/msgblock.go index ffc7b69d211..5a1d742db37 100644 --- a/wire/msgblock.go +++ b/wire/msgblock.go @@ -43,7 +43,7 @@ type TxLoc struct { type MsgBlock struct { Header BlockHeader Transactions []*MsgTx - BlockSig []byte // todo ppc unused + Signature []byte // todo ppc unused } // AddTransaction adds a transaction to the message. @@ -68,11 +68,6 @@ func (msg *MsgBlock) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) er return err } - // todo ppc some flag we dont deal with yet - if msg.Header.PrevBlock.String() != "0000000000000000000000000000000000000000000000000000000000000000" { - _, err = binarySerializer.Uint32(r, littleEndian) - } - txCount, err := ReadVarInt(r, pver) if err != nil { return err @@ -97,7 +92,12 @@ func (msg *MsgBlock) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) er msg.Transactions = append(msg.Transactions, &tx) } - msg.BlockSig = nil + // todo ppc cap maxAllowed to 72? + msg.Signature, err = ReadVarBytes(r, pver, MaxMessagePayload, + "block signature") + if err != nil { + return err + } return nil } @@ -174,6 +174,12 @@ func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, error) { txLocs[i].TxLen = (fullLen - r.Len()) - txLocs[i].TxStart } + msg.Signature, err = ReadVarBytes(r, 0, MaxMessagePayload, + "block signature") + if err != nil { + return nil, err + } + return txLocs, nil } @@ -182,7 +188,7 @@ func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, error) { // See Serialize for encoding blocks to be stored to disk, such as in a // database, as opposed to encoding blocks for the wire. func (msg *MsgBlock) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error { - err := writeBlockHeader(w, pver, &msg.Header) + err := writeBlockHeader(w, pver, &msg.Header, true) if err != nil { return err } @@ -199,6 +205,12 @@ func (msg *MsgBlock) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) er } } + // todo ppc write blocksig here + err = WriteVarBytes(w, pver, msg.Signature) + if err != nil { + return err + } + return nil } @@ -242,6 +254,8 @@ func (msg *MsgBlock) SerializeSize() int { n += tx.SerializeSize() } + n += VarIntSerializeSize(uint64(len(msg.Signature))) + len(msg.Signature) + return n } @@ -294,5 +308,6 @@ func NewMsgBlock(blockHeader *BlockHeader) *MsgBlock { return &MsgBlock{ Header: *blockHeader, Transactions: make([]*MsgTx, 0, defaultTransactionAlloc), + Signature: []byte{}, } } diff --git a/wire/msgheaders.go b/wire/msgheaders.go index 7d18d930e0b..6f4ab34acfc 100644 --- a/wire/msgheaders.go +++ b/wire/msgheaders.go @@ -71,6 +71,20 @@ func (msg *MsgHeaders) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) "transactions [count %v]", txCount) return messageError("MsgHeaders.BtcDecode", str) } + + // todo ppc read signature length + signatureLength, err := ReadVarInt(r, pver) + if err != nil { + return err + } + + // todo ppc verify signature length + if signatureLength > 0 { + str := fmt.Sprintf("block headers may not contain "+ + "signature [length %v]", signatureLength) + return messageError("MsgHeaders.BtcDecode", str) + } + msg.AddBlockHeader(bh) } @@ -94,7 +108,7 @@ func (msg *MsgHeaders) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) } for _, bh := range msg.Headers { - err := writeBlockHeader(w, pver, bh) + err := writeBlockHeader(w, pver, bh, true) if err != nil { return err } @@ -107,6 +121,12 @@ func (msg *MsgHeaders) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) if err != nil { return err } + + // todo ppc write signature length + err = WriteVarInt(w, pver, 0) + if err != nil { + return err + } } return nil @@ -123,7 +143,7 @@ func (msg *MsgHeaders) Command() string { func (msg *MsgHeaders) MaxPayloadLength(pver uint32) uint32 { // Num headers (varInt) + max allowed headers (header length + 1 byte // for the number of transactions which is always 0). - return MaxVarIntPayload + ((MaxBlockHeaderPayload + 1) * + return MaxVarIntPayload + ((MaxBlockHeaderPayload + 5) * MaxBlockHeadersPerMsg) } diff --git a/wire/msgmerkleblock.go b/wire/msgmerkleblock.go index d2ee4721783..f221cafacb3 100644 --- a/wire/msgmerkleblock.go +++ b/wire/msgmerkleblock.go @@ -111,7 +111,7 @@ func (msg *MsgMerkleBlock) BtcEncode(w io.Writer, pver uint32, enc MessageEncodi return messageError("MsgMerkleBlock.BtcDecode", str) } - err := writeBlockHeader(w, pver, &msg.Header) + err := writeBlockHeader(w, pver, &msg.Header, true) if err != nil { return err } diff --git a/wire/msgtx.go b/wire/msgtx.go index 6aa48191aa2..86cbf1b7c1c 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -9,6 +9,7 @@ import ( "fmt" "io" "strconv" + "time" "github.com/btcsuite/btcd/chaincfg/chainhash" ) @@ -315,7 +316,7 @@ func NewTxOut(value int64, pkScript []byte) *TxOut { // inputs and outputs. type MsgTx struct { Version int32 - Timestamp uint32 + Timestamp time.Time TxIn []*TxIn TxOut []*TxOut LockTime uint32 @@ -445,12 +446,12 @@ func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error msg.Version = int32(version) if version < 3 { - msg.Timestamp, err = binarySerializer.Uint32(r, littleEndian) + err = readElement(r, (*uint32Time)(&msg.Timestamp)) if err != nil { return err } } else { - msg.Timestamp = 0 + msg.Timestamp = time.Unix(0, 0) } count, err := ReadVarInt(r, pver) @@ -726,7 +727,7 @@ func (msg *MsgTx) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error } if msg.Version < 3 { - err = binarySerializer.PutUint32(w, littleEndian, msg.Timestamp) + err = writeElement(w, uint32(msg.Timestamp.Unix())) if err != nil { return err } @@ -864,7 +865,8 @@ func (msg *MsgTx) SerializeSize() int { } } - return n + // peercoin Time 4 bytes + return n + 4 } // SerializeSizeStripped returns the number of bytes it would take to serialize @@ -937,7 +939,7 @@ func (msg *MsgTx) PkScriptLocs() []int { func NewMsgTx(version int32) *MsgTx { return &MsgTx{ Version: version, - Timestamp: 0, // todo ppc should be passed down + Timestamp: time.Unix(0, 0), // todo ppc should be passed down TxIn: make([]*TxIn, 0, defaultTxInOutAlloc), TxOut: make([]*TxOut, 0, defaultTxInOutAlloc), }