Skip to content

Commit

Permalink
refactor(transaction): add default checker
Browse files Browse the repository at this point in the history
  • Loading branch information
RainFallsSilent committed Oct 27, 2021
1 parent c3dbb78 commit 76916bc
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 83 deletions.
39 changes: 25 additions & 14 deletions blockchain/txvalidator.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,24 +149,35 @@ func (b *BlockChain) CheckTransactionContext(blockHeight uint32,
//}

para := &payload.CheckParameters{
BlockHeight: 0,
CRCommitteeStartHeight: 0,
ConsensusAlgorithm: 0,
DestroyELAAddress: common.Uint168{},
CRAssetsAddress: common.Uint168{},
FoundationAddress: common.Uint168{},
}

contextErr := txn.Payload.ContextCheck(para)
Version: txn.Version,
TxType: txn.TxType,
PayloadVersion: txn.PayloadVersion,
Attributes: txn.Attributes,
Inputs: txn.Inputs,
Outputs: txn.Outputs,
LockTime: txn.LockTime,
Programs: txn.Programs,
TxHash: txn.Hash(),

BlockHeight: blockHeight,
CRCommitteeStartHeight: b.chainParams.CRCommitteeStartHeight,
ConsensusAlgorithm: byte(b.state.GetConsensusAlgorithm()),
DestroyELAAddress: b.chainParams.DestroyELAAddress,
CRAssetsAddress: b.chainParams.CRAssetsAddress,
FoundationAddress: b.chainParams.Foundation,
}

references, contextErr := txn.Payload.ContextCheck(para)
if contextErr != nil {
return nil, contextErr
}

references, err := b.UTXOCache.GetTxReference(txn)
if err != nil {
log.Warn("[CheckTransactionContext] get transaction reference failed")
return nil, elaerr.Simple(elaerr.ErrTxUnknownReferredTx, nil)
}
//
//references, err := b.UTXOCache.GetTxReference(txn)
//if err != nil {
// log.Warn("[CheckTransactionContext] get transaction reference failed")
// return nil, elaerr.Simple(elaerr.ErrTxUnknownReferredTx, nil)
//}

if err := b.checkPOWConsensusTransaction(txn, references); err != nil {
log.Warn("[checkPOWConsensusTransaction],", err)
Expand Down
49 changes: 25 additions & 24 deletions core/types/payload/coinbase.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
package payload

import (
"errors"
"fmt"
common2 "github.com/elastos/Elastos.ELA/core/types/common"
"io"

elaerr "github.com/elastos/Elastos.ELA/errors"
Expand Down Expand Up @@ -43,35 +45,34 @@ func (a *CoinBase) Deserialize(r io.Reader, version byte) error {
}

// todo add description
func (a *CoinBase) SpecialCheck(p *CheckParameters) (elaerr.ELAError, bool) {
func (a *CoinBase) SpecialCheck(para *CheckParameters) (elaerr.ELAError, bool) {
// todo special check, all check witch used isCoinbase function, need to move here.
//if p.BlockHeight >= p.CRCommitteeStartHeight {
// if p.ConsensusAlgorithm == 0x01 {
// if !txn.Outputs[0].ProgramHash.IsEqual(p.DestroyELAAddress) {
// return elaerr.Simple(elaerr.ErrTxInvalidOutput,
// errors.New("first output address should be "+
// "DestroyAddress in POW consensus algorithm")), true
// }
// } else {
// if !txn.Outputs[0].ProgramHash.IsEqual(p.CRAssetsAddress) {
// return elaerr.Simple(elaerr.ErrTxInvalidOutput,
// errors.New("first output address should be CR assets address")), true
// }
// }
//} else if !txn.Outputs[0].ProgramHash.IsEqual(p.FoundationAddress) {
// return elaerr.Simple(elaerr.ErrTxInvalidOutput,
// errors.New("first output address should be foundation address")), true
//}
//
if para.BlockHeight >= para.CRCommitteeStartHeight {
if para.ConsensusAlgorithm == 0x01 {
if !para.Outputs[0].ProgramHash.IsEqual(para.DestroyELAAddress) {
return elaerr.Simple(elaerr.ErrTxInvalidOutput,
errors.New("first output address should be "+
"DestroyAddress in POW consensus algorithm")), true
}
} else {
if !para.Outputs[0].ProgramHash.IsEqual(para.CRAssetsAddress) {
return elaerr.Simple(elaerr.ErrTxInvalidOutput,
errors.New("first output address should be CR assets address")), true
}
}
} else if !para.Outputs[0].ProgramHash.IsEqual(para.FoundationAddress) {
return elaerr.Simple(elaerr.ErrTxInvalidOutput,
errors.New("first output address should be foundation address")), true
}

fmt.Println("CoinBase self check")
return nil, true
}

func (a *CoinBase) ContextCheck(para *CheckParameters) elaerr.ELAError {
func (a *CoinBase) ContextCheck(para *CheckParameters) (map[*common2.Input]common2.Output, elaerr.ELAError) {

if err := a.CheckTxHeightVersion(para); err != nil {
return elaerr.Simple(elaerr.ErrTxHeightVersion, nil)
return nil, elaerr.Simple(elaerr.ErrTxHeightVersion, nil)
}

//// check if duplicated with transaction in ledger
Expand All @@ -81,13 +82,13 @@ func (a *CoinBase) ContextCheck(para *CheckParameters) elaerr.ELAError {
//}
if exist := a.IsTxHashDuplicate(para.TxHash); exist {
//log.Warn("[CheckTransactionContext] duplicate transaction check failed.")
return elaerr.Simple(elaerr.ErrTxDuplicate, nil)
return nil, elaerr.Simple(elaerr.ErrTxDuplicate, nil)
}

firstErr, end := a.SpecialCheck(para)
if end {
return firstErr
return nil, firstErr
}

return nil
return nil, nil
}
69 changes: 63 additions & 6 deletions core/types/payload/coinbase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,71 @@

package payload

import "testing"
import (
"testing"

"github.com/elastos/Elastos.ELA/common"
common2 "github.com/elastos/Elastos.ELA/core/types/common"
)

func TestCoinBase_FunctionRewrite(t *testing.T) {
// self check
payload := CoinBase{}
payload.SpecialCheck(&CheckParameters{})
var para = &CheckParameters{
Version: 0,
TxType: 0,
PayloadVersion: 0,
Attributes: nil,
Inputs: []*common2.Input{
{
Previous: common2.OutPoint{
TxID: common.Uint256{1},
Index: 0,
},
Sequence: 0,
},
},
Outputs: []*common2.Output{
{
AssetID: common.Uint256{2},
Value: 100,
OutputLock: 0,
ProgramHash: common.Uint168{},
Type: 0,
Payload: nil,
},
},
LockTime: 0,
Programs: nil,
TxHash: common.Uint256{},
BlockHeight: 0,
CRCommitteeStartHeight: 0,
ConsensusAlgorithm: 0,
DestroyELAAddress: common.Uint168{},
CRAssetsAddress: common.Uint168{},
FoundationAddress: common.Uint168{},
} // self check
payload := CoinBase{
DefaultChecker: DefaultChecker{
IsTxHashDuplicateFunction: func(txhash common.Uint256) bool { return false },
GetTxReferenceFunction: func(para *CheckParameters) (map[*common2.Input]common2.Output, error) {
result := make(map[*common2.Input]common2.Output)
return result, nil
},
},
}
payload.ContextCheck(para)
payload.SpecialCheck(para)

// default check
payload2 := Confirm{}
payload2.SpecialCheck(&CheckParameters{})
payload2 := Confirm{
DefaultChecker: DefaultChecker{
IsTxHashDuplicateFunction: func(txhash common.Uint256) bool { return false },
GetTxReferenceFunction: func(para *CheckParameters) (map[*common2.Input]common2.Output, error) {
result := make(map[*common2.Input]common2.Output)
return result, nil
},
},
}
payload2.ContextCheck(para)
payload2.SpecialCheck(para)

}
5 changes: 3 additions & 2 deletions core/types/payload/crcproposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ package payload
import (
"bytes"
"errors"
"github.com/elastos/Elastos.ELA/common"
"github.com/elastos/Elastos.ELA/crypto"
"io"
"regexp"

"github.com/elastos/Elastos.ELA/common"
"github.com/elastos/Elastos.ELA/crypto"
)

const (
Expand Down
72 changes: 36 additions & 36 deletions core/types/payload/payloadchecker.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,63 +8,63 @@ package payload
import (
"fmt"
"github.com/elastos/Elastos.ELA/common"
common2 "github.com/elastos/Elastos.ELA/core/types/common"
elaerr "github.com/elastos/Elastos.ELA/errors"
)

type CheckParameters struct {
// others
BlockHeight uint32
CRCommitteeStartHeight uint32
ConsensusAlgorithm byte
DestroyELAAddress common.Uint168
CRAssetsAddress common.Uint168
FoundationAddress common.Uint168

TxHash common.Uint256
}

type DefaultChecker struct {
IsTxHashDuplicateFunction func(txhash common.Uint256) bool
GetTxReference func(para *CheckParameters) error
GetTxReferenceFunction func(para *CheckParameters) (map[*common2.Input]common2.Output, error)
}

func (a *DefaultChecker) SpecialCheck(para *CheckParameters) (elaerr.ELAError, bool) {
fmt.Println("default check")
return nil, false
}

func (a *DefaultChecker) CheckTxHeightVersion(para *CheckParameters) error {
// todo default check
return nil
}

func (a *DefaultChecker) IsTxHashDuplicate(txHash common.Uint256) bool {
return a.IsTxHashDuplicateFunction(txHash)
}

func (a *DefaultChecker) ContextCheck(para *CheckParameters) elaerr.ELAError {
func (a *DefaultChecker) ContextCheck(para *CheckParameters) (map[*common2.Input]common2.Output, elaerr.ELAError) {

if err := a.CheckTxHeightVersion(para); err != nil {
return elaerr.Simple(elaerr.ErrTxHeightVersion, nil)
return nil, elaerr.Simple(elaerr.ErrTxHeightVersion, nil)
}

//// check if duplicated with transaction in ledger
//if exist := b.db.IsTxHashDuplicate(txn.Hash()); exist {
// log.Warn("[CheckTransactionContext] duplicate transaction check failed.")
// return nil, elaerr.Simple(elaerr.ErrTxDuplicate, nil)
//}
if exist := a.IsTxHashDuplicate(para.TxHash); exist {
//log.Warn("[CheckTransactionContext] duplicate transaction check failed.")
return elaerr.Simple(elaerr.ErrTxDuplicate, nil)
return nil, elaerr.Simple(elaerr.ErrTxDuplicate, nil)
}

references, err := a.GetTxReference(para)
if err != nil {
//log.Warn("[CheckTransactionContext] get transaction reference failed")
return nil, elaerr.Simple(elaerr.ErrTxUnknownReferredTx, nil)
}

// todo add more common check
// ...

firstErr, end := a.SpecialCheck(para)
if end {
return firstErr
return nil, firstErr
}

return references, nil
}

func (a *DefaultChecker) CheckTxHeightVersion(para *CheckParameters) error {
// todo default check
return nil
}

func (a *DefaultChecker) IsTxHashDuplicate(txHash common.Uint256) bool {
return a.IsTxHashDuplicateFunction(txHash)
}

func (a *DefaultChecker) GetTxReference(para *CheckParameters) (
map[*common2.Input]common2.Output, error) {
return a.GetTxReferenceFunction(para)
}

func (a *DefaultChecker) CheckPOWConsensusTransaction(para *CheckParameters, references map[*common2.Input]common2.Output) error {
// todo default check
return nil
}

func (a *DefaultChecker) SpecialCheck(para *CheckParameters) (elaerr.ELAError, bool) {
fmt.Println("default check")
return nil, false
}
7 changes: 6 additions & 1 deletion core/types/payload/payloadcheckerinterface.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ package payload

import (
"github.com/elastos/Elastos.ELA/common"
common2 "github.com/elastos/Elastos.ELA/core/types/common"
elaerr "github.com/elastos/Elastos.ELA/errors"
)

type PayloadChecker interface {
ContextCheck(p *CheckParameters) elaerr.ELAError
ContextCheck(p *CheckParameters) (map[*common2.Input]common2.Output, elaerr.ELAError)

// todo ... add SanityCheck
}
Expand All @@ -21,6 +22,10 @@ type BasePayloadChecker interface {

IsTxHashDuplicate(txHash common.Uint256) bool

GetTxReference(para *CheckParameters) (map[*common2.Input]common2.Output, error)

CheckPOWConsensusTransaction(para *CheckParameters, references map[*common2.Input]common2.Output) error

// todo add description
SpecialCheck(p *CheckParameters) (error elaerr.ELAError, end bool)

Expand Down
33 changes: 33 additions & 0 deletions core/types/payload/payloadcheckerparameter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) 2017-2021 The Elastos Foundation
// Use of this source code is governed by an MIT
// license that can be found in the LICENSE file.
//

package payload

import (
"github.com/elastos/Elastos.ELA/common"
pg "github.com/elastos/Elastos.ELA/core/contract/program"
common2 "github.com/elastos/Elastos.ELA/core/types/common"
)

type CheckParameters struct {
// transaction
Version common2.TransactionVersion
TxType common2.TxType
PayloadVersion byte
Attributes []*common2.Attribute
Inputs []*common2.Input
Outputs []*common2.Output
LockTime uint32
Programs []*pg.Program
TxHash common.Uint256

// others
BlockHeight uint32
CRCommitteeStartHeight uint32
ConsensusAlgorithm byte
DestroyELAAddress common.Uint168
CRAssetsAddress common.Uint168
FoundationAddress common.Uint168
}

0 comments on commit 76916bc

Please sign in to comment.