gitlab.com/aquachain/aquachain@v1.17.16-rc3.0.20221018032414-e3ddf1e1c055/cmd/aquastrat/main.go (about) 1 // Copyright 2018 The aquachain Authors 2 // This file is part of aquachain. 3 // 4 // aquachain is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // aquachain is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with aquachain. If not, see <http://www.gnu.org/licenses/>. 16 17 package main 18 19 import ( 20 "context" 21 "fmt" 22 "math/big" 23 "math/rand" 24 "os" 25 "path/filepath" 26 "strings" 27 "time" 28 29 cli "github.com/urfave/cli" 30 "gitlab.com/aquachain/aquachain/cmd/utils" 31 "gitlab.com/aquachain/aquachain/common" 32 "gitlab.com/aquachain/aquachain/consensus/aquahash" 33 "gitlab.com/aquachain/aquachain/consensus/lightvalid" 34 "gitlab.com/aquachain/aquachain/core/types" 35 "gitlab.com/aquachain/aquachain/internal/debug" 36 "gitlab.com/aquachain/aquachain/opt/aquaclient" 37 "gitlab.com/aquachain/aquachain/params" 38 "gitlab.com/aquachain/aquachain/rlp" 39 rpc "gitlab.com/aquachain/aquachain/rpc/rpcclient" 40 ) 41 42 var gitCommit = "" 43 44 var ( 45 app = utils.NewApp(gitCommit, "usage") 46 big1 = big.NewInt(1) 47 Config *params.ChainConfig 48 ) 49 50 func init() { 51 app.Name = "aquastrat" 52 app.Action = loopit 53 _ = filepath.Join 54 app.Flags = append(debug.Flags, []cli.Flag{ 55 cli.StringFlag{ 56 //Value: filepath.Join(utils.DataDirFlag.Value.String(), "testnet/aquachain.ipc"), 57 Value: "https://tx.aquacha.in/testnet/", 58 Name: "rpc", 59 Usage: "path or url to rpc", 60 }, 61 cli.StringFlag{ 62 Value: "", 63 Name: "coinbase", 64 Usage: "address for mining rewards", 65 }, 66 }...) 67 } 68 69 //valid block #1 using -testnet2 70 var header1 = &types.Header{ 71 Difficulty: big.NewInt(4096), 72 Extra: []byte{0xd4, 0x83, 0x01, 0x07, 0x04, 0x89, 0x61, 0x71, 0x75, 0x61, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x85, 0x6c, 0x69, 0x6e, 0x75, 0x78}, 73 GasLimit: 4704588, 74 GasUsed: 0, 75 // Hash: "0x73851a4d607acd8341cf415beeed9c8b8c803e1e835cb45080f6af7a2127e807", 76 Coinbase: common.HexToAddress("0xcf8e5ba37426404bef34c3ca4fa2d2ed9be41e58"), 77 MixDigest: common.Hash{}, 78 Nonce: types.BlockNonce{0x70, 0xc2, 0xdd, 0x45, 0xa3, 0x10, 0x17, 0x35}, 79 Number: big.NewInt(1), 80 ParentHash: common.HexToHash("0xde434983d3ada19cd43c44d8ad5511bad01ed12b3cc9a99b1717449a245120df"), 81 ReceiptHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), 82 UncleHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"), 83 Root: common.HexToHash("0x194b1927f77b77161b58fed1184990d8f7b345fabf8ef8706ee865a844f73bc3"), 84 Time: big.NewInt(1536181711), 85 TxHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), 86 Version: 2, 87 } 88 89 func main() { 90 if err := app.Run(os.Args); err != nil { 91 fmt.Println("fatal:", err) 92 } 93 } 94 95 func loopit(ctx *cli.Context) error { 96 for { 97 if err := runit(ctx); err != nil { 98 fmt.Println(err) 99 return err 100 } 101 } 102 } 103 func runit(ctx *cli.Context) error { 104 coinbase := ctx.String("coinbase") 105 if coinbase == "" || !strings.HasPrefix(coinbase, "0x") || len(coinbase) != 42 { 106 return fmt.Errorf("cant mine with no -coinbase flag, or invalid: len: %v, coinbase: %q", len(coinbase), coinbase) 107 } 108 coinbaseAddr := common.HexToAddress(coinbase) 109 110 rpcclient, err := getclient(ctx) 111 if err != nil { 112 return err 113 } 114 aqua := aquaclient.NewClient(rpcclient) 115 block1, err := aqua.BlockByNumber(context.Background(), big1) 116 if err != nil { 117 fmt.Println("blockbynumber") 118 return err 119 } 120 121 // to get genesis hash, we can't grab block zero and Hash() 122 // because we dont know the chainconfig which tells us 123 // the version to use for hashing. 124 genesisHash := block1.ParentHash() 125 switch genesisHash { 126 case params.MainnetGenesisHash: 127 Config = params.MainnetChainConfig 128 case params.TestnetGenesisHash: 129 Config = params.TestnetChainConfig 130 default: 131 Config = params.Testnet2ChainConfig 132 } 133 parent, err := aqua.BlockByNumber(context.Background(), nil) 134 if err != nil { 135 fmt.Println("blockbynumber") 136 return err 137 } 138 var encoded []byte 139 // first block is on the house (testnet2 only) 140 if Config == params.Testnet2ChainConfig && parent.Number().Uint64() == 0 { 141 parent.SetVersion(Config.GetBlockVersion(parent.Number())) 142 block1 := types.NewBlock(header1, nil, nil, nil) 143 encoded, err = rlp.EncodeToBytes(&block1) 144 if err != nil { 145 return err 146 } 147 } 148 encoded, err = aqua.GetBlockTemplate(context.Background(), coinbaseAddr) 149 if err != nil { 150 println("gbt") 151 return err 152 } 153 var bt = new(types.Block) 154 if err := rlp.DecodeBytes(encoded, bt); err != nil { 155 println("getblocktemplate rlp decode error", err.Error()) 156 return err 157 } 158 159 // modify block 160 bt.SetVersion(Config.GetBlockVersion(bt.Number())) 161 fmt.Println("mining:") 162 fmt.Println(bt) 163 encoded, err = mine(Config, parent.Header(), bt) 164 if err != nil { 165 return err 166 } 167 if encoded == nil { 168 return fmt.Errorf("failed to encoded block to rlp") 169 } 170 if !aqua.SubmitBlock(context.Background(), encoded) { 171 fmt.Println("failed") 172 return fmt.Errorf("failed") 173 } else { 174 fmt.Println("success") 175 } 176 return nil 177 178 } 179 180 func mine(cfg *params.ChainConfig, parent *types.Header, block *types.Block) ([]byte, error) { 181 validator := lightvalid.New() 182 rand.Seed(time.Now().UnixNano()) 183 nonce := uint64(0) 184 nonce = rand.Uint64() 185 hdr := block.Header() 186 fmt.Println("mining algo:", hdr.Version) 187 fmt.Printf("#%v, by %x\ndiff: %s\ntx: %s\n", hdr.Number, hdr.Coinbase, hdr.Difficulty, block.Transactions()) 188 fmt.Printf("starting from nonce: %v\n", nonce) 189 second := time.Tick(10 * time.Second) 190 fps := uint64(0) 191 for { 192 select { 193 case <-second: 194 // not necessary, but impossible with getwork() 195 hdr.Time = big.NewInt(time.Now().Unix()) 196 hdr.Difficulty = aquahash.CalcDifficulty(cfg, hdr.Time.Uint64(), parent, nil) 197 fmt.Printf("%s %v h/s\n", hdr.Time, fps/uint64(10)) 198 fps = 0 199 default: 200 nonce++ 201 fps++ 202 hdr.Nonce = types.EncodeNonce(nonce) 203 block = block.WithSeal(hdr) 204 block = types.NewBlock(hdr, block.Transactions(), block.Uncles(), []*types.Receipt{}) 205 if err := validator.VerifyWithError(block); err != nil { 206 if err != lightvalid.ErrPOW { 207 fmt.Println("error:", err) 208 } 209 continue 210 } 211 println("found nonce, encoding block", block.String()) 212 b, err := rlp.EncodeToBytes(&block) 213 if err != nil { 214 return nil, err 215 } 216 fmt.Println(b) 217 return b, nil 218 } 219 } 220 } 221 222 func getclient(ctx *cli.Context) (*rpc.Client, error) { 223 if strings.HasPrefix(ctx.String("rpc"), "http") { 224 return rpc.DialHTTP(ctx.String("rpc")) 225 } else { 226 return rpc.DialIPC(context.Background(), ctx.String("rpc")) 227 } 228 }