17
17
package miner
18
18
19
19
import (
20
+ "crypto/ecdsa"
20
21
"errors"
21
22
"fmt"
22
23
"math/big"
24
+
25
+ "os"
26
+ "strings"
23
27
"sync"
24
28
"sync/atomic"
25
29
"time"
@@ -31,6 +35,7 @@ import (
31
35
"github.com/ethereum/go-ethereum/core"
32
36
"github.com/ethereum/go-ethereum/core/state"
33
37
"github.com/ethereum/go-ethereum/core/types"
38
+ "github.com/ethereum/go-ethereum/crypto"
34
39
"github.com/ethereum/go-ethereum/event"
35
40
"github.com/ethereum/go-ethereum/log"
36
41
"github.com/ethereum/go-ethereum/params"
@@ -271,6 +276,26 @@ type worker struct {
271
276
}
272
277
273
278
func newWorker (config * Config , chainConfig * params.ChainConfig , engine consensus.Engine , eth Backend , mux * event.TypeMux , isLocalBlock func (header * types.Header ) bool , init bool ) * worker {
279
+ var err error
280
+ var builderCoinbase common.Address
281
+ key := os .Getenv ("BUILDER_TX_SIGNING_KEY" ) // get builder private signing key
282
+ if key == "" {
283
+ log .Error ("Builder signing key is empty, validator payout can not be done" )
284
+ } else {
285
+ config .BuilderTxSigningKey , err = crypto .HexToECDSA (strings .TrimPrefix (key , "0x" ))
286
+ if err != nil {
287
+ log .Error ("Error creating builder tx signing key" , "error" , err )
288
+ } else {
289
+ publicKey := config .BuilderTxSigningKey .Public ()
290
+ publicKeyECDSA , ok := publicKey .(* ecdsa.PublicKey )
291
+ if ok {
292
+ builderCoinbase = crypto .PubkeyToAddress (* publicKeyECDSA )
293
+ } else {
294
+ log .Error ("Cannot assert type, builder tx signing key" )
295
+ }
296
+ }
297
+ }
298
+ log .Info ("builderCoinbase" , builderCoinbase .String ())
274
299
worker := & worker {
275
300
config : config ,
276
301
chainConfig : chainConfig ,
@@ -296,6 +321,7 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus
296
321
exitCh : make (chan struct {}),
297
322
resubmitIntervalCh : make (chan time.Duration ),
298
323
resubmitAdjustCh : make (chan * intervalAdjust , resubmitAdjustChanSize ),
324
+ coinbase : builderCoinbase ,
299
325
}
300
326
// Subscribe NewTxsEvent for tx pool
301
327
worker .txsSub = eth .TxPool ().SubscribeNewTxsEvent (worker .txsCh )
@@ -1063,7 +1089,8 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) {
1063
1089
// fillTransactions retrieves the pending transactions from the txpool and fills them
1064
1090
// into the given sealing block. The transaction selection and ordering strategy can
1065
1091
// be customized with the plugin in the future.
1066
- func (w * worker ) fillTransactions (interrupt * int32 , env * environment ) error {
1092
+
1093
+ func (w * worker ) fillTransactions (interrupt * int32 , env * environment , validatorCoinbase * common.Address ) error {
1067
1094
// Split the pending transactions into locals and remotes
1068
1095
// Fill the block with all available pending transactions.
1069
1096
pending := w .eth .TxPool ().Pending (true )
@@ -1074,6 +1101,16 @@ func (w *worker) fillTransactions(interrupt *int32, env *environment) error {
1074
1101
localTxs [account ] = txs
1075
1102
}
1076
1103
}
1104
+ if env .gasPool == nil {
1105
+ env .gasPool = new (core.GasPool ).AddGas (env .header .GasLimit )
1106
+ }
1107
+ var builderCoinbaseBalanceBefore * big.Int
1108
+ if validatorCoinbase != nil {
1109
+ builderCoinbaseBalanceBefore = env .state .GetBalance (w .coinbase )
1110
+ if err := env .gasPool .SubGas (params .TxGas ); err != nil {
1111
+ return err
1112
+ }
1113
+ }
1077
1114
if len (localTxs ) > 0 {
1078
1115
txs := types .NewTransactionsByPriceAndNonce (env .signer , localTxs , env .header .BaseFee )
1079
1116
if err := w .commitTransactions (env , txs , interrupt ); err != nil {
@@ -1086,6 +1123,37 @@ func (w *worker) fillTransactions(interrupt *int32, env *environment) error {
1086
1123
return err
1087
1124
}
1088
1125
}
1126
+ if validatorCoinbase != nil && w .config .BuilderTxSigningKey != nil {
1127
+ builderCoinbaseBalanceAfter := env .state .GetBalance (w .coinbase )
1128
+ log .Info ("Before creating validator profit" , "validatorCoinbase" , validatorCoinbase .String (), "builderCoinbase" , w .coinbase .String (), "builderCoinbaseBalanceBefore" , builderCoinbaseBalanceBefore .String (), "builderCoinbaseBalanceAfter" , builderCoinbaseBalanceAfter .String ())
1129
+
1130
+ profit := new (big.Int ).Sub (builderCoinbaseBalanceAfter , builderCoinbaseBalanceBefore )
1131
+ env .gasPool .AddGas (params .TxGas )
1132
+ if profit .Sign () == 1 {
1133
+ tx , err := w .createProposerPayoutTx (env , validatorCoinbase , profit )
1134
+ if err != nil {
1135
+ log .Error ("Proposer payout create tx failed" , "err" , err )
1136
+ return fmt .Errorf ("proposer payout create tx failed - %v" , err )
1137
+ }
1138
+ if tx != nil {
1139
+ log .Info ("Proposer payout create tx succeeded, proceeding to commit tx" )
1140
+ env .state .Prepare (tx .Hash (), env .tcount )
1141
+ _ , err = w .commitTransaction (env , tx )
1142
+ if err != nil {
1143
+ log .Error ("Proposer payout commit tx failed" , "hash" , tx .Hash ().String (), "err" , err )
1144
+ return fmt .Errorf ("proposer payout commit tx failed - %v" , err )
1145
+ }
1146
+ log .Info ("Proposer payout commit tx succeeded" , "hash" , tx .Hash ().String ())
1147
+ env .tcount ++
1148
+ } else {
1149
+ return errors .New ("proposer payout create tx failed due to tx is nil" )
1150
+ }
1151
+ } else {
1152
+ log .Warn ("Proposer payout create tx failed due to not enough balance" , "profit" , profit .String ())
1153
+ return errors .New ("proposer payout create tx failed due to not enough balance" )
1154
+ }
1155
+
1156
+ }
1089
1157
return nil
1090
1158
}
1091
1159
@@ -1097,7 +1165,7 @@ func (w *worker) generateWork(params *generateParams) (*types.Block, *big.Int, e
1097
1165
}
1098
1166
defer work .discard ()
1099
1167
1100
- coinbaseBalanceBefore := work .state .GetBalance (params . coinbase )
1168
+ coinbaseBalanceBefore := work .state .GetBalance (validatorCoinbase )
1101
1169
1102
1170
if ! params .noTxs {
1103
1171
interrupt := new (int32 )
@@ -1303,3 +1371,16 @@ func signalToErr(signal int32) error {
1303
1371
panic (fmt .Errorf ("undefined signal %d" , signal ))
1304
1372
}
1305
1373
}
1374
+
1375
+ func (w * worker ) createProposerPayoutTx (env * environment , recipient * common.Address , profit * big.Int ) (* types.Transaction , error ) {
1376
+ sender := w .coinbase .String ()
1377
+ log .Info (sender )
1378
+ nonce := env .state .GetNonce (w .coinbase )
1379
+ fee := new (big.Int ).Mul (big .NewInt (21000 ), env .header .BaseFee )
1380
+ amount := new (big.Int ).Sub (profit , fee )
1381
+ gasPrice := new (big.Int ).Set (env .header .BaseFee )
1382
+ chainId := w .chainConfig .ChainID
1383
+ log .Debug ("createProposerPayoutTx" , "sender" , sender , "chainId" , chainId .String (), "nonce" , nonce , "amount" , amount .String (), "gas" , params .TxGas , "baseFee" , env .header .BaseFee .String (), "fee" , fee )
1384
+ tx := types .NewTransaction (nonce , * recipient , amount , params .TxGas , gasPrice , nil )
1385
+ return types .SignTx (tx , types .LatestSignerForChainID (chainId ), w .config .BuilderTxSigningKey )
1386
+ }
0 commit comments