소스 코드에서 이더리움 Replacementtransaction underpriced 이상 분석
3518 단어 이태방
func (pool *TxPool) add(tx *types.Transaction, local bool) (replaced bool, err error) {
//--------- ------------------------
from, _ := types.Sender(pool.signer, tx) // already validated
if list := pool.pending[from]; list != nil && list.Overlaps(tx) {
// Nonce already pending, check if required price bump is met
inserted, old := list.Add(tx, pool.config.PriceBump)
if !inserted {
pendingDiscardMeter.Mark(1)
return false, ErrReplaceUnderpriced //
}
// New transaction is better, replace old one
if old != nil {
pool.all.Remove(old.Hash())
pool.priced.Removed(1)
pendingReplaceMeter.Mark(1)
}
//------------ -------------------
}
}
func (l *txList) Add(tx *types.Transaction, priceBump uint64) (bool, *types.Transaction) {
// If there's an older better transaction, abort
old := l.txs.Get(tx.Nonce())
if old != nil {
threshold := new(big.Int).Div(new(big.Int).Mul(old.GasPrice(), big.NewInt(100+int64(priceBump))), big.NewInt(100))
// Have to ensure that the new gas price is higher than the old gas
// price as well as checking the percentage threshold to ensure that
// this is accurate for low (Wei-level) gas price replacements
//pending nonce , nonce threshold
if old.GasPrice().Cmp(tx.GasPrice()) >= 0 || threshold.Cmp(tx.GasPrice()) > 0 {
return false, nil
}
}
// Otherwise overwrite the old transaction with the current one
l.txs.Put(tx)
if cost := tx.Cost(); l.costcap.Cmp(cost) < 0 {
l.costcap = cost
}
if gas := tx.Gas(); l.gascap < gas {
l.gascap = gas
}
return true, old
}
pending 대기열에는 이미 같은 nonce 값의 거래가 있고 신구 두 거래의 nonce가 같거나 새로운 거래의 값이threshold 값보다 작다. 이것은 오보의 원인이다. 그러나gas의 비용은 자동으로 계산되기 때문에 원인은 nonce 값에 있다. 거래를 보내는 코드를 보면 nonce 값이 들어가지 않고 결점이 거래 소식을 받은 후,전송된 매개 변수 nonce 값이 비어 있으면 기존 pending 대기열에서 같은 nonce를 가져옵니다. nonce 값은 블록이 포장될 때까지 기다려야 거래 메시지를 state DB로 지속할 때 +1 변화가 있습니다.//다음은 기본 nonce 코드를 가져오는 것입니다
// setDefaults is a helper function that fills in default values for unspecified tx fields.
func (args *SendTxArgs) setDefaults(ctx context.Context, b Backend) error {
//
if args.Nonce == nil {
nonce, err := b.GetPoolNonce(ctx, args.From)
if err != nil {
return err
}
args.Nonce = (*hexutil.Uint64)(&nonce)
}
//
}
//다음은 거래를 수행할 때 블록에 포장된 코드입니다
// TransitionDb will transition the state by applying the current message and
// returning the result including the used gas. It returns an error if failed.
// An error indicates a consensus issue.
func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bool, err error) {
//
if contractCreation {
ret, _, st.gas, vmerr = evm.Create(sender, st.data, st.gas, st.value)
} else {
// Increment the nonce for the next transaction
st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1) // +1
ret, st.gas, vmerr = evm.Call(sender, st.to(), st.data, st.gas, st.value)
}
//
}
이 문제를 해결하려면 두 가지 방식이 있다. 첫째, 호출자가 nonce 값을 유지하고 자신이 매번 거래를 만들 때마다 nonce 값이 변화하고 거래 매개 변수를 전송한다. 2. 상기 거래 비용을 토대로 가스를 많이 넣는다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
소스 코드에서 이더리움 Replacementtransaction underpriced 이상 분석프로젝트에서 이더리움 이체 기능을 사용했는데 어느 날 이더리움 네트워크가 막혀서 이체가 Replacementtransaction underpriced 이상을 보고했습니다. 이 이상 키워드에 따라 이더리움 원본 코드를...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.