return nil
}
+// Outputs return outputs of transactions
+func (b *TemplateBuilder) Outputs() []*types.TxOutput {
+ return b.outputs
+}
+
// InputCount return number of input in the template builder
func (b *TemplateBuilder) InputCount() int {
return len(b.inputs)
return nil, err
}
+ if err = builder.AddOutput(types.NewOriginalTxOutput(*consensus.BTMAssetID, 0, script, [][]byte{})); err != nil {
+ return nil, err
+ }
+
if b.block.Height%state.BlocksOfEpoch == 1 && b.block.Height != 1 {
for controlProgram, amount := range checkpoint.Rewards {
+ if controlProgram == hex.EncodeToString(script) {
+ builder.Outputs()[0].Amount = amount
+ continue
+ }
+
controlProgramBytes, err := hex.DecodeString(controlProgram)
if err != nil {
return nil, err
return nil, err
}
}
- } else {
- if err = builder.AddOutput(types.NewOriginalTxOutput(*consensus.BTMAssetID, 0, script, [][]byte{})); err != nil {
- return nil, err
- }
}
_, txData, err := builder.Build()
ParentHash: parent.checkpoint.Hash,
Parent: parent.checkpoint,
Status: state.Growing,
+ Rewards: make(map[string]uint64),
Votes: make(map[string]uint64),
Guaranties: make(map[string]uint64),
},
return nil, err
}
+ if err := node.checkpoint.ApplyValidatorReward(attachBlock); err != nil {
+ return nil, err
+ }
+
node.checkpoint.Hash = attachBlock.Hash()
node.checkpoint.Height = attachBlock.Height
node.checkpoint.Timestamp = attachBlock.Timestamp
if len(tx.TxHeader.ResultIds) != 1 {
return errors.Wrap(ErrWrongCoinbaseTransaction, "have more than 1 output")
}
- } else {
- if len(tx.TxHeader.ResultIds) != len(checkpoint.Rewards) {
- return errors.Wrap(ErrWrongCoinbaseTransaction)
+
+ return nil
+ }
+
+ return checkoutRewardCoinbase(tx, checkpoint)
+}
+
+func checkoutRewardCoinbase(tx *bc.Tx, checkpoint *state.Checkpoint) error {
+ resultIdLen := len(tx.TxHeader.ResultIds)
+ if resultIdLen != len(checkpoint.Rewards) && resultIdLen != len(checkpoint.Rewards)+1 {
+ return errors.Wrap(ErrWrongCoinbaseTransaction)
+ }
+
+ var startIndex int
+ if resultIdLen == len(checkpoint.Rewards)+1 {
+ output, err := tx.Output(*tx.TxHeader.ResultIds[0])
+ if err != nil {
+ return err
}
- rewards := checkpoint.Rewards
- for i := 0; i < len(tx.TxHeader.ResultIds); i++ {
- output := tx.TxHeader.ResultIds[i]
- out, err := tx.Output(*output)
- if err != nil {
- return err
- }
-
- if rewards[hex.EncodeToString(out.ControlProgram.Code)] != out.Source.Value.Amount {
- return errors.Wrap(ErrWrongCoinbaseTransaction)
- }
+ if output.Source.Value.Amount != 0 {
+ return errors.Wrap(ErrWrongCoinbaseTransaction, "dismatch output amount")
+ }
+
+ startIndex = 1
+ }
+
+ rewards := checkpoint.Rewards
+ for i := startIndex; i < resultIdLen; i++ {
+ output := tx.TxHeader.ResultIds[i]
+ out, err := tx.Output(*output)
+ if err != nil {
+ return err
+ }
+
+ if rewards[hex.EncodeToString(out.ControlProgram.Code)] != out.Source.Value.Amount {
+ return errors.Wrap(ErrWrongCoinbaseTransaction)
}
}
types.NewTx(types.TxData{
Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
Outputs: []*types.TxOutput{
+ types.NewOriginalTxOutput(*consensus.BTMAssetID, 0, []byte("controlProgram"), nil),
+ types.NewOriginalTxOutput(*consensus.BTMAssetID, 5000, []byte("controlProgram"), nil),
+ },
+ }),
+ },
+ },
+ checkpoint: &state.Checkpoint{
+ Rewards: map[string]uint64{hex.EncodeToString([]byte("controlProgram")): 5000},
+ },
+ err: nil,
+ },
+ {
+ block: &types.Block{
+ BlockHeader: types.BlockHeader{Height: state.BlocksOfEpoch + 1},
+ Transactions: []*types.Tx{
+ types.NewTx(types.TxData{
+ Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
+ Outputs: []*types.TxOutput{
+ types.NewOriginalTxOutput(*consensus.BTMAssetID, 1000, []byte("controlProgram"), nil),
+ types.NewOriginalTxOutput(*consensus.BTMAssetID, 5000, []byte("controlProgram"), nil),
+ },
+ }),
+ },
+ },
+ checkpoint: &state.Checkpoint{
+ Rewards: map[string]uint64{hex.EncodeToString([]byte("controlProgram")): 5000},
+ },
+ err: ErrWrongCoinbaseTransaction,
+ },
+ {
+ block: &types.Block{
+ BlockHeader: types.BlockHeader{Height: state.BlocksOfEpoch + 1},
+ Transactions: []*types.Tx{
+ types.NewTx(types.TxData{
+ Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
+ Outputs: []*types.TxOutput{
types.NewOriginalTxOutput(*consensus.BTMAssetID, 5000, []byte("controlProgram1"), nil),
types.NewOriginalTxOutput(*consensus.BTMAssetID, 5000, []byte("controlProgram2"), nil),
},