Skip to content

Commit

Permalink
Merge ad52005 into 72b2037
Browse files Browse the repository at this point in the history
  • Loading branch information
erickyan86 committed Dec 3, 2019
2 parents 72b2037 + ad52005 commit 19a44c7
Show file tree
Hide file tree
Showing 20 changed files with 684 additions and 58 deletions.
49 changes: 48 additions & 1 deletion accountmanager/accountmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,7 @@ func (am *AccountManager) getParentAccount(accountName common.Name, parentIndex

// RecoverTx Make sure the transaction is signed properly and validate account authorization.
func (am *AccountManager) RecoverTx(signer types.Signer, tx *types.Transaction) error {
authorVersion := make(map[common.Name]common.Hash)
for _, action := range tx.GetActions() {
pubs, err := types.RecoverMultiKey(signer, action, tx)
if err != nil {
Expand Down Expand Up @@ -647,7 +648,6 @@ func (am *AccountManager) RecoverTx(signer types.Signer, tx *types.Transaction)
}
}

authorVersion := make(map[common.Name]common.Hash)
for name, acctAuthor := range recoverRes.acctAuthors {
var count uint64
for _, weight := range acctAuthor.indexWeight {
Expand All @@ -665,6 +665,53 @@ func (am *AccountManager) RecoverTx(signer types.Signer, tx *types.Transaction)

types.StoreAuthorCache(action, authorVersion)
}
if tx.PayerExist() {
for _, action := range tx.GetActions() {
pubs, err := types.RecoverPayerMultiKey(signer, action, tx)
if err != nil {
return err
}

if uint64(len(pubs)) > params.MaxSignLength {
return fmt.Errorf("exceed max sign length, want most %d, actual is %d", params.MaxSignLength, len(pubs))
}

sig := action.PayerSignature()
if sig == nil {
return fmt.Errorf("payer signature is nil")
}
parentIndex := sig.ParentIndex
signSender, err := am.getParentAccount(action.Payer(), parentIndex)
if err != nil {
return err
}
recoverRes := &recoverActionResult{make(map[common.Name]*accountAuthor)}
for i, pub := range pubs {
index := sig.SignData[uint64(i)].Index
if uint64(len(index)) > params.MaxSignDepth {
return fmt.Errorf("exceed max sign depth, want most %d, actual is %d", params.MaxSignDepth, len(index))
}

if err := am.ValidSign(signSender, pub, index, recoverRes); err != nil {
return err
}
}

for name, acctAuthor := range recoverRes.acctAuthors {
var count uint64
for _, weight := range acctAuthor.indexWeight {
count += weight
}
threshold := acctAuthor.threshold
if count < threshold {
return fmt.Errorf("account %s want threshold %d, but actual is %d", name, threshold, count)
}
authorVersion[name] = acctAuthor.version
}

types.StoreAuthorCache(action, authorVersion)
}
}
return nil
}

Expand Down
3 changes: 2 additions & 1 deletion processor/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ var (

errParentBlock = errors.New("parent block not exist")

ErrActionInvalid = errors.New("action field invalid")
ErrActionInvalid = errors.New("action field invalid")
errPayerNotSupport = errors.New("payer not support")
)

// GenesisMismatchError is raised when trying to overwrite an existing
Expand Down
21 changes: 18 additions & 3 deletions processor/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/fractalplatform/fractal/accountmanager"
"github.com/fractalplatform/fractal/common"
"github.com/fractalplatform/fractal/consensus"
"github.com/fractalplatform/fractal/params"
"github.com/fractalplatform/fractal/processor/vm"
"github.com/fractalplatform/fractal/state"
"github.com/fractalplatform/fractal/types"
Expand Down Expand Up @@ -100,7 +101,6 @@ func (p *StateProcessor) ApplyTransaction(author *common.Name, gp *common.GasPoo
if assetID != tx.GasAssetID() {
return nil, 0, fmt.Errorf("only support system asset %d as tx fee", p.bc.Config().SysTokenID)
}
gasPrice := tx.GasPrice()
//timer for vm exec overtime
var t *time.Timer
//
Expand All @@ -125,11 +125,26 @@ func (p *StateProcessor) ApplyTransaction(author *common.Name, gp *common.GasPoo
return nil, 0, ErrNonceTooLow
}

var gasPayer = action.Sender()
var gasPrice = tx.GasPrice()
if tx.PayerExist() {
if header.CurForkID() >= params.ForkID4 {
gasPayer = action.Payer()
gasPrice = action.PayerGasPrice()
} else {
return nil, 0, errPayerNotSupport
}
} else {
if action.PayerIsExist() {
return nil, 0, errPayerNotSupport
}
}

evmcontext := &EvmContext{
ChainContext: p.bc,
EngineContext: p.engine,
}
context := NewEVMContext(action.Sender(), action.Recipient(), assetID, tx.GasPrice(), header, evmcontext, author)
context := NewEVMContext(action.Sender(), action.Recipient(), assetID, gasPrice, header, evmcontext, author)
vmenv := vm.NewEVM(context, accountDB, statedb, config, cfg)

//will abort the vm if overtime
Expand All @@ -139,7 +154,7 @@ func (p *StateProcessor) ApplyTransaction(author *common.Name, gp *common.GasPoo
})
}

_, gas, failed, err, vmerr := ApplyMessage(accountDB, vmenv, action, gp, gasPrice, assetID, config, p.engine)
_, gas, failed, err, vmerr := ApplyMessage(accountDB, vmenv, action, gp, gasPrice, gasPayer, assetID, config, p.engine)

if false == cfg.EndTime.IsZero() {
//close timer
Expand Down
14 changes: 8 additions & 6 deletions processor/transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type StateTransition struct {
gas uint64
initialGas uint64
gasPrice *big.Int
gasPayer common.Name
assetID uint64
account *accountmanager.AccountManager
evm *vm.EVM
Expand All @@ -52,7 +53,7 @@ type StateTransition struct {

// NewStateTransition initialises and returns a new state transition object.
func NewStateTransition(accountDB *accountmanager.AccountManager, evm *vm.EVM,
action *types.Action, gp *common.GasPool, gasPrice *big.Int, assetID uint64,
action *types.Action, gp *common.GasPool, gasPrice *big.Int, gasPayer common.Name, assetID uint64,
config *params.ChainConfig, engine EngineContext) *StateTransition {
return &StateTransition{
engine: engine,
Expand All @@ -61,6 +62,7 @@ func NewStateTransition(accountDB *accountmanager.AccountManager, evm *vm.EVM,
evm: evm,
action: action,
gasPrice: gasPrice,
gasPayer: gasPayer,
assetID: assetID,
account: accountDB,
chainConfig: config,
Expand All @@ -69,9 +71,9 @@ func NewStateTransition(accountDB *accountmanager.AccountManager, evm *vm.EVM,

// ApplyMessage computes the new state by applying the given message against the old state within the environment.
func ApplyMessage(accountDB *accountmanager.AccountManager, evm *vm.EVM,
action *types.Action, gp *common.GasPool, gasPrice *big.Int,
action *types.Action, gp *common.GasPool, gasPrice *big.Int, gasPayer common.Name,
assetID uint64, config *params.ChainConfig, engine EngineContext) ([]byte, uint64, bool, error, error) {
return NewStateTransition(accountDB, evm, action, gp, gasPrice,
return NewStateTransition(accountDB, evm, action, gp, gasPrice, gasPayer,
assetID, config, engine).TransitionDb()
}

Expand All @@ -89,7 +91,7 @@ func (st *StateTransition) preCheck() error {

func (st *StateTransition) buyGas() error {
mgval := new(big.Int).Mul(new(big.Int).SetUint64(st.action.Gas()), st.gasPrice)
balance, err := st.account.GetAccountBalanceByID(st.from, st.assetID, 0)
balance, err := st.account.GetAccountBalanceByID(st.gasPayer, st.assetID, 0)
if err != nil {
return err
}
Expand All @@ -101,7 +103,7 @@ func (st *StateTransition) buyGas() error {
}
st.gas += st.action.Gas()
st.initialGas = st.action.Gas()
return st.account.TransferAsset(st.from, common.Name(st.chainConfig.FeeName), st.assetID, mgval)
return st.account.TransferAsset(st.gasPayer, common.Name(st.chainConfig.FeeName), st.assetID, mgval)
}

// TransitionDb will transition the state by applying the current message and
Expand Down Expand Up @@ -403,7 +405,7 @@ func (st *StateTransition) distributeFee() error {

func (st *StateTransition) refundGas() {
remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gas), st.gasPrice)
st.account.TransferAsset(common.Name(st.chainConfig.FeeName), st.from, st.assetID, remaining)
st.account.TransferAsset(common.Name(st.chainConfig.FeeName), st.gasPayer, st.assetID, remaining)
st.gp.AddGas(st.gas)
}

Expand Down
13 changes: 10 additions & 3 deletions processor/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,16 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
return err
}

// Header validity is known at this point, check the uncles and transactions
if hash := types.DeriveTxsMerkleRoot(block.Txs); hash != block.TxHash() {
return fmt.Errorf("transaction root hash mismatch: have %x, want %x", hash, block.TxHash())
if block.CurForkID() >= params.ForkID4 {
// Header validity is known at this point, check the uncles and transactions
if hash := types.DeriveExtensTxsMerkleRoot(block.Txs); hash != block.TxHash() {
return fmt.Errorf("transaction root hash mismatch: have %x, want %x", hash, block.TxHash())
}
} else {
// Header validity is known at this point, check the uncles and transactions
if hash := types.DeriveTxsMerkleRoot(block.Txs); hash != block.TxHash() {
return fmt.Errorf("transaction root hash mismatch: have %x, want %x", hash, block.TxHash())
}
}
return nil
}
Expand Down
12 changes: 10 additions & 2 deletions processor/vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -580,9 +580,17 @@ func (evm *EVM) Create(caller ContractRef, action *types.Action, gas uint64) (re
snapshot := evm.StateDB.Snapshot()

if b, err := evm.AccountDB.AccountHaveCode(contractName); err != nil {
return nil, 0, err
if evm.ForkID >= params.ForkID4 {
return nil, gas, err
} else {
return nil, 0, err
}
} else if b {
return nil, 0, ErrContractCodeCollision
if evm.ForkID >= params.ForkID4 {
return nil, gas, ErrContractCodeCollision
} else {
return nil, 0, ErrContractCodeCollision
}
}

if err := evm.AccountDB.TransferAsset(action.Sender(), action.Recipient(), evm.AssetID, action.Value()); err != nil {
Expand Down
19 changes: 18 additions & 1 deletion rpcapi/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,23 @@ func (s *PublicBlockChainAPI) GetTransactionReceipt(ctx context.Context, hash co
return receipt.NewRPCReceipt(blockHash, blockNumber, index, tx), nil
}

func (s *PublicBlockChainAPI) GetTransactionReceiptWithPayer(ctx context.Context, hash common.Hash) (*types.RPCReceiptWithPayer, error) {
tx, blockHash, blockNumber, index := rawdb.ReadTransaction(s.b.ChainDb(), hash)
if tx == nil {
return nil, nil
}

receipts, err := s.b.GetReceipts(ctx, blockHash)
if err != nil {
return nil, err
}
if len(receipts) <= int(index) {
return nil, nil
}
receipt := receipts[index]
return receipt.NewRPCReceiptWithPayer(blockHash, blockNumber, index, tx), nil
}

func (s *PublicBlockChainAPI) GetBlockAndResultByNumber(ctx context.Context, blockNr rpc.BlockNumber) *types.BlockAndResult {
r := s.b.GetBlockDetailLog(ctx, blockNr)
if r == nil {
Expand Down Expand Up @@ -306,7 +323,7 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
// and apply the message.
gp := new(common.GasPool).AddGas(math.MaxUint64)
action := types.NewAction(args.ActionType, args.From, args.To, 0, assetID, gas, value, args.Data, args.Remark)
res, gas, failed, err, _ := processor.ApplyMessage(account, evm, action, gp, gasPrice, assetID, s.b.ChainConfig(), s.b.Engine())
res, gas, failed, err, _ := processor.ApplyMessage(account, evm, action, gp, gasPrice, action.Sender(), assetID, s.b.ChainConfig(), s.b.Engine())
if err := vmError(); err != nil {
return nil, 0, false, err
}
Expand Down

0 comments on commit 19a44c7

Please sign in to comment.