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