Skip to content

Commit

Permalink
Merge branch 'v0.7.0-hotfix.3-review'
Browse files Browse the repository at this point in the history
  • Loading branch information
gordon-sero committed May 6, 2019
2 parents 0179777 + 5e226ec commit 8b1dbdc
Show file tree
Hide file tree
Showing 21 changed files with 226 additions and 50 deletions.
5 changes: 3 additions & 2 deletions core/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func CanTransfer(db vm.StateDB, addr common.Address, asset *assets.Asset) bool {
}

// Transfer subtracts amount from sender and adds amount to recipient using the given Db
func Transfer(db vm.StateDB, sender, recipient common.Address, asset *assets.Asset) {
func Transfer(db vm.StateDB, sender, recipient common.Address, asset *assets.Asset) (alarm bool) {
if asset == nil {
return
}
Expand Down Expand Up @@ -137,6 +137,7 @@ func Transfer(db vm.StateDB, sender, recipient common.Address, asset *assets.Ass
db.AddTicket(recipient, category, common.BytesToHash(asset.Tkt.Value[:]))
}
} else {
db.GetZState().AddTxOut(recipient, *asset)
alarm = db.GetZState().AddTxOutWithCheck(recipient, *asset)
}
return
}
2 changes: 1 addition & 1 deletion core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
if contractCreation {
ret, _, st.gas, vmerr = evm.Create(sender, st.data, st.gas, msg.Asset())
} else {
ret, st.gas, vmerr = evm.Call(sender, st.to(), st.data, st.gas, msg.Asset())
ret, st.gas, vmerr, _ = evm.Call(sender, st.to(), st.data, st.gas, msg.Asset())
}
if vmerr != nil {
log.Debug("VM returned with error", "err", vmerr)
Expand Down
11 changes: 10 additions & 1 deletion core/tx_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import (
"sync"
"time"

"github.com/sero-cash/go-sero/zero/zconfig"

"github.com/sero-cash/go-sero/common"
"github.com/sero-cash/go-sero/core/state"
"github.com/sero-cash/go-sero/core/types"
Expand Down Expand Up @@ -111,7 +113,7 @@ type TxPoolConfig struct {
// pool.
var DefaultTxPoolConfig = TxPoolConfig{

PriceLimit: 1,
PriceLimit: params.Gta,
AccountSlots: 16,
GlobalSlots: 4096,
AccountQueue: 64,
Expand Down Expand Up @@ -499,6 +501,13 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) {
log.Trace("Discarding already known transaction", "hash", hash)
return false, fmt.Errorf("known transaction: %x", hash)
}

currentBlockNum := pool.chain.CurrentBlock().NumberU64()

if (zconfig.VP0-50) < currentBlockNum && currentBlockNum < (zconfig.VP0+50) {
return false, fmt.Errorf("protect vp0:%v", zconfig.VP0)
}

// If the transaction fails basic validation, discard it
if err := pool.validateTx(tx, local); err != nil {
log.Trace("Discarding invalid transaction", "hash", hash, "err", err)
Expand Down
29 changes: 17 additions & 12 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type (
// CanTransferFunc is the signature of a transfer guard function
CanTransferFunc func(StateDB, common.Address, *assets.Asset) bool
// TransferFunc is the signature of a transfer function
TransferFunc func(StateDB, common.Address, common.Address, *assets.Asset)
TransferFunc func(StateDB, common.Address, common.Address, *assets.Asset) (alarm bool)
// GetHashFunc returns the nth block hash in the blockchain
// and is used by the BLOCKHASH EVM op code.
GetHashFunc func(uint64) common.Hash
Expand Down Expand Up @@ -152,34 +152,35 @@ func (evm *EVM) Interpreter() Interpreter {
// parameters. It also handles any necessary value transfer required and takes
// the necessary steps to create accounts and reverses the state in case of an
// execution error or failed value transfer.
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, asset *assets.Asset) (ret []byte, leftOverGas uint64, err error) {
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, asset *assets.Asset) (ret []byte, leftOverGas uint64, err error, alarm bool) {
if evm.vmConfig.NoRecursion && evm.depth > 0 {
return nil, gas, nil
return nil, gas, nil, false
}

// Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) {
return nil, gas, ErrDepth
return nil, gas, ErrDepth, false
}

if evm.StateDB.IsContract(caller.Address()) && !evm.Context.CanTransfer(evm.StateDB, caller.Address(), asset) {
return nil, gas, ErrInsufficientBalance
return nil, gas, ErrInsufficientBalance, false
}

var (
to = AccountRef(addr)
snapshot = evm.StateDB.Snapshot()
)

evm.Transfer(evm.StateDB, caller.Address(), to.Address(), asset)
alarm = evm.Transfer(evm.StateDB, caller.Address(), to.Address(), asset)

// Initialise a new contract and set the code that is to be used by the EVM.
// The contract is a scoped environment for this execution context only.
contract := NewContract(caller, to, asset, gas)
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
input,err = loadAddress(evm, caller, input, contract, false)
input, err = loadAddress(evm, caller, input, contract, false)
if err != nil {
return ret, leftOverGas, err
evm.StateDB.RevertToSnapshot(snapshot)
return ret, leftOverGas, err, alarm
}

start := time.Now()
Expand All @@ -203,7 +204,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
contract.UseGas(contract.Gas)
}
}
return ret, contract.Gas, err
return ret, contract.Gas, err, alarm
}

// CallCode executes the contract associated with the addr with the given input
Expand Down Expand Up @@ -236,8 +237,9 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
// only.
contract := NewContract(caller, to, asset, gas)
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
input,err = loadAddress(evm, caller, input, contract, false)
input, err = loadAddress(evm, caller, input, contract, false)
if err != nil {
evm.StateDB.RevertToSnapshot(snapshot)
return ret, leftOverGas, err
}

Expand Down Expand Up @@ -273,8 +275,9 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
// Initialise a new contract and make initialise the delegate values
contract := NewContract(caller, to, nil, gas).AsDelegate()
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
input,err = loadAddress(evm, caller, input, contract, false)
input, err = loadAddress(evm, caller, input, contract, false)
if err != nil {
evm.StateDB.RevertToSnapshot(snapshot)
return ret, leftOverGas, err
}

Expand Down Expand Up @@ -317,8 +320,9 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
// only.
contract := NewContract(caller, to, nil, gas)
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
input,err = loadAddress(evm, caller, input, contract, false)
input, err = loadAddress(evm, caller, input, contract, false)
if err != nil {
evm.StateDB.RevertToSnapshot(snapshot)
return ret, leftOverGas, err
}

Expand Down Expand Up @@ -381,6 +385,7 @@ func (evm *EVM) create(caller ContractRef, code []byte, gas uint64, asset *asset
contract := NewContract(caller, AccountRef(address), asset, gas)
code, err := loadAddress(evm, caller, code, contract, true)
if err != nil {
evm.StateDB.RevertToSnapshot(snapshot)
return nil, common.Address{}, 0, err
}
contract.SetCallCode(&address, crypto.Keccak256Hash(code), code)
Expand Down
67 changes: 42 additions & 25 deletions core/vm/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,7 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
gas += params.CallStipend
}

ret, returnGas, err := interpreter.evm.Call(contract, toAddr, args, gas, asset)
ret, returnGas, err, alarm := interpreter.evm.Call(contract, toAddr, args, gas, asset)
contract.SetCallMsg(nil)
if err != nil {
stack.push(interpreter.intPool.getZero())
Expand All @@ -733,6 +733,10 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
}
contract.Gas += returnGas

if alarm {
contract.UseGas(contract.Gas)
}

interpreter.intPool.put(addr, value, inOffset, inSize, retOffset, retSize)
return ret, nil
}
Expand Down Expand Up @@ -765,7 +769,7 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, contract *Contract, mem
gas += params.CallStipend
}

ret, returnGas, err := interpreter.evm.Call(contract, toAddr, args, gas, asset)
ret, returnGas, err, alarm := interpreter.evm.Call(contract, toAddr, args, gas, asset)
contract.SetCallMsg(nil)
if err != nil {
stack.push(interpreter.intPool.getZero())
Expand All @@ -776,6 +780,9 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, contract *Contract, mem
memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
}
contract.Gas += returnGas
if alarm {
contract.UseGas(contract.Gas)
}

interpreter.intPool.put(addr, value, inOffset, inSize, retOffset, retSize)
return ret, nil
Expand Down Expand Up @@ -865,27 +872,27 @@ func opSuicide(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memo
return nil, nil
}

func handleAllotTicket(d []byte, evm *EVM, contract *Contract, mem []byte) (common.Hash, uint64, error) {
func handleAllotTicket(d []byte, evm *EVM, contract *Contract, mem []byte) (common.Hash, uint64, error, bool) {
offset := new(big.Int).SetBytes(d[64:96]).Uint64()
len := new(big.Int).SetBytes(mem[offset:offset+32]).Uint64()
len := new(big.Int).SetBytes(mem[offset : offset+32]).Uint64()
if len == 0 {
return common.Hash{}, 0, fmt.Errorf("allotTicket error , contract : %s, error : %s", contract.Address(), "nameLen is zero")
return common.Hash{}, 0, fmt.Errorf("allotTicket error , contract : %s, error : %s", contract.Address(), "nameLen is zero"), false
}

categoryName := string(mem[offset+32 : offset+32+len])
match, err := regexp.Match("^[A-Z][A-Z0-9_]{0,31}$", []byte(categoryName))
if err != nil || !match {
return common.Hash{}, 0, fmt.Errorf("allotTicket error , contract : %s, error : %s", contract.Address(), "illegal categoryName")
return common.Hash{}, 0, fmt.Errorf("allotTicket error , contract : %s, error : %s", contract.Address(), "illegal categoryName"), false
}

categoryName = strings.ToUpper(categoryName)
if strings.Contains(categoryName, "SERO") {
return common.Hash{}, 0, fmt.Errorf("allotTicket error , contract : %s, error : %s", contract.Address(), "categoryName can not contains SERO")
return common.Hash{}, 0, fmt.Errorf("allotTicket error , contract : %s, error : %s", contract.Address(), "categoryName can not contains SERO"), false
}
value := common.BytesToHash(d[0:32])
if value == (common.Hash{}) {
if !evm.StateDB.RegisterTicket(contract.Address(), categoryName) {
return common.Hash{}, 0, fmt.Errorf("allotTicket error , contract : %s, error : %s", contract.Address(), "categoryName registered by other")
return common.Hash{}, 0, fmt.Errorf("allotTicket error , contract : %s, error : %s", contract.Address(), "categoryName registered by other"), false
}

nonce := evm.StateDB.GetTicketNonce(contract.Address())
Expand All @@ -896,6 +903,7 @@ func handleAllotTicket(d []byte, evm *EVM, contract *Contract, mem []byte) (comm
}

toAddr := evm.StateDB.GetNonceAddress(d[44:64])
alarm := false
if toAddr != (common.Address{}) && toAddr != contract.Address() {
asset := assets.Asset{
Tkt: &assets.Ticket{
Expand All @@ -905,14 +913,17 @@ func handleAllotTicket(d []byte, evm *EVM, contract *Contract, mem []byte) (comm
}

gas := evm.callGasTemp + params.CallStipend
_, returnGas, err := evm.Call(contract, toAddr, nil, gas, &asset)
_, returnGas, err, _alarm := evm.Call(contract, toAddr, nil, gas, &asset)
alarm = _alarm
//contract.Gas += returnGas
if err != nil {
return common.Hash{}, returnGas, err
return common.Hash{}, returnGas, err, alarm
} else {
return value, returnGas, nil, alarm
}
}

return value, evm.callGasTemp, nil
return value, evm.callGasTemp, nil, alarm
}

var (
Expand Down Expand Up @@ -950,7 +961,7 @@ var foundationAccount2 = common.Base58ToAddress("5niHmAcSoDzaekKTUpLR3qkQf6djC7A

func handleIssueToken(d []byte, evm *EVM, contract *Contract, mem []byte) (bool, error) {
offset := new(big.Int).SetBytes(d[0:32]).Uint64()
len := new(big.Int).SetBytes(mem[offset:offset+32]).Uint64()
len := new(big.Int).SetBytes(mem[offset : offset+32]).Uint64()
if len == 0 {
return false, fmt.Errorf("issueToken error , contract : %s, error : %s", contract.Address(), "nameLen is zero")
}
Expand Down Expand Up @@ -981,7 +992,7 @@ func handleIssueToken(d []byte, evm *EVM, contract *Contract, mem []byte) (bool,
Value: utils.U256(*fee),
},
}
if (evm.BlockNumber.Uint64() >= 300000) {
if evm.BlockNumber.Uint64() >= 300000 {
evm.StateDB.GetZState().AddTxOut(foundationAccount2, asset)
} else {
evm.StateDB.GetZState().AddTxOut(foundationAccount1, asset)
Expand All @@ -999,22 +1010,22 @@ func handleIssueToken(d []byte, evm *EVM, contract *Contract, mem []byte) (bool,
return true, nil
}

func handleSend(d []byte, evm *EVM, contract *Contract, mem []byte) ([]byte, uint64, error) {
func handleSend(d []byte, evm *EVM, contract *Contract, mem []byte) ([]byte, uint64, error, bool) {
addr := common.BytesToContractAddress(d[12:32])
toAddr := evm.StateDB.GetNonceAddress(addr[:])
if toAddr == (common.Address{}) {
return nil, 0, fmt.Errorf("handleSend error , contract : %s, toAddr : %s, error : %s", contract.Address(), toAddr, "not load toAddrss")
return nil, 0, fmt.Errorf("handleSend error , contract : %s, toAddr : %s, error : %s", contract.Address(), toAddr, "not load toAddrss"), false
}
currency_offset := new(big.Int).SetBytes(d[32:64]).Uint64()
length := new(big.Int).SetBytes(mem[currency_offset:currency_offset+32]).Uint64()
length := new(big.Int).SetBytes(mem[currency_offset : currency_offset+32]).Uint64()
var currency string
if length != 0 {
currency = string(mem[currency_offset+32 : currency_offset+32+length])
}

var category string
category_offset := new(big.Int).SetBytes(d[96:128]).Uint64()
length = new(big.Int).SetBytes(mem[category_offset:category_offset+32]).Uint64()
length = new(big.Int).SetBytes(mem[category_offset : category_offset+32]).Uint64()
if length != 0 {
category = string(mem[category_offset+32 : category_offset+32+length])
}
Expand All @@ -1029,7 +1040,7 @@ func handleSend(d []byte, evm *EVM, contract *Contract, mem []byte) ([]byte, uin
if len(currency) != 0 && amount.Sign() != 0 {
balance := evm.StateDB.GetBalance(contract.Address(), currency)
if balance.Cmp(amount) < 0 {
return nil, 0, fmt.Errorf("handleSend error , contract : %s, toAddr : %s, error : %s", contract.Address(), toAddr, "balance not enough")
return nil, 0, fmt.Errorf("handleSend error , contract : %s, toAddr : %s, error : %s", contract.Address(), toAddr, "balance not enough"), false
}
token = &assets.Token{
Currency: *common.BytesToHash(common.LeftPadBytes([]byte(currency), 32)).HashToUint256(),
Expand All @@ -1040,7 +1051,7 @@ func handleSend(d []byte, evm *EVM, contract *Contract, mem []byte) ([]byte, uin
var ticket *assets.Ticket
if len(category) != 0 && ticketHash != (common.Hash{}) {
if !evm.StateDB.OwnTicket(contract.Address(), category, ticketHash) {
return nil, 0, fmt.Errorf("handleSend error , contract : %s, toAddr : %s, error : %s", contract.Address(), toAddr, "ticket not own")
return nil, 0, fmt.Errorf("handleSend error , contract : %s, toAddr : %s, error : %s", contract.Address(), toAddr, "ticket not own"), false
}
ticket = &assets.Ticket{
Category: *common.BytesToHash(common.LeftPadBytes([]byte(category), 32)).HashToUint256(),
Expand Down Expand Up @@ -1086,8 +1097,11 @@ func makeLog(size int) executionFunc {
}
}
if topics[0] == topic_allotTicket {
hash, returnGas, err := handleAllotTicket(d, interpreter.evm, contract, data)
hash, returnGas, err, alarm := handleAllotTicket(d, interpreter.evm, contract, data)
contract.Gas += returnGas
if alarm {
contract.UseGas(contract.Gas)
}
if err != nil {
log.Trace("IssueToken error ", "contract", contract.Address(), "error", err)
}
Expand All @@ -1103,7 +1117,7 @@ func makeLog(size int) executionFunc {
contract.Gas += interpreter.evm.callGasTemp
} else if topics[0] == topic_balanceOf {
offset := new(big.Int).SetBytes(d[0:32]).Uint64()
len := new(big.Int).SetBytes(data[offset:offset+32]).Uint64()
len := new(big.Int).SetBytes(data[offset : offset+32]).Uint64()
balance := new(big.Int)
if len != 0 {
coinName := string(data[offset+32 : offset+32+len])
Expand All @@ -1112,8 +1126,11 @@ func makeLog(size int) executionFunc {
memory.Set(mStart.Uint64(), 32, common.LeftPadBytes(balance.Bytes(), 32))
contract.Gas += interpreter.evm.callGasTemp
} else if topics[0] == topic_send {
_, returnGas, err := handleSend(d, interpreter.evm, contract, data)
_, returnGas, err, alarm := handleSend(d, interpreter.evm, contract, data)
contract.Gas += returnGas
if alarm {
contract.UseGas(contract.Gas)
}
if err != nil {
log.Trace("send error ", "contract", contract.Address(), "error", err)
memory.Set(mStart.Uint64()+length-32, 32, hashFalse)
Expand Down Expand Up @@ -1148,7 +1165,7 @@ func makeLog(size int) executionFunc {
contract.Gas += interpreter.evm.callGasTemp
} else if topics[0] == topic_setTokenRate {
offset := new(big.Int).SetBytes(d[0:32]).Uint64()
len := new(big.Int).SetBytes(data[offset:offset+32]).Uint64()
len := new(big.Int).SetBytes(data[offset : offset+32]).Uint64()
if len == 0 {
return nil, fmt.Errorf("setTokenRate error , contract : %s, error : %s", contract.Address(), "coinName len=0")
}
Expand Down Expand Up @@ -1237,14 +1254,14 @@ func makeLog(size int) executionFunc {

func setCallValues(d []byte, data []byte, contract *Contract) {
currency_offset := new(big.Int).SetBytes(d[0:32]).Uint64()
length := new(big.Int).SetBytes(data[currency_offset:currency_offset+32]).Uint64()
length := new(big.Int).SetBytes(data[currency_offset : currency_offset+32]).Uint64()
var currency string
if length != 0 {
currency = string(data[currency_offset+32 : currency_offset+32+length])
}
var category string
category_offset := new(big.Int).SetBytes(d[64:96]).Uint64()
length = new(big.Int).SetBytes(data[category_offset:category_offset+32]).Uint64()
length = new(big.Int).SetBytes(data[category_offset : category_offset+32]).Uint64()
if length != 0 {
category = string(data[category_offset+32 : category_offset+32+length])
}
Expand Down
Loading

0 comments on commit 8b1dbdc

Please sign in to comment.