Example #1
0
// Tell mempool that these txs were committed.
// Mempool will discard these txs.
// NOTE: this should be called *after* block is committed by consensus.
func (mem *Mempool) ResetForBlockAndState(block *types.Block, state *sm.State) {
	mem.mtx.Lock()
	defer mem.mtx.Unlock()

	mem.state = state.Copy()
	mem.cache = sm.NewBlockCache(mem.state)

	// First, create a lookup map of txns in new txs.
	txsMap := make(map[string]struct{})
	for _, tx := range block.Data.Txs {
		txsMap[mem.TxID(tx)] = struct{}{}
	}

	// Set height
	mem.height = block.Height
	// Remove transactions that are already in txs.
	goodTxs := mem.filterTxs(txsMap)
	// Recheck mempool txs
	// TODO: make optional
	mem.recheckTxs(goodTxs)

	// At this point, mem.txs are being rechecked.
	// mem.recheckCursor re-scans mem.txs and possibly removes some txs.
	// Before mem.Reap(), we should wait for mem.recheckCursor to be nil.
}
Example #2
0
// Run a contract's code on an isolated and unpersisted state
// Cannot be used to create new contracts
func (this *transactor) Call(fromAddress, toAddress, data []byte) (*Call, error) {

	st := this.consensusState.GetState() // performs a copy
	cache := state.NewBlockCache(st)
	outAcc := cache.GetAccount(toAddress)
	if outAcc == nil {
		return nil, fmt.Errorf("Account %X does not exist", toAddress)
	}
	if fromAddress == nil {
		fromAddress = []byte{}
	}
	callee := toVMAccount(outAcc)
	caller := &vm.Account{Address: cmn.LeftPadWord256(fromAddress)}
	txCache := state.NewTxCache(cache)
	params := vm.Params{
		BlockHeight: int64(st.LastBlockHeight),
		BlockHash:   cmn.LeftPadWord256(st.LastBlockHash),
		BlockTime:   st.LastBlockTime.Unix(),
		GasLimit:    10000000,
	}

	vmach := vm.NewVM(txCache, params, caller.Address, nil)
	vmach.SetFireable(this.eventSwitch)
	gas := int64(1000000000)
	ret, err := vmach.Call(caller, callee, callee.Code, data, 0, &gas)
	if err != nil {
		return nil, err
	}
	return &Call{Return: hex.EncodeToString(ret)}, nil
}
Example #3
0
// Run a contract's code on an isolated and unpersisted state
// Cannot be used to create new contracts
func Call(fromAddress, toAddress, data []byte) (*ctypes.ResponseCall, error) {
	st := consensusState.GetState() // performs a copy
	cache := state.NewBlockCache(st)
	outAcc := cache.GetAccount(toAddress)
	if outAcc == nil {
		return nil, fmt.Errorf("Account %x does not exist", toAddress)
	}
	callee := toVMAccount(outAcc)
	caller := &vm.Account{Address: LeftPadWord256(fromAddress)}
	txCache := state.NewTxCache(cache)
	params := vm.Params{
		BlockHeight: int64(st.LastBlockHeight),
		BlockHash:   LeftPadWord256(st.LastBlockHash),
		BlockTime:   st.LastBlockTime.Unix(),
		GasLimit:    st.GetGasLimit(),
	}

	vmach := vm.NewVM(txCache, params, caller.Address, nil)
	gas := st.GetGasLimit()
	ret, err := vmach.Call(caller, callee, callee.Code, data, 0, &gas)
	if err != nil {
		return nil, err
	}
	return &ctypes.ResponseCall{Return: ret}, nil
}
Example #4
0
func resetPeer(t *testing.T, reactor *MempoolReactor, mempool *Mempool, state *sm.State, tickerChan chan time.Time, newBlockChan chan ResetInfo, peer *TestPeer) *TestPeer {
	// reset peer
	mempool.txs = []types.Tx{}
	mempool.state = state
	mempool.cache = sm.NewBlockCache(state)
	peer.SetRunning(false)
	tickerChan <- time.Now()
	peer = newPeer(t, state)
	go reactor.broadcastTxRoutine(tickerChan, newBlockChan, peer)
	return peer
}
Example #5
0
func NewMempool(state *sm.State) *Mempool {
	mempool := &Mempool{
		state:         state,
		cache:         sm.NewBlockCache(state),
		txs:           clist.New(),
		counter:       0,
		height:        0,
		rechecking:    0,
		recheckCursor: nil,
		recheckEnd:    nil,

		cacheMap:  make(map[string]struct{}, cacheSize),
		cacheList: list.New(),
	}
	return mempool
}
Example #6
0
// "block" is the new block being committed.
// "state" is the result of state.AppendBlock("block").
// Txs that are present in "block" are discarded from mempool.
// Txs that have become invalid in the new "state" are also discarded.
func (mem *Mempool) ResetForBlockAndState(block *types.Block, state *sm.State) ResetInfo {
	mem.mtx.Lock()
	defer mem.mtx.Unlock()
	mem.state = state.Copy()
	mem.cache = sm.NewBlockCache(mem.state)

	// First, create a lookup map of txns in new block.
	blockTxsMap := make(map[string]struct{})
	for _, tx := range block.Data.Txs {
		blockTxsMap[string(types.TxID(state.ChainID, tx))] = struct{}{}
	}

	// Now we filter all txs from mem.txs that are in blockTxsMap,
	// and ExecTx on what remains. Only valid txs are kept.
	// We track the ranges of txs included in the block and invalidated by it
	// so we can tell peer routines
	var ri = ResetInfo{Height: block.Height}
	var validTxs []types.Tx
	includedStart, invalidStart := -1, -1
	for i, tx := range mem.txs {
		txID := types.TxID(state.ChainID, tx)
		if _, ok := blockTxsMap[string(txID)]; ok {
			startRange(&includedStart, i)           // start counting included txs
			endRange(&invalidStart, i, &ri.Invalid) // stop counting invalid txs
			log.Info("Filter out, already committed", "tx", tx, "txID", txID)
		} else {
			endRange(&includedStart, i, &ri.Included) // stop counting included txs
			err := sm.ExecTx(mem.cache, tx, false, nil)
			if err != nil {
				startRange(&invalidStart, i) // start counting invalid txs
				log.Info("Filter out, no longer valid", "tx", tx, "error", err)
			} else {
				endRange(&invalidStart, i, &ri.Invalid) // stop counting invalid txs
				log.Info("Filter in, new, valid", "tx", tx, "txID", txID)
				validTxs = append(validTxs, tx)
			}
		}
	}
	endRange(&includedStart, len(mem.txs)-1, &ri.Included) // stop counting included txs
	endRange(&invalidStart, len(mem.txs)-1, &ri.Invalid)   // stop counting invalid txs

	// We're done!
	log.Info("New txs", "txs", validTxs, "oldTxs", mem.txs)
	mem.txs = validTxs
	return ri
}
Example #7
0
// "block" is the new block being committed.
// "state" is the result of state.AppendBlock("block").
// Txs that are present in "block" are discarded from mempool.
// Txs that have become invalid in the new "state" are also discarded.
func (mem *Mempool) ResetForBlockAndState(block *types.Block, state *sm.State) {
	mem.mtx.Lock()
	defer mem.mtx.Unlock()
	mem.state = state.Copy()
	mem.cache = sm.NewBlockCache(mem.state)

	// First, create a lookup map of txns in new block.
	blockTxsMap := make(map[string]struct{})
	for _, tx := range block.Data.Txs {
		blockTxsMap[string(types.TxID(state.ChainID, tx))] = struct{}{}
	}

	// Next, filter all txs from mem.txs that are in blockTxsMap
	txs := []types.Tx{}
	for _, tx := range mem.txs {
		txID := types.TxID(state.ChainID, tx)
		if _, ok := blockTxsMap[string(txID)]; ok {
			log.Debug("Filter out, already committed", "tx", tx, "txID", txID)
			continue
		} else {
			log.Debug("Filter in, still new", "tx", tx, "txID", txID)
			txs = append(txs, tx)
		}
	}

	// Next, filter all txs that aren't valid given new state.
	validTxs := []types.Tx{}
	for _, tx := range txs {
		err := sm.ExecTx(mem.cache, tx, false, nil)
		if err == nil {
			log.Debug("Filter in, valid", "tx", tx)
			validTxs = append(validTxs, tx)
		} else {
			// tx is no longer valid.
			log.Debug("Filter out, no longer valid", "tx", tx, "error", err)
		}
	}

	// We're done!
	log.Debug("New txs", "txs", validTxs, "oldTxs", mem.txs)
	mem.txs = validTxs
}
Example #8
0
func NewMempool(state *sm.State) *Mempool {
	return &Mempool{
		state: state,
		cache: sm.NewBlockCache(state),
	}
}