Skip to content

Commit 74ca8ac

Browse files
committed
add multiy recharge
1 parent 0900c01 commit 74ca8ac

12 files changed

+242
-98
lines changed

core/gaspool.go

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ func (gp *GasPool) AddGas(amount uint64) *GasPool {
3838
// available and returns an error otherwise.
3939
func (gp *GasPool) SubGas(amount uint64) error {
4040
if uint64(*gp) < amount {
41+
fmt.Println("1111111111 ")
4142
return ErrGasLimitReached
4243
}
4344
*(*uint64)(gp) -= amount

core/state_transition.go

+52-37
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,8 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
213213
sender := vm.AccountRef(msg.From())
214214
contractCreation := msg.To() == nil
215215
isRefundWithdrawTx := false
216+
var recharges spv.RechargeDatas
217+
var totalFee *big.Int
216218

217219
//recharge tx and widthdraw refund
218220
if msg.To() != nil && *msg.To() == blackaddr {
@@ -272,46 +274,52 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
272274
txhash = hexutil.Encode(msg.Data())
273275
}
274276
if len(msg.Data()) == 32 || isSmallRechargeTx {
275-
fee, toaddr, output := spv.FindOutputFeeAndaddressByTxHash(txhash)
276-
if toaddr != blackaddr {
277-
completetxhash := evm.StateDB.GetState(blackaddr, common.HexToHash(txhash))
278-
if (completetxhash == emptyHash) && output.Cmp(fee) > 0 {
279-
st.state.AddBalance(st.msg.From(), new(big.Int).SetUint64(evm.ChainConfig().PassBalance))
280-
defer func() {
281-
ethfee := new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice)
282-
if fee.Cmp(new(big.Int)) <= 0 || fee.Cmp(ethfee) < 0 || st.state.GetBalance(toaddr).Uint64() < 0 || vmerr != nil {
283-
ret = nil
284-
usedGas = 0
285-
failed = false
286-
if err == nil {
287-
log.Error("fee is not enough :", "fee", fee.String(), "need", ethfee.String(), "vmerr", vmerr)
288-
err = ErrGasLimitReached
289-
}
290-
evm.StateDB.RevertToSnapshot(snapshot)
291-
return
292-
} else {
293-
st.state.AddBalance(st.msg.From(), fee)
294-
}
277+
recharges, totalFee, err = spv.GetRechargeDataByTxhash(txhash)
278+
if err != nil || len(recharges) <= 0 {
279+
log.Error("recharge data error", "error", err)
280+
return nil, 0, false, ErrElaToEthAddress
281+
}
282+
completetxhash := evm.StateDB.GetState(blackaddr, common.HexToHash(txhash))
283+
if completetxhash != emptyHash {
284+
return nil, 0, false, ErrMainTxHashPresence
285+
}
286+
for _, recharge := range recharges {
287+
if recharge.TargetAddress == blackaddr || recharge.TargetAmount.Cmp(recharge.Fee) < 0 {
288+
log.Error("recharge data error ", "fee", recharge.Fee.String(), "TargetAddress", recharge.TargetAddress.String(), "TargetAmount", recharge.TargetAmount.String(), "isSmallRechargeTx", isSmallRechargeTx)
289+
return nil, 0, false, ErrElaToEthAddress
290+
}
291+
}
295292

296-
if st.state.GetBalance(st.msg.From()).Cmp(new(big.Int).SetUint64(evm.ChainConfig().PassBalance)) < 0 {
297-
ret = nil
298-
usedGas = 0
299-
failed = false
300-
if err == nil {
301-
err = ErrGasLimitReached
302-
}
303-
evm.StateDB.RevertToSnapshot(snapshot)
304-
} else {
305-
st.state.SubBalance(st.msg.From(), new(big.Int).SetUint64(evm.ChainConfig().PassBalance))
293+
st.state.AddBalance(st.msg.From(), new(big.Int).SetUint64(evm.ChainConfig().PassBalance))
294+
defer func() {
295+
ethfee := new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice)
296+
for _, recharge := range recharges {
297+
if recharge.Fee.Cmp(new(big.Int)) <= 0 || st.state.GetBalance(recharge.TargetAddress).Uint64() < 0 {
298+
ret = nil
299+
usedGas = 0
300+
failed = false
301+
if err == nil {
302+
log.Error("ErrGasLimitReached 1111", "totalFee", totalFee.String(), "ethFee", ethfee.String(), " st.state.GetBalance(recharge.TargetAddress).Uint64()", st.state.GetBalance(recharge.TargetAddress).Uint64(), "targetAddress", recharge.TargetAddress)
303+
err = ErrGasLimitReached
306304
}
307-
}()
305+
evm.StateDB.RevertToSnapshot(snapshot)
306+
return
307+
}
308+
}
309+
st.state.AddBalance(st.msg.From(), totalFee)
310+
if st.state.GetBalance(st.msg.From()).Cmp(new(big.Int).SetUint64(evm.ChainConfig().PassBalance)) < 0 || totalFee.Cmp(ethfee) < 0 {
311+
ret = nil
312+
usedGas = 0
313+
failed = false
314+
if err == nil {
315+
log.Error("ErrGasLimitReached 22222", "totalFee", totalFee.String(), "ethFee", ethfee.String(), " st.state.GetBalance(st.msg.From())", st.state.GetBalance(st.msg.From()))
316+
err = ErrGasLimitReached
317+
}
318+
evm.StateDB.RevertToSnapshot(snapshot)
308319
} else {
309-
return nil, 0, false, ErrMainTxHashPresence
320+
st.state.SubBalance(st.msg.From(), new(big.Int).SetUint64(evm.ChainConfig().PassBalance))
310321
}
311-
} else {
312-
log.Info("recharge failed ", "fee", fee.String(), "toaddr", toaddr, "output", output, "isSmallRechargeTx", isSmallRechargeTx)
313-
return nil, 0, false, ErrElaToEthAddress
314-
}
322+
}()
315323
}
316324
}
317325
} else if contractCreation { //deploy contract
@@ -356,7 +364,14 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
356364
} else {
357365
// Increment the nonce for the next transaction
358366
st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)
359-
ret, st.gas, vmerr = evm.Call(sender, st.to(), st.data, st.gas, st.value)
367+
if len(recharges) > 0 {
368+
for _, recharge := range recharges {
369+
ret, st.gas, vmerr = evm.Call(sender, st.to(), st.data, st.gas, st.value, recharge)
370+
}
371+
} else {
372+
ret, st.gas, vmerr = evm.Call(sender, st.to(), st.data, st.gas, st.value, nil)
373+
}
374+
360375
}
361376
if vmerr != nil {
362377
log.Info("VM returned with error", "err", vmerr, "ret", string(ret))

core/tx_pool.go

+32-12
Original file line numberDiff line numberDiff line change
@@ -889,22 +889,42 @@ func (pool *TxPool) addTxsLocked(txs []*types.Transaction, local bool) ([]error,
889889
} else {
890890
txhash, _, _, _ = spv.IsSmallCrossTxByData(tx.Data())
891891
}
892-
fee, addr, output := spv.FindOutputFeeAndaddressByTxHash(txhash)
893-
if addr != blackAddr {
894-
if fee.Cmp(new(big.Int)) > 0 && output.Cmp(new(big.Int)) > 0 {
895-
ethFee := new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice())
896-
completeTxHash := pool.currentState.GetState(blackAddr, common.HexToHash(txhash))
897-
if fee.Cmp(ethFee) < 0 {
892+
//fee, addr, output := spv.FindOutputFeeAndaddressByTxHash(txhash)
893+
recharges, fee, err := spv.GetRechargeDataByTxhash(txhash)
894+
if err != nil {
895+
errs[i] = err
896+
}
897+
ethFee := new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice())
898+
completeTxHash := pool.currentState.GetState(blackAddr, common.HexToHash(txhash))
899+
if (completeTxHash != common.Hash{}) {
900+
errs[i] = ErrMainTxHashPresence
901+
}
902+
for _, recharge := range recharges {
903+
if recharge.TargetAddress != blackAddr {
904+
if recharge.Fee.Cmp(new(big.Int)) <= 0 && recharge.TargetAmount.Cmp(new(big.Int)) <= 0 {
898905
errs[i] = ErrGasLimitReached
899-
} else if (completeTxHash != common.Hash{}) {
900-
errs[i] = ErrMainTxHashPresence
906+
break
901907
}
902-
} else {
903-
errs[i] = ErrGasLimitReached
904908
}
905-
} else {
906-
errs[i] = ErrElaToEthAddress
907909
}
910+
if fee.Cmp(ethFee) < 0 {
911+
errs[i] = ErrGasLimitReached
912+
}
913+
//if addr != blackAddr {
914+
// if fee.Cmp(new(big.Int)) > 0 && output.Cmp(new(big.Int)) > 0 {
915+
// ethFee := new(big.Int).Mul(new(big.Int).SetUint64(tx.Gas()), tx.GasPrice())
916+
// completeTxHash := pool.currentState.GetState(blackAddr, common.HexToHash(txhash))
917+
// if fee.Cmp(ethFee) < 0 {
918+
// errs[i] = ErrGasLimitReached
919+
// } else if (completeTxHash != common.Hash{}) {
920+
// errs[i] = ErrMainTxHashPresence
921+
// }
922+
// } else {
923+
// errs[i] = ErrGasLimitReached
924+
// }
925+
//} else {
926+
// errs[i] = ErrElaToEthAddress
927+
//}
908928
}
909929
}
910930
}

core/vm/evm.go

+24-18
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ func (evm *EVM) Interpreter() Interpreter {
190190
// parameters. It also handles any necessary value transfer required and takes
191191
// the necessary steps to create accounts and reverses the state in case of an
192192
// execution error or failed value transfer.
193-
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
193+
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int, recharge *spv.RechargeData) (ret []byte, leftOverGas uint64, err error) {
194194
if evm.vmConfig.NoRecursion && evm.depth > 0 {
195195
return nil, gas, nil
196196
}
@@ -207,6 +207,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
207207
txHash string
208208
)
209209
isRechargeTx := false
210+
var targetMemoData []byte
210211
//this is recharge tx
211212
if blackAddr == addr {
212213
emptyHash := common.Hash{}
@@ -229,18 +230,18 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
229230
topics[3] = common.HexToHash(from)
230231
topics[4] = common.BigToHash(amount)
231232
evm.StateDB.AddLog(&types.Log{
232-
Address: common.HexToAddress(evm.chainConfig.BlackContractAddr),
233-
Topics:topics,
234-
Data:nil,
235-
BlockNumber:evm.BlockNumber.Uint64(),
233+
Address: common.HexToAddress(evm.chainConfig.BlackContractAddr),
234+
Topics: topics,
235+
Data: nil,
236+
BlockNumber: evm.BlockNumber.Uint64(),
236237
})
237238
//first give caller, then caller transfer to target behind
238239
evm.StateDB.AddBalance(caller.Address(), amount)
239240
withdrawfailedtx.OnProcessFaildWithdrawTx(txid)
240241
} else {
241242
return nil, gas, ErrWithdawrefundCallFailed
242243
}
243-
} else {
244+
} else if recharge != nil {
244245
isSmallRechargeTx := false
245246
if len(input) > 32 {
246247
rawTxid, _, _, _ := spv.IsSmallCrossTxByData(input)
@@ -250,27 +251,33 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
250251
if len(input) == 32 {
251252
txHash = hexutil.Encode(input)
252253
}
254+
253255
if len(input) == 32 || isSmallRechargeTx {
254256
completeTxHash := evm.StateDB.GetState(blackAddr, common.HexToHash(txHash))
255-
fee, address, output := spv.FindOutputFeeAndaddressByTxHash(txHash)
256-
addr = address
257-
if completeTxHash == emptyHash && addr != blackAddr && output.Cmp(fee) > 0 {
257+
if completeTxHash != emptyHash {
258+
return nil, gas, spv.ErrMainTxHashPresence
259+
}
260+
addr = recharge.TargetAddress
261+
if recharge.TargetAddress != blackAddr && recharge.TargetAmount.Cmp(recharge.Fee) >= 0 {
258262
isRechargeTx = true
259-
to = AccountRef(addr)
260-
value = new(big.Int).Sub(output, fee)
263+
to = AccountRef(recharge.TargetAddress)
264+
if len(recharge.TargetData) > 0 {
265+
targetMemoData = recharge.TargetData
266+
}
267+
value = new(big.Int).Sub(recharge.TargetAmount, recharge.Fee)
261268
topics := make([]common.Hash, 5)
262269
topics[0] = common.HexToHash("0x09f15c376272c265d7fcb47bf57d8f84a928195e6ea156d12f5a3cd05b8fed5a")
263270
topics[1] = common.HexToHash(caller.Address().String())
264271
topics[2] = common.HexToHash(txHash)
265-
topics[3] = common.HexToHash(addr.String())
272+
topics[3] = common.HexToHash(recharge.TargetAddress.String())
266273
topics[4] = common.BigToHash(value)
267274
evm.StateDB.AddLog(&types.Log{
268-
Address:blackAddr,
269-
Topics:topics,
270-
Data:nil,
275+
Address: blackAddr,
276+
Topics: topics,
277+
Data: nil,
271278
// This is a non-consensus field, but assigned here because
272279
// core/state doesn't know the current block number.
273-
BlockNumber:evm.BlockNumber.Uint64(),
280+
BlockNumber: evm.BlockNumber.Uint64(),
274281
})
275282
evm.StateDB.AddBalance(caller.Address(), value)
276283
}
@@ -319,8 +326,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
319326
}()
320327
}
321328
if isRechargeTx {
322-
inputData := spv.FindOutRechargeInput(txHash)
323-
ret, err = run(evm, contract, inputData, false)
329+
ret, err = run(evm, contract, targetMemoData, false)
324330
} else {
325331
ret, err = run(evm, contract, input, false)
326332
}

core/vm/gas_table_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func TestEIP2200(t *testing.T) {
9393
}
9494
vmenv := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
9595

96-
_, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(big.Int))
96+
_, gas, err := vmenv.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(big.Int), nil)
9797
if err != tt.failure {
9898
t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.failure)
9999
}

core/vm/instructions.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,7 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory
760760
if value.Sign() != 0 {
761761
gas += params.CallStipend
762762
}
763-
ret, returnGas, err := interpreter.evm.Call(contract, toAddr, args, gas, value)
763+
ret, returnGas, err := interpreter.evm.Call(contract, toAddr, args, gas, value, nil)
764764
if err != nil {
765765
stack.push(interpreter.intPool.getZero())
766766
} else {

core/vm/runtime/runtime.go

+2
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
117117
input,
118118
cfg.GasLimit,
119119
cfg.Value,
120+
nil,
120121
)
121122

122123
return ret, cfg.State, err
@@ -165,6 +166,7 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er
165166
input,
166167
cfg.GasLimit,
167168
cfg.Value,
169+
nil,
168170
)
169171

170172
return ret, leftOverGas, err

smallcrosstx/smallcrossTx_test.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import (
1111

1212
func TestSmallCrossTx_Deserialize(t *testing.T) {
1313
tx := &SmallCrossTx{
14-
RawTxID: "215c669bf8fd2a7d8ebf9d2689428c1ed1e2a85c8292e6ee0032ae7732619606",
15-
RawTx: "3e1b0efac4212580f1014ed68f8c432ed886b4888065e26dad8023feecc9c468",
16-
Signatures: []string{"123","456"},
14+
RawTxID: "215c669bf8fd2a7d8ebf9d2689428c1ed1e2a85c8292e6ee0032ae7732619606",
15+
RawTx: "3e1b0efac4212580f1014ed68f8c432ed886b4888065e26dad8023feecc9c468",
16+
Signatures: []string{"123", "456"},
1717
BlockHeight: 889898,
1818
}
1919

@@ -32,7 +32,7 @@ func TestSmallCrossTx_Deserialize(t *testing.T) {
3232

3333
byteData, err := common.HexStringToBytes(hexString)
3434
assert.NoError(t, err)
35-
data = bytes.NewBuffer(byteData[:len(byteData) - 2])
35+
data = bytes.NewBuffer(byteData[:len(byteData)-2])
3636
tx3 := &SmallCrossTx{}
3737
err = tx3.Deserialize(data)
3838
assert.Error(t, err)

0 commit comments

Comments
 (0)