diff --git a/core/evm.go b/core/evm.go index f24f9be7..97d14805 100644 --- a/core/evm.go +++ b/core/evm.go @@ -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 } @@ -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 } diff --git a/core/state_transition.go b/core/state_transition.go index 2900bbe3..3c903f41 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -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) diff --git a/core/tx_pool.go b/core/tx_pool.go index 915df78c..ad80ed50 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -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" @@ -111,7 +113,7 @@ type TxPoolConfig struct { // pool. var DefaultTxPoolConfig = TxPoolConfig{ - PriceLimit: 1, + PriceLimit: params.Gta, AccountSlots: 16, GlobalSlots: 4096, AccountQueue: 64, @@ -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) diff --git a/core/vm/evm.go b/core/vm/evm.go index bb3e47ce..b7d6057a 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -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 @@ -152,18 +152,18 @@ 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 ( @@ -171,15 +171,16 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas 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() @@ -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 @@ -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 } @@ -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 } @@ -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 } @@ -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) diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 4ccda2a9..d3b414e0 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -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()) @@ -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 } @@ -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()) @@ -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 @@ -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()) @@ -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{ @@ -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 ( @@ -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") } @@ -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) @@ -999,14 +1010,14 @@ 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]) @@ -1014,7 +1025,7 @@ func handleSend(d []byte, evm *EVM, contract *Contract, mem []byte) ([]byte, uin 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]) } @@ -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(), @@ -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(), @@ -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) } @@ -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]) @@ -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) @@ -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") } @@ -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]) } diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index ac5f6bf8..c61b971c 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -113,7 +113,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { Value: utils.U256(*cfg.Value), }, } - ret, _, err := vmenv.Call( + ret, _, err, _ := vmenv.Call( sender, common.BytesToAddress([]byte("contract")), input, @@ -170,7 +170,7 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er Value: utils.U256(*cfg.Value), }, } - ret, leftOverGas, err := vmenv.Call( + ret, leftOverGas, err, _ := vmenv.Call( sender, address, input, diff --git a/miner/worker.go b/miner/worker.go index 3dab0c3f..e7a67bbb 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -23,6 +23,8 @@ import ( "sync/atomic" "time" + "github.com/sero-cash/go-sero/zero/zconfig" + "github.com/sero-cash/go-sero/common/address" "github.com/sero-cash/go-czero-import/keys" @@ -485,6 +487,12 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB break } + if env.header.Number.Uint64() == zconfig.VP0 { + txs.Shift() + env.errHandledTxs = append(env.errHandledTxs, tx) + continue + } + // Start executing the transaction env.state.Prepare(tx.Hash(), common.Hash{}, env.tcount) diff --git a/params/version.go b/params/version.go index 21698f9f..5965895a 100644 --- a/params/version.go +++ b/params/version.go @@ -24,7 +24,7 @@ const ( VersionMajor = 0 // Major version component of the current release VersionMinor = 7 // Minor version component of the current release VersionPatch = 0 // Patch version component of the current release - VersionMeta = "beta.r7-hotfix.2" // Version metadata to append to the version string + VersionMeta = "beta.r7-hotfix.3" // Version metadata to append to the version string ) // Version holds the textual version string. diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index 7f341753..14097225 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -125,7 +125,8 @@ func (t *VMTest) exec(statedb *state.StateDB, vmconfig vm.Config) ([]byte, uint6 Value: utils.U256(*e.Value), }, } - return evm.Call(vm.AccountRef(e.Caller), e.Address, e.Data, e.GasLimit, &asset) + a, b, c, _ := evm.Call(vm.AccountRef(e.Caller), e.Address, e.Data, e.GasLimit, &asset) + return a, b, c } func (t *VMTest) newEVM(statedb *state.StateDB, vmconfig vm.Config) *vm.EVM { @@ -137,7 +138,7 @@ func (t *VMTest) newEVM(statedb *state.StateDB, vmconfig vm.Config) *vm.EVM { // } // return core.CanTransfer(db, address, amount) //} - transfer := func(db vm.StateDB, sender, recipient common.Address, pkg *assets.Asset) {} + transfer := func(db vm.StateDB, sender, recipient common.Address, pkg *assets.Asset) (alarm bool) { return false } context := vm.Context{ //CanTransfer: canTransfer, Transfer: transfer, diff --git a/zero/light/light_issi/type.go b/zero/light/light_issi/type.go new file mode 100644 index 00000000..9636f58c --- /dev/null +++ b/zero/light/light_issi/type.go @@ -0,0 +1,37 @@ +package light_issi + +import ( + "github.com/sero-cash/go-czero-import/keys" + "github.com/sero-cash/go-sero/common/hexutil" + "github.com/sero-cash/go-sero/zero/light/light_types" +) + +type Out struct { + Root keys.Uint256 + PKr keys.PKr +} +type Block struct { + Num hexutil.Uint64 + Outs []Out + Nils []keys.Uint256 +} + +type GIn struct { + SKr keys.PKr + Root keys.Uint256 +} + +type GenTxParam struct { + Gas uint64 + GasPrice uint64 + From light_types.Kr + Ins []GIn + Outs []light_types.GOut +} + +type ISSI interface { + GetBlocksInfo(start uint64, count uint64) ([]Block, error) + Detail(root []keys.Uint256, skr *keys.PKr) ([]light_types.DOut, error) + GenTx(param GenTxParam) (keys.Uint256, error) + CommitTx(txhash keys.Uint256) error +} diff --git a/zero/light/sri.go b/zero/light/sri.go index 6afabf85..8ca41233 100644 --- a/zero/light/sri.go +++ b/zero/light/sri.go @@ -64,8 +64,8 @@ func (self *SRI) GetAnchor(roots []keys.Uint256) (wits []light_types.Witness, e for _, root := range roots { wit := light_types.Witness{} out := localdb.GetRoot(light_ref.Ref_inst.Bc.GetDB(), &root) - if out==nil { - e=errors.New("GetAnchor use root but out is nil !!!") + if out == nil { + e = errors.New("GetAnchor use root but out is nil !!!") return } pos, paths, anchor := state.State.MTree.GetPaths(*out.OS.RootCM) diff --git a/zero/light/ssi.go b/zero/light/ssi.go new file mode 100644 index 00000000..c1705a01 --- /dev/null +++ b/zero/light/ssi.go @@ -0,0 +1,32 @@ +package light + +import ( + "github.com/sero-cash/go-czero-import/keys" + "github.com/sero-cash/go-sero/zero/light/light_issi" + "github.com/sero-cash/go-sero/zero/light/light_types" +) + +type SSI struct { +} + +var SSI_Inst = SSI{} + +func (self *SSI) GetBlocksInfo(start uint64, count uint64) (blocks []light_issi.Block, e error) { + + return +} + +func (self *SSI) Detail(root []keys.Uint256, skr *keys.PKr) (douts []light_types.DOut, e error) { + + return +} + +func (self *SSI) GenTx(param light_issi.GenTxParam) (hash keys.Uint256, e error) { + + return +} + +func (self *SSI) CommitTx(txhash keys.Uint256) (e error) { + + return +} diff --git a/zero/txs/generate/pre_tx.go b/zero/txs/generate/pre_tx.go index b6bfb84f..99a03c8a 100644 --- a/zero/txs/generate/pre_tx.go +++ b/zero/txs/generate/pre_tx.go @@ -20,6 +20,8 @@ import ( "encoding/hex" "fmt" + "github.com/sero-cash/go-sero/zero/zconfig" + "github.com/sero-cash/go-sero/zero/localdb" "github.com/sero-cash/go-sero/zero/txs/pkg" @@ -96,6 +98,11 @@ func preGen(ts *tx.T, state1 *lstate.State) (p preTx, e error) { } } + if len(p.desc_o.ins) > zconfig.MAX_O_INS_LENGTH { + e = fmt.Errorf("pre gen tx O ins length > %v,current is %v", zconfig.MAX_O_INS_LENGTH, len(p.desc_o.ins)) + return + } + if ts.PkgClose != nil { if zpkg := state1.State.Pkgs.GetPkgById(&ts.PkgClose.Id); zpkg == nil || zpkg.Closed { e = fmt.Errorf("Get Pkg error %v", hex.EncodeToString(ts.PkgClose.Id[:])) diff --git a/zero/txs/verify/txs_verify.go b/zero/txs/verify/txs_verify.go index fb796527..544fe1cf 100644 --- a/zero/txs/verify/txs_verify.go +++ b/zero/txs/verify/txs_verify.go @@ -20,6 +20,8 @@ import ( "errors" "fmt" + "github.com/sero-cash/go-sero/zero/zconfig" + "github.com/sero-cash/go-sero/common/hexutil" "github.com/sero-cash/go-sero/zero/txs/zstate" @@ -83,6 +85,13 @@ func Verify_state1(s *stx.T, state *zstate.ZState) (e error) { var verify_input_o_procs = verify_input_o_procs_pool.GetProcs() defer verify_input_o_procs_pool.PutProcs(verify_input_o_procs) + if state.State.Num() >= zconfig.VP0 { + if len(s.Desc_O.Ins) > zconfig.MAX_O_INS_LENGTH { + e = fmt.Errorf("txs.verify O ins length > %v, current is %v", zconfig.MAX_O_INS_LENGTH, len(s.Desc_O.Ins)) + return + } + } + for _, in_o := range s.Desc_O.Ins { if state.Num() >= cpt.SIP2 { if ok := state.State.HasIn(&in_o.Nil); ok { diff --git a/zero/txs/zstate/txstate/data/data.go b/zero/txs/zstate/txstate/data/data.go index 8fdb6f5b..ca322042 100644 --- a/zero/txs/zstate/txstate/data/data.go +++ b/zero/txs/zstate/txstate/data/data.go @@ -59,6 +59,10 @@ func (self *Data) addOutByRoot(k *keys.Uint256, out *localdb.OutState) { self.Dirty_G2outs[*k] = true } +func (self *Data) AddTxOut(pkr *keys.PKr) int { + return 0 +} + func (self *Data) AddOut(root *keys.Uint256, out *localdb.OutState, txhash *keys.Uint256) { self.addOutByRoot(root, out) self.appendRoot(root) diff --git a/zero/txs/zstate/txstate/data/iface.go b/zero/txs/zstate/txstate/data/iface.go index f6cdf72e..8254fbc5 100644 --- a/zero/txs/zstate/txstate/data/iface.go +++ b/zero/txs/zstate/txstate/data/iface.go @@ -9,6 +9,8 @@ import ( type IData interface { Clear() + + AddTxOut(pkr *keys.PKr) int AddOut(root *keys.Uint256, out *localdb.OutState, txhash *keys.Uint256) AddNil(in *keys.Uint256) AddDel(in *keys.Uint256) diff --git a/zero/txs/zstate/txstate/data_v1/data.go b/zero/txs/zstate/txstate/data_v1/data.go index c2de6e24..3b18d65e 100644 --- a/zero/txs/zstate/txstate/data_v1/data.go +++ b/zero/txs/zstate/txstate/data_v1/data.go @@ -15,6 +15,8 @@ type Data struct { Dels utils.Dirtys Nils utils.HSet Roots utils.HSet + + PKr2Count map[keys.PKr]int } func NewData(num uint64) (ret *Data) { @@ -27,11 +29,23 @@ func NewData(num uint64) (ret *Data) { func (state *Data) Clear() { state.Root2Out = make(map[keys.Uint256]localdb.RootState) + state.PKr2Count = make(map[keys.PKr]int) state.Dels.Clear() state.Nils.Clear() state.Roots.Clear() } +func (self *Data) AddTxOut(pkr *keys.PKr) int { + if count, ok := self.PKr2Count[*pkr]; !ok { + self.PKr2Count[*pkr] = 1 + return 1 + } else { + count++ + self.PKr2Count[*pkr] = count + return count + } +} + func (self *Data) AddOut(root *keys.Uint256, out *localdb.OutState, txhash *keys.Uint256) { self.Roots.Append(root) rs := localdb.RootState{} diff --git a/zero/txs/zstate/txstate/data_v1/data_state.go b/zero/txs/zstate/txstate/data_v1/data_state.go index 179b8369..cfdf958f 100644 --- a/zero/txs/zstate/txstate/data_v1/data_state.go +++ b/zero/txs/zstate/txstate/data_v1/data_state.go @@ -26,6 +26,7 @@ func (self *Data) LoadState(tr tri.Tri) { func (self *Data) SaveState(tr tri.Tri) { self.Nils.Save(tr) self.Roots.Save(tr) + self.PKr2Count = make(map[keys.PKr]int) return } diff --git a/zero/txs/zstate/txstate/state.go b/zero/txs/zstate/txstate/state.go index ed66d1fc..2102f3d4 100644 --- a/zero/txs/zstate/txstate/state.go +++ b/zero/txs/zstate/txstate/state.go @@ -101,6 +101,10 @@ func (self *State) Revert(revid int) { self.data = self.snapshots.Revert(revid).(data.IData) } +func (self *State) AddTxOut(pkr *keys.PKr) int { + return self.data.AddTxOut(pkr) +} + func (state *State) AddOut(out_o *stx.Out_O, out_z *stx.Out_Z, txhash *keys.Uint256) (root keys.Uint256) { state.rw.Lock() defer state.rw.Unlock() diff --git a/zero/txs/zstate/zstate.go b/zero/txs/zstate/zstate.go index 92b8ef21..6000a8e4 100644 --- a/zero/txs/zstate/zstate.go +++ b/zero/txs/zstate/zstate.go @@ -17,10 +17,12 @@ package zstate import ( - "github.com/sero-cash/go-sero/core/types" - "github.com/sero-cash/go-sero/zero/localdb" + "github.com/sero-cash/go-sero/log" + "github.com/sero-cash/go-sero/core/types" "github.com/sero-cash/go-sero/serodb" + "github.com/sero-cash/go-sero/zero/localdb" + "github.com/sero-cash/go-sero/zero/zconfig" "github.com/sero-cash/go-sero/zero/txs/assets" "github.com/sero-cash/go-sero/zero/txs/zstate/pkgstate" @@ -125,6 +127,21 @@ func (state *ZState) AddStx(st *stx.T) (e error) { return } +func (state *ZState) AddTxOutWithCheck(addr common.Address, asset assets.Asset) (alarm bool) { + alarm = false + if state.Num() >= zconfig.VP0 { + count := state.State.AddTxOut(addr.ToPKr()) + if count > zconfig.MAX_TX_OUT_COUNT_LENGTH { + log.Error("[ALARM] ZState AddTxOut Overflow", "MAX_TX_OUT_COUNT_LENGTH", zconfig.MAX_TX_OUT_COUNT_LENGTH) + alarm = true + } + } + + state.AddTxOut(addr, asset) + + return +} + func (state *ZState) AddTxOut(addr common.Address, asset assets.Asset) { t := utils.TR_enter("AddTxOut-----") need_add := false @@ -147,4 +164,6 @@ func (state *ZState) AddTxOut(addr common.Address, asset assets.Asset) { state.AddOut_O(&o) } t.Leave() + + return } diff --git a/zero/zconfig/config.go b/zero/zconfig/config.go index 6c5b4d47..019b3c27 100644 --- a/zero/zconfig/config.go +++ b/zero/zconfig/config.go @@ -79,3 +79,9 @@ func State1_file(last_fork string) string { file := filepath.Join(state1_dir, last_fork) return file } + +var VP0 = uint64(788888) + +var MAX_O_INS_LENGTH = 2500 + +var MAX_TX_OUT_COUNT_LENGTH = 256