Fix for issue 576 where private transactions can cause block gas limit to be exceeded, leading to BAD BLOCK.

This commit is contained in:
SatpalSandhu61 2018-12-10 09:58:16 +00:00
parent 912140d06f
commit 5af110984a
1 changed files with 23 additions and 3 deletions

View File

@ -162,7 +162,9 @@ func (st *StateTransition) buyGas() error {
if st.state.GetBalance(st.msg.From()).Cmp(mgval) < 0 {
return errInsufficientBalanceForGas
}
log.Info("======== Attempting to subtract gas", "gasToSubtract", st.msg.Gas(), "gas", st.gp.Gas())
if err := st.gp.SubGas(st.msg.Gas()); err != nil {
log.Info("======== Subtraction failed!!!", "err", err)
return err
}
st.gas += st.msg.Gas()
@ -218,7 +220,10 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
data = st.data
}
// Pay intrinsic gas
log.Info("======== remaining gas prior to IntrinsicGas()", "gas", st.gas)
// Pay intrinsic gas. For a private contract this is done using the public hash passed in,
// not the private data retrieved above. This is because we need any (participant) validator
// node to get the same result as a (non-participant) minter node, to avoid out-of-gas issues.
gas, err := IntrinsicGas(st.data, contractCreation, homestead)
if err != nil {
return nil, 0, false, err
@ -226,8 +231,10 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
if err = st.useGas(gas); err != nil {
return nil, 0, false, err
}
log.Info("======== remaining gas after IntrinsicGas()", "gas", st.gas)
var (
leftoverGas uint64
evm = st.evm
// vm errors do not effect consensus and are therefor
// not assigned to err, except for insufficient balance
@ -235,7 +242,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
vmerr error
)
if contractCreation {
ret, _, st.gas, vmerr = evm.Create(sender, data, st.gas, st.value)
ret, _, leftoverGas, vmerr = evm.Create(sender, data, st.gas, st.value)
} else {
// Increment the account nonce only if the transaction isn't private.
// If the transaction is private it has already been incremented on
@ -254,7 +261,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
return nil, 0, false, nil
}
ret, st.gas, vmerr = evm.Call(sender, to, data, st.gas, st.value)
ret, leftoverGas, vmerr = evm.Call(sender, to, data, st.gas, st.value)
}
if vmerr != nil {
log.Debug("VM returned with error", "err", vmerr)
@ -265,8 +272,21 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
return nil, 0, false, vmerr
}
}
//Pay gas used during contract creation or execution (st.gas tracks remaining gas)
//However, if private contract then we don't want to do this else we could
//have a mismatch between a (non-participant) minter and (participant) validator,
//which can cause a 'BAD BLOCK' crash.
if !isPrivate {
st.gas = leftoverGas
log.Info("======== setting leftoverGas for public transaction after Create or Call", "gas", st.gas)
}
log.Info("======== left over gas to be refunded", "gas", st.gas)
log.Info("======== remaining gas prior to refundGas()", "gas", st.gas)
st.refundGas()
st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
log.Info("======== remaining gas after refundGas()", "gas", st.gas)
if isPrivate {
return ret, 0, vmerr != nil, err