diff --git a/action/protocol/context.go b/action/protocol/context.go index 5227f6eb07..4a5360620b 100644 --- a/action/protocol/context.go +++ b/action/protocol/context.go @@ -110,6 +110,7 @@ type ( CorrectGasRefund bool SkipSystemActionNonce bool ValidateSystemAction bool + SharedGasWithDapp bool } // FeatureWithHeightCtx provides feature check functions. @@ -246,6 +247,7 @@ func WithFeatureCtx(ctx context.Context) context.Context { CorrectGasRefund: g.IsOkhotsk(height), SkipSystemActionNonce: g.IsPalau(height), ValidateSystemAction: g.IsToBeEnabled(height), + SharedGasWithDapp: g.IsToBeEnabled(height), }, ) } diff --git a/action/protocol/execution/evm/evm.go b/action/protocol/execution/evm/evm.go index 4baaf5a1d5..b7e5ef1af1 100644 --- a/action/protocol/execution/evm/evm.go +++ b/action/protocol/execution/evm/evm.go @@ -46,6 +46,19 @@ var ( ErrInconsistentNonce = errors.New("Nonce is not identical to executor nonce") ) +type ( + // GetBlockHash gets block hash by height + GetBlockHash func(uint64) (hash.Hash256, error) + + // DepositGasWithSGD deposits gas with Sharing of Gas-fee with DApps + DepositGasWithSGD func(context.Context, protocol.StateManager, address.Address, *big.Int, *big.Int) (*action.TransactionLog, error) + + // SGDRegistry is the interface for handling Sharing of Gas-fee with DApps + SGDRegistry interface { + CheckContract(context.Context, string) (address.Address, uint64, bool, error) + } +) + // CanTransfer checks whether the from account has enough balance func CanTransfer(db vm.StateDB, fromHash common.Address, balance *big.Int) bool { return db.GetBalance(fromHash).Cmp(balance) >= 0 @@ -191,7 +204,8 @@ func ExecuteContract( sm protocol.StateManager, execution *action.Execution, getBlockHash GetBlockHash, - depositGasFunc DepositGas, + depositGasFunc DepositGasWithSGD, + sgd SGDRegistry, ) ([]byte, *action.Receipt, error) { ctx, span := tracer.NewSpan(ctx, "evm.ExecuteContract") defer span.End() @@ -219,7 +233,10 @@ func ExecuteContract( } receipt.Status = uint64(statusCode) - var burnLog *action.TransactionLog + var ( + depositLog, burnLog *action.TransactionLog + consumedGas = depositGas - remainingGas + ) if featureCtx.FixDoubleChargeGas { // Refund all deposit and, actual gas fee will be subtracted when depositing gas fee to the rewarding protocol stateDB.AddBalance(ps.txCtx.Origin, big.NewInt(0).Mul(big.NewInt(0).SetUint64(depositGas), ps.txCtx.GasPrice)) @@ -228,19 +245,33 @@ func ExecuteContract( remainingValue := new(big.Int).Mul(new(big.Int).SetUint64(remainingGas), ps.txCtx.GasPrice) stateDB.AddBalance(ps.txCtx.Origin, remainingValue) } - if depositGas-remainingGas > 0 { + if consumedGas > 0 { burnLog = &action.TransactionLog{ Type: iotextypes.TransactionLogType_GAS_FEE, Sender: actionCtx.Caller.String(), Recipient: "", // burned - Amount: new(big.Int).Mul(new(big.Int).SetUint64(depositGas-remainingGas), ps.txCtx.GasPrice), + Amount: new(big.Int).Mul(new(big.Int).SetUint64(consumedGas), ps.txCtx.GasPrice), } } } - var depositLog *action.TransactionLog - if depositGas-remainingGas > 0 { - gasValue := new(big.Int).Mul(new(big.Int).SetUint64(depositGas-remainingGas), ps.txCtx.GasPrice) - depositLog, err = depositGasFunc(ctx, sm, gasValue) + if consumedGas > 0 { + var ( + receiver address.Address + sharedGas uint64 + sharedGasFee, totalGasFee *big.Int + ) + if featureCtx.SharedGasWithDapp && sgd != nil { + receiver, sharedGas, err = processSGD(ctx, sm, execution, consumedGas, sgd) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to process Sharing of Gas-fee with DApps") + } + } + if sharedGas > 0 { + sharedGasFee = big.NewInt(int64(sharedGas)) + sharedGasFee.Mul(sharedGasFee, ps.txCtx.GasPrice) + } + totalGasFee = new(big.Int).Mul(new(big.Int).SetUint64(consumedGas), ps.txCtx.GasPrice) + depositLog, err = depositGasFunc(ctx, sm, receiver, totalGasFee, sharedGasFee) if err != nil { return nil, nil, err } @@ -267,6 +298,24 @@ func ExecuteContract( return retval, receipt, nil } +func processSGD(ctx context.Context, sm protocol.StateManager, execution *action.Execution, consumedGas uint64, sgd SGDRegistry, +) (address.Address, uint64, error) { + if execution.Contract() == action.EmptyAddress { + return nil, 0, nil + } + + receiver, percentage, ok, err := sgd.CheckContract(ctx, execution.Contract()) + if err != nil || !ok { + return nil, 0, err + } + + sharedGas := consumedGas * percentage / 100 + if sharedGas > consumedGas { + sharedGas = consumedGas + } + return receiver, sharedGas, nil +} + // ReadContractStorage reads contract's storage func ReadContractStorage( ctx context.Context, @@ -569,8 +618,9 @@ func SimulateExecution( sm, ex, getBlockHash, - func(context.Context, protocol.StateManager, *big.Int) (*action.TransactionLog, error) { + func(context.Context, protocol.StateManager, address.Address, *big.Int, *big.Int) (*action.TransactionLog, error) { return nil, nil }, + nil, ) } diff --git a/action/protocol/execution/evm/evm_test.go b/action/protocol/execution/evm/evm_test.go index 5f3ca3e805..ee8f4017a5 100644 --- a/action/protocol/execution/evm/evm_test.go +++ b/action/protocol/execution/evm/evm_test.go @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/require" "github.com/iotexproject/go-pkgs/hash" + "github.com/iotexproject/iotex-address/address" "github.com/iotexproject/iotex-proto/golang/iotextypes" "github.com/iotexproject/iotex-core/action" @@ -63,9 +64,9 @@ func TestExecuteContractFailure(t *testing.T) { func(uint64) (hash.Hash256, error) { return hash.ZeroHash256, nil }, - func(context.Context, protocol.StateManager, *big.Int) (*action.TransactionLog, error) { + func(context.Context, protocol.StateManager, address.Address, *big.Int, *big.Int) (*action.TransactionLog, error) { return nil, nil - }) + }, nil) require.Nil(t, retval) require.Nil(t, receipt) require.Error(t, err) diff --git a/action/protocol/execution/evm/evmstatedbadapter.go b/action/protocol/execution/evm/evmstatedbadapter.go index 0e12f46d95..21e98fb6a1 100644 --- a/action/protocol/execution/evm/evmstatedbadapter.go +++ b/action/protocol/execution/evm/evmstatedbadapter.go @@ -7,7 +7,6 @@ package evm import ( "bytes" - "context" "encoding/hex" "fmt" "math/big" @@ -40,12 +39,6 @@ type ( // preimageMap records the preimage of hash reported by VM preimageMap map[common.Hash]protocol.SerializableBytes - // GetBlockHash gets block hash by height - GetBlockHash func(uint64) (hash.Hash256, error) - - // DepositGas deposits gas - DepositGas func(context.Context, protocol.StateManager, *big.Int) (*action.TransactionLog, error) - // StateDBAdapter represents the state db adapter for evm to access iotx blockchain StateDBAdapter struct { sm protocol.StateManager diff --git a/action/protocol/execution/protocol.go b/action/protocol/execution/protocol.go index e468cf36bd..108aa262c7 100644 --- a/action/protocol/execution/protocol.go +++ b/action/protocol/execution/protocol.go @@ -29,18 +29,19 @@ const ( // Protocol defines the protocol of handling executions type Protocol struct { getBlockHash evm.GetBlockHash - depositGas evm.DepositGas + depositGas evm.DepositGasWithSGD addr address.Address + sgdRegistry evm.SGDRegistry } // NewProtocol instantiates the protocol of exeuction -func NewProtocol(getBlockHash evm.GetBlockHash, depostGas evm.DepositGas) *Protocol { +func NewProtocol(getBlockHash evm.GetBlockHash, depositGasWithSGD evm.DepositGasWithSGD, sgd evm.SGDRegistry) *Protocol { h := hash.Hash160b([]byte(_protocolID)) addr, err := address.FromBytes(h[:]) if err != nil { log.L().Panic("Error when constructing the address of vote protocol", zap.Error(err)) } - return &Protocol{getBlockHash: getBlockHash, depositGas: depostGas, addr: addr} + return &Protocol{getBlockHash: getBlockHash, depositGas: depositGasWithSGD, addr: addr, sgdRegistry: sgd} } // FindProtocol finds the registered protocol from registry @@ -65,7 +66,7 @@ func (p *Protocol) Handle(ctx context.Context, act action.Action, sm protocol.St if !ok { return nil, nil } - _, receipt, err := evm.ExecuteContract(ctx, sm, exec, p.getBlockHash, p.depositGas) + _, receipt, err := evm.ExecuteContract(ctx, sm, exec, p.getBlockHash, p.depositGas, p.sgdRegistry) if err != nil { return nil, errors.Wrap(err, "failed to execute contract") diff --git a/action/protocol/execution/protocol_test.go b/action/protocol/execution/protocol_test.go index 766e38b800..fe5664d89a 100644 --- a/action/protocol/execution/protocol_test.go +++ b/action/protocol/execution/protocol_test.go @@ -455,7 +455,7 @@ func (sct *SmartContractTest) prepareBlockchain( r.NoError(reward.Register(registry)) r.NotNil(bc) - execution := NewProtocol(dao.GetBlockHash, rewarding.DepositGas) + execution := NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil) r.NoError(execution.Register(registry)) r.NoError(bc.Start(ctx)) @@ -605,7 +605,7 @@ func TestProtocol_Validate(t *testing.T) { require := require.New(t) p := NewProtocol(func(uint64) (hash.Hash256, error) { return hash.ZeroHash256, nil - }, rewarding.DepositGas) + }, rewarding.DepositGasWithSGD, nil) ex, err := action.NewExecution("2", uint64(1), big.NewInt(0), uint64(0), big.NewInt(0), make([]byte, 32684)) require.NoError(err) @@ -675,7 +675,7 @@ func TestProtocol_Handle(t *testing.T) { protocol.NewGenericValidator(sf, accountutil.AccountState), )), ) - exeProtocol := NewProtocol(dao.GetBlockHash, rewarding.DepositGas) + exeProtocol := NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil) require.NoError(exeProtocol.Register(registry)) require.NoError(bc.Start(ctx)) require.NotNil(bc) diff --git a/action/protocol/poll/consortium.go b/action/protocol/poll/consortium.go index 769232e291..021ff74d58 100644 --- a/action/protocol/poll/consortium.go +++ b/action/protocol/poll/consortium.go @@ -133,9 +133,10 @@ func (cc *consortiumCommittee) CreateGenesisStates(ctx context.Context, sm proto func(height uint64) (hash.Hash256, error) { return hash.ZeroHash256, nil }, - func(ctx context.Context, sm protocol.StateManager, amount *big.Int) (*action.TransactionLog, error) { + func(context.Context, protocol.StateManager, address.Address, *big.Int, *big.Int) (*action.TransactionLog, error) { return nil, nil }, + nil, ) if err != nil { return err diff --git a/action/protocol/poll/staking_committee.go b/action/protocol/poll/staking_committee.go index 44010ecc0f..d6d4d115dc 100644 --- a/action/protocol/poll/staking_committee.go +++ b/action/protocol/poll/staking_committee.go @@ -143,9 +143,10 @@ func (sc *stakingCommittee) CreateGenesisStates(ctx context.Context, sm protocol func(height uint64) (hash.Hash256, error) { return hash.ZeroHash256, nil }, - func(ctx context.Context, sm protocol.StateManager, amount *big.Int) (*action.TransactionLog, error) { + func(context.Context, protocol.StateManager, address.Address, *big.Int, *big.Int) (*action.TransactionLog, error) { return nil, nil }, + nil, ) if err != nil { return err diff --git a/action/protocol/rewarding/fund.go b/action/protocol/rewarding/fund.go index 1f942c934a..bb29fb81cb 100644 --- a/action/protocol/rewarding/fund.go +++ b/action/protocol/rewarding/fund.go @@ -63,6 +63,17 @@ func (p *Protocol) Deposit( sm protocol.StateManager, amount *big.Int, transactionLogType iotextypes.TransactionLogType, +) (*action.TransactionLog, error) { + // fallback to regular case by setting sgdAmount = nil + return p.deposit(ctx, sm, nil, amount, nil, transactionLogType) +} + +func (p *Protocol) deposit( + ctx context.Context, + sm protocol.StateManager, + receiver address.Address, + amount, sgdAmount *big.Int, + transactionLogType iotextypes.TransactionLogType, ) (*action.TransactionLog, error) { actionCtx := protocol.MustGetActionCtx(ctx) accountCreationOpts := []state.AccountCreationOption{} @@ -85,8 +96,18 @@ func (p *Protocol) Deposit( if _, err := p.state(ctx, sm, _fundKey, &f); err != nil { return nil, err } - f.totalBalance = big.NewInt(0).Add(f.totalBalance, amount) - f.unclaimedBalance = big.NewInt(0).Add(f.unclaimedBalance, amount) + f.totalBalance.Add(f.totalBalance, amount) + f.unclaimedBalance.Add(f.unclaimedBalance, amount) + if !isZero(sgdAmount) { + f.unclaimedBalance.Sub(f.unclaimedBalance, sgdAmount) + if f.unclaimedBalance.Sign() == -1 { + return nil, errors.New("no enough available balance") + } + // grant sgd amount to receiver + if err := p.grantToAccount(ctx, sm, receiver, sgdAmount); err != nil { + return nil, err + } + } if err := p.putState(ctx, sm, _fundKey, &f); err != nil { return nil, err } @@ -146,3 +167,35 @@ func DepositGas(ctx context.Context, sm protocol.StateManager, amount *big.Int) } return rp.Deposit(ctx, sm, amount, iotextypes.TransactionLogType_GAS_FEE) } + +// DepositGasWithSGD deposits gas into the rewarding fund with Sharing of Gas-fee with DApps +func DepositGasWithSGD(ctx context.Context, sm protocol.StateManager, sgdReceiver address.Address, totalAmount, sgdAmount *big.Int, +) (*action.TransactionLog, error) { + if isZero(sgdAmount) { + // fallback to regular case if SGD amount is zero + return DepositGas(ctx, sm, totalAmount) + } + if sgdReceiver == nil { + // a valid SGD amount but no valid receiver address + return nil, errors.New("no valid receiver address to receive the Sharing of Gas-fee with DApps") + } + // TODO: we bypass the gas deposit for the actions in genesis block. Later we should remove this after we remove + // genesis actions + blkCtx := protocol.MustGetBlockCtx(ctx) + if blkCtx.BlockHeight == 0 { + return nil, nil + } + reg, ok := protocol.GetRegistry(ctx) + if !ok { + return nil, nil + } + rp := FindProtocol(reg) + if rp == nil { + return nil, nil + } + return rp.deposit(ctx, sm, sgdReceiver, totalAmount, sgdAmount, iotextypes.TransactionLogType_GAS_FEE) +} + +func isZero(a *big.Int) bool { + return a == nil || len(a.Bytes()) == 0 +} diff --git a/action/protocol/rewarding/protocol_test.go b/action/protocol/rewarding/protocol_test.go index a60f626d5f..18aeb7c108 100644 --- a/action/protocol/rewarding/protocol_test.go +++ b/action/protocol/rewarding/protocol_test.go @@ -570,7 +570,14 @@ func TestStateCheckLegacy(t *testing.T) { require.Equal(tests[useV2].before.Add(tests[useV2].before, tests[useV2].add), acc.balance) } if i == 0 { + // grant to existing addr require.NoError(p.grantToAccount(ctx, sm, addr, tests[useV2].add)) + // grant to new addr + newAddr := identityset.Address(4 + useV2) + require.NoError(p.grantToAccount(ctx, sm, newAddr, tests[useV2].add)) + _, err = p.state(ctx, sm, append(_adminKey, newAddr.Bytes()...), &acc) + require.NoError(err) + require.Equal(acc.balance, tests[useV2].add) } } diff --git a/api/serverV2_integrity_test.go b/api/serverV2_integrity_test.go index 007770fedb..ecb34ac756 100644 --- a/api/serverV2_integrity_test.go +++ b/api/serverV2_integrity_test.go @@ -336,7 +336,7 @@ func setupChain(cfg testConfig) (blockchain.Blockchain, blockdao.BlockDAO, block }() acc := account.NewProtocol(rewarding.DepositGas) - evm := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGas) + evm := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil) p := poll.NewLifeLongDelegatesProtocol(cfg.genesis.Delegates) rolldposProtocol := rolldpos.NewProtocol( genesis.Default.NumCandidateDelegates, diff --git a/blockchain/integrity/benchmark_test.go b/blockchain/integrity/benchmark_test.go index 6bc972d072..a60fd41ad0 100644 --- a/blockchain/integrity/benchmark_test.go +++ b/blockchain/integrity/benchmark_test.go @@ -277,7 +277,7 @@ func newChainInDB() (blockchain.Blockchain, actpool.ActPool, error) { if bc == nil { return nil, nil, errors.New("pointer is nil") } - ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGas) + ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil) if err = ep.Register(registry); err != nil { return nil, nil, err } diff --git a/blockchain/integrity/integrity_test.go b/blockchain/integrity/integrity_test.go index 77ce5a42a1..dfb00c96e8 100644 --- a/blockchain/integrity/integrity_test.go +++ b/blockchain/integrity/integrity_test.go @@ -494,7 +494,7 @@ func TestCreateBlockchain(t *testing.T) { protocol.NewGenericValidator(sf, accountutil.AccountState), )), ) - ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGas) + ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil) require.NoError(ep.Register(registry)) rewardingProtocol := rewarding.NewProtocol(cfg.Genesis.Rewarding) require.NoError(rewardingProtocol.Register(registry)) @@ -547,7 +547,7 @@ func TestGetBlockHash(t *testing.T) { protocol.NewGenericValidator(sf, accountutil.AccountState), )), ) - ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGas) + ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil) require.NoError(ep.Register(registry)) rewardingProtocol := rewarding.NewProtocol(cfg.Genesis.Rewarding) require.NoError(rewardingProtocol.Register(registry)) @@ -710,7 +710,7 @@ func TestBlockchain_MintNewBlock(t *testing.T) { protocol.NewGenericValidator(sf, accountutil.AccountState), )), ) - ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGas) + ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil) require.NoError(t, ep.Register(registry)) rewardingProtocol := rewarding.NewProtocol(cfg.Genesis.Rewarding) require.NoError(t, rewardingProtocol.Register(registry)) @@ -786,7 +786,7 @@ func TestBlockchain_MintNewBlock_PopAccount(t *testing.T) { ) rp := rolldpos.NewProtocol(cfg.Genesis.NumCandidateDelegates, cfg.Genesis.NumDelegates, cfg.Genesis.NumSubEpochs) require.NoError(t, rp.Register(registry)) - ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGas) + ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil) require.NoError(t, ep.Register(registry)) rewardingProtocol := rewarding.NewProtocol(cfg.Genesis.Rewarding) require.NoError(t, rewardingProtocol.Register(registry)) @@ -885,7 +885,7 @@ func TestConstantinople(t *testing.T) { protocol.NewGenericValidator(sf, accountutil.AccountState), )), ) - ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGas) + ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil) require.NoError(ep.Register(registry)) rewardingProtocol := rewarding.NewProtocol(cfg.Genesis.Rewarding) require.NoError(rewardingProtocol.Register(registry)) @@ -1135,7 +1135,7 @@ func TestLoadBlockchainfromDB(t *testing.T) { protocol.NewGenericValidator(sf, accountutil.AccountState), )), ) - ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGas) + ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil) require.NoError(ep.Register(registry)) require.NoError(bc.Start(ctx)) @@ -1989,7 +1989,7 @@ func newChain(t *testing.T, stateTX bool) (blockchain.Blockchain, factory.Factor )), ) require.NotNil(bc) - ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGas) + ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil) require.NoError(ep.Register(registry)) require.NoError(bc.Start(context.Background())) diff --git a/blockindex/sgd_indexer.go b/blockindex/sgd_indexer.go new file mode 100644 index 0000000000..5d5e2532bb --- /dev/null +++ b/blockindex/sgd_indexer.go @@ -0,0 +1,56 @@ +// Copyright (c) 2023 IoTeX Foundation +// This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability +// or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. +// This source code is governed by Apache License 2.0 that can be found in the LICENSE file. + +package blockindex + +import ( + "context" + + "github.com/iotexproject/iotex-address/address" + + "github.com/iotexproject/iotex-core/blockchain/block" + "github.com/iotexproject/iotex-core/blockchain/blockdao" +) + +type ( + // SGDRegistry is the interface for Sharing of Gas-fee with DApps + SGDRegistry interface { + blockdao.BlockIndexer + // CheckContract returns the contract's eligibility for SGD and percentage + CheckContract(context.Context, string) (address.Address, uint64, bool, error) + } + + sgdRegistry struct { + } +) + +// NewSGDRegistry creates a new SGDIndexer +func NewSGDRegistry() SGDRegistry { + return &sgdRegistry{} +} + +func (sgd *sgdRegistry) Start(ctx context.Context) error { + return nil +} + +func (sgd *sgdRegistry) Stop(ctx context.Context) error { + return nil +} + +func (sgd *sgdRegistry) Height() (uint64, error) { + return 0, nil +} + +func (sgd *sgdRegistry) PutBlock(ctx context.Context, blk *block.Block) error { + return nil +} + +func (sgd *sgdRegistry) DeleteTipBlock(context.Context, *block.Block) error { + return nil +} + +func (sgd *sgdRegistry) CheckContract(ctx context.Context, contract string) (address.Address, uint64, bool, error) { + return nil, 0, false, nil +} diff --git a/chainservice/builder.go b/chainservice/builder.go index e68c542003..228e920df9 100644 --- a/chainservice/builder.go +++ b/chainservice/builder.go @@ -254,6 +254,9 @@ func (builder *Builder) buildBlockDAO(forTest bool) error { if builder.cs.bfIndexer != nil { indexers = append(indexers, builder.cs.bfIndexer) } + if builder.cs.sgdIndexer != nil { + indexers = append(indexers, builder.cs.sgdIndexer) + } if forTest { builder.cs.blockdao = blockdao.NewBlockDAOInMemForTest(indexers) } else { @@ -266,6 +269,18 @@ func (builder *Builder) buildBlockDAO(forTest bool) error { return nil } +func (builder *Builder) buildSGDRegistry(forTest bool) error { + if builder.cs.sgdIndexer != nil { + return nil + } + if forTest { + builder.cs.sgdIndexer = nil + } else { + builder.cs.sgdIndexer = blockindex.NewSGDRegistry() + } + return nil +} + func (builder *Builder) buildGatewayComponents(forTest bool) error { indexer, bfIndexer, candidateIndexer, candBucketsIndexer, err := builder.createGateWayComponents(forTest) if err != nil { @@ -506,7 +521,7 @@ func (builder *Builder) registerAccountProtocol() error { } func (builder *Builder) registerExecutionProtocol() error { - return execution.NewProtocol(builder.cs.blockdao.GetBlockHash, rewarding.DepositGas).Register(builder.cs.registry) + return execution.NewProtocol(builder.cs.blockdao.GetBlockHash, rewarding.DepositGasWithSGD, builder.cs.sgdIndexer).Register(builder.cs.registry) } func (builder *Builder) registerRollDPoSProtocol() error { @@ -566,7 +581,7 @@ func (builder *Builder) registerRollDPoSProtocol() error { func(start, end uint64) (map[string]uint64, error) { return blockchain.Productivity(chain, start, end) }, - builder.cs.blockdao.GetBlockHash, + dao.GetBlockHash, ) if err != nil { return errors.Wrap(err, "failed to generate poll protocol") @@ -625,6 +640,9 @@ func (builder *Builder) build(forSubChain, forTest bool) (*ChainService, error) if err := builder.buildGatewayComponents(forTest); err != nil { return nil, err } + if err := builder.buildSGDRegistry(forTest); err != nil { + return nil, err + } if err := builder.buildBlockDAO(forTest); err != nil { return nil, err } diff --git a/chainservice/chainservice.go b/chainservice/chainservice.go index fc41d3339d..9632d869ba 100644 --- a/chainservice/chainservice.go +++ b/chainservice/chainservice.go @@ -84,6 +84,7 @@ type ChainService struct { bfIndexer blockindex.BloomFilterIndexer candidateIndexer *poll.CandidateIndexer candBucketsIndexer *staking.CandidatesBucketsIndexer + sgdIndexer blockindex.SGDRegistry registry *protocol.Registry nodeInfoManager *nodeinfo.InfoManager } diff --git a/e2etest/bigint_test.go b/e2etest/bigint_test.go index 0fc0a5130a..ead36d90a4 100644 --- a/e2etest/bigint_test.go +++ b/e2etest/bigint_test.go @@ -110,7 +110,7 @@ func prepareBlockchain(ctx context.Context, _executor string, r *require.Asserti reward := rewarding.NewProtocol(cfg.Genesis.Rewarding) r.NoError(reward.Register(registry)) - ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGas) + ep := execution.NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil) r.NoError(ep.Register(registry)) r.NoError(bc.Start(ctx)) ctx = genesis.WithGenesisContext(ctx, cfg.Genesis) diff --git a/gasstation/gasstattion_test.go b/gasstation/gasstattion_test.go index e3b63ad401..e89bc99194 100644 --- a/gasstation/gasstattion_test.go +++ b/gasstation/gasstattion_test.go @@ -81,7 +81,7 @@ func TestSuggestGasPriceForUserAction(t *testing.T) { protocol.NewGenericValidator(sf, accountutil.AccountState), )), ) - ep := execution.NewProtocol(blkMemDao.GetBlockHash, rewarding.DepositGas) + ep := execution.NewProtocol(blkMemDao.GetBlockHash, rewarding.DepositGasWithSGD, nil) require.NoError(t, ep.Register(registry)) rewardingProtocol := rewarding.NewProtocol(cfg.Genesis.Rewarding) require.NoError(t, rewardingProtocol.Register(registry)) @@ -157,7 +157,7 @@ func TestSuggestGasPriceForSystemAction(t *testing.T) { protocol.NewGenericValidator(sf, accountutil.AccountState), )), ) - ep := execution.NewProtocol(blkMemDao.GetBlockHash, rewarding.DepositGas) + ep := execution.NewProtocol(blkMemDao.GetBlockHash, rewarding.DepositGasWithSGD, nil) require.NoError(t, ep.Register(registry)) rewardingProtocol := rewarding.NewProtocol(cfg.Genesis.Rewarding) require.NoError(t, rewardingProtocol.Register(registry))