return 0, err
}
+ _, err = blockchain.ReadExtensibleString(r, bh.BlockCommitment.readFrom)
+ if err != nil {
+ return 0, err
+ }
+
bh.Nonce, err = blockchain.ReadVarint63(r)
if err != nil {
return 0, err
if err != nil {
return err
}
+ _, err = blockchain.WriteExtensibleString(w, nil, bh.BlockCommitment.writeTo)
+ if err != nil {
+ return err
+ }
_, err = blockchain.WriteVarint63(w, bh.Nonce)
if err != nil {
return err
"01" + // block height
"0000000000000000000000000000000000000000000000000000000000000000" + // prev block hash
"00" + // timestamp
- "41" + // commitment extensible field length
+ "40" + // commitment extensible field length
"0000000000000000000000000000000000000000000000000000000000000000" + // tx merkle root
"0000000000000000000000000000000000000000000000000000000000000000" + // assets merkle root
- "00" + // consensus program
- "01" + // witness extensible string length
- "00" + // witness number of witness args
+ "00" + // nonce
+ "00" + // bits
+
"01" + // num transactions
"07" + // tx 0, serialization flags
"01" + // tx 0, tx version
"01" + // block height
"0000000000000000000000000000000000000000000000000000000000000000" + // prev block hash
"00" + // timestamp
- "41" + // commitment extensible field length
+ "40" + // commitment extensible field length
"0000000000000000000000000000000000000000000000000000000000000000" + // transactions merkle root
"0000000000000000000000000000000000000000000000000000000000000000" + // assets merkle root
- "00" + // consensus program
- "01" + // witness extensible string length
- "00" + // witness number of witness args
+ "00" + // nonce
+ "00" + // bits
"00") // num transactions
want, _ := hex.DecodeString(wantHex)
if !bytes.Equal(got, want) {
"01" + // block height
"0000000000000000000000000000000000000000000000000000000000000000" + // prev block hash
"00" + // timestamp
- "41" + // commitment extensible field length
+ "40" + // commitment extensible field length
"0000000000000000000000000000000000000000000000000000000000000000" + // transactions merkle root
"0000000000000000000000000000000000000000000000000000000000000000" + // assets merkle root
- "00" + // consensus program
- "01" + // witness extensible string length
- "00") // witness number of witness args
+ "00" + // nonce
+ "00") // bits
want, _ = hex.DecodeString(wantHex)
if !bytes.Equal(got, want) {
t.Errorf("empty block header bytes = %x want %x", got, want)
}
- wantHash := mustDecodeHash("6a73cbca99e33c8403d589664623c74df34dd6d7328ab6e7f27dd3e60d959850")
+ wantHash := mustDecodeHash("f2e8d5be16096e275a51866eb5207b385c9aa02ec570a1540f445efcba05e04d")
if h := block.Hash(); h != wantHash {
t.Errorf("got block hash %x, want %x", h.Bytes(), wantHash.Bytes())
}
"01" + // block height
"0000000000000000000000000000000000000000000000000000000000000000" + // prev block hash
"00" + // timestamp
- "41" + // commitment extensible field length
+ "40" + // commitment extensible field length
"0000000000000000000000000000000000000000000000000000000000000000" + // transactions merkle root
"0000000000000000000000000000000000000000000000000000000000000000" + // assets merkle root
- "00" + // consensus program
- "01" + // witness extensible string length
- "00" + // witness num witness args
+ "00" + // nonce
+ "00" + // bits
"01" + // num transactions
"070102000000000000") // transaction
want, _ := hex.DecodeString(wantHex)
}
}
- if len(tx.Inputs) == 0 && len(tx.Outputs) == 1 {
+ if tx.IsCoinbase() {
cb := bc.NewCoinbase()
cbId := addEntry(cb)
out := tx.Outputs[0]
- muxSources[0] = &bc.ValueSource{
+ muxSources = []*bc.ValueSource{{
Ref: &cbId,
Value: &out.AssetAmount,
- }
+ }}
}
mux := bc.NewMux(muxSources, &bc.Program{VmVersion: 1, Code: []byte{byte(vm.OP_TRUE)}})
iss.SetDestination(&muxID, iss.Value, iss.Ordinal)
}
- if len(tx.Inputs) == 0 && len(tx.Outputs) == 1 {
- cbId := muxSources[0].Ref
- cb := entryMap[*cbId].(*bc.Coinbase)
- cb.SetDestination(&muxID, muxSources[0].Value, 0)
+ if tx.IsCoinbase() {
+ muxSource := mux.Sources[0]
+ cb := entryMap[*muxSource.Ref].(*bc.Coinbase)
+ cb.SetDestination(&muxID, muxSource.Value, 0)
}
var resultIDs []*bc.Hash
"github.com/davecgh/go-spew/spew"
"github.com/bytom/protocol/bc"
+ "github.com/bytom/protocol/validation"
)
func TestMapTx(t *testing.T) {
}
}
}
+
+func TestMapCoinbaseTx(t *testing.T) {
+ oldTx := &TxData{
+ Version: 1,
+ Inputs: []*TxInput{},
+ Outputs: []*TxOutput{
+ NewTxOutput(*validation.BTMAssetID, 800000000000, []byte{1}, nil),
+ },
+ }
+ oldOut := oldTx.Outputs[0]
+
+ _, header, entryMap := mapTx(oldTx)
+ t.Log(spew.Sdump(entryMap))
+
+ outEntry, ok := entryMap[*header.ResultIds[0]]
+ if !ok {
+ t.Errorf("entryMap contains nothing for output")
+ return
+ }
+ newOut, ok := outEntry.(*bc.Output)
+ if !ok {
+ t.Errorf("header.ResultIds[0] has type %T, expected *Output", outEntry)
+ return
+ }
+ if *newOut.Source.Value != oldOut.AssetAmount {
+ t.Errorf("(*output).Source is %v, expected %v", newOut.Source.Value, oldOut.AssetAmount)
+ return
+ }
+
+ muxEntry, ok := entryMap[*newOut.Source.Ref]
+ if !ok {
+ t.Errorf("entryMap contains nothing for mux")
+ return
+ }
+ mux, ok := muxEntry.(*bc.Mux)
+ if !ok {
+ t.Errorf("muxEntry has type %T, expected *Mux", muxEntry)
+ return
+ }
+ if *mux.WitnessDestinations[0].Value != oldOut.AssetAmount {
+ t.Errorf("(*Mux).Source is %v, expected %v", newOut.Source.Value, oldOut.AssetAmount)
+ return
+ }
+
+ if coinbaseEntry, ok := entryMap[*mux.Sources[0].Ref]; ok {
+ if coinbase, ok := coinbaseEntry.(*bc.Coinbase); ok {
+ if *coinbase.WitnessDestination.Value != oldOut.AssetAmount {
+ t.Errorf("(*Coinbase).Source is %v, expected %v", newOut.Source.Value, oldOut.AssetAmount)
+ }
+ } else {
+ t.Errorf("inputEntry has type %T, expected *Coinbase", coinbaseEntry)
+ }
+ } else {
+ t.Errorf("entryMap contains nothing for input")
+ }
+}
return false
}
+// IsCoinbase returns true if this transaction is coinbase transaction.
+func (tx *TxData) IsCoinbase() bool {
+ return len(tx.Inputs) == 0 && len(tx.Outputs) == 1
+}
+
func (tx *TxData) UnmarshalText(p []byte) error {
b := make([]byte, hex.DecodedLen(len(p)))
_, err := hex.Decode(b, p)
"066f7574707574" + // output 0, reference data
"00" + // output 0, output witness
"0869737375616e6365"), // reference data
- hash: mustDecodeHash("cd4669d5363374f8661621273501c23e613fc98b0fab9d5d858f30e16ccd24ce"),
+ hash: mustDecodeHash("515774561625cfe07629e49d4cf938d641aeb62af58e1b3ae2c582fee41dc628"),
},
{
tx: NewTx(TxData{
}
}
+func TestIsCoinbase(t *testing.T) {
+ cases := []struct {
+ tx *TxData
+ want bool
+ }{{
+ tx: &TxData{
+ Inputs: []*TxInput{NewIssuanceInput(nil, 0, nil, bc.Hash{}, nil, nil, nil)},
+ },
+ want: false,
+ }, {
+ tx: &TxData{
+ Inputs: []*TxInput{
+ NewSpendInput(nil, bc.Hash{}, bc.AssetID{}, 0, 0, nil, bc.Hash{}, nil),
+ NewIssuanceInput(nil, 0, nil, bc.Hash{}, nil, nil, nil),
+ },
+ Outputs: []*TxOutput{
+ NewTxOutput(bc.AssetID{}, 0, nil, nil),
+ },
+ },
+ want: false,
+ }, {
+ tx: &TxData{
+ Outputs: []*TxOutput{
+ NewTxOutput(bc.AssetID{}, 0, nil, nil),
+ },
+ },
+ want: true,
+ }}
+
+ for _, c := range cases {
+ got := c.tx.IsCoinbase()
+ if got != c.want {
+ t.Errorf("IsCoinbase(%+v) = %v want %v", c.tx, got, c.want)
+ }
+ }
+}
+
func TestInvalidIssuance(t *testing.T) {
hex := ("07" + // serflags
"01" + // transaction version