github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/scripts/gendump/main.go (about) 1 package main 2 3 import ( 4 "crypto/rand" 5 "errors" 6 "flag" 7 "fmt" 8 "os" 9 "strings" 10 "time" 11 12 "github.com/nspcc-dev/neo-go/internal/testchain" 13 "github.com/nspcc-dev/neo-go/pkg/config" 14 "github.com/nspcc-dev/neo-go/pkg/config/netmode" 15 "github.com/nspcc-dev/neo-go/pkg/core" 16 "github.com/nspcc-dev/neo-go/pkg/core/block" 17 "github.com/nspcc-dev/neo-go/pkg/core/chaindump" 18 "github.com/nspcc-dev/neo-go/pkg/core/native" 19 "github.com/nspcc-dev/neo-go/pkg/core/storage" 20 "github.com/nspcc-dev/neo-go/pkg/core/transaction" 21 "github.com/nspcc-dev/neo-go/pkg/io" 22 "github.com/nspcc-dev/neo-go/pkg/smartcontract" 23 "github.com/nspcc-dev/neo-go/pkg/wallet" 24 "go.uber.org/zap" 25 "go.uber.org/zap/zapcore" 26 ) 27 28 // Takes 1 minute for 100 tx per block and 5000 blocks. 29 const ( 30 defaultBlockCount = 5000 31 defaultTxPerBlock = 100 32 ) 33 34 var ( 35 outFile = flag.String("out", "", "filename to write dump to") 36 blockCount = flag.Uint("blocks", defaultBlockCount, "number of blocks to generate") 37 txPerBlock = flag.Uint("txs", defaultTxPerBlock, "number of blocks to generate") 38 ) 39 40 func main() { 41 flag.Parse() 42 43 if *outFile == "" { 44 handleError("", errors.New("output file is not provided")) 45 } 46 outStream, err := os.Create(*outFile) // fail early 47 handleError("can't open output file", err) 48 defer outStream.Close() 49 50 const contract = ` 51 package contract 52 import "github.com/nspcc-dev/neo-go/pkg/interop/storage" 53 var ctx = storage.GetContext() 54 func Put(key, value []byte) { 55 storage.Put(ctx, key, value) 56 }` 57 58 acc, err := wallet.NewAccount() 59 handleError("can't create new account", err) 60 h := acc.Contract.ScriptHash() 61 62 bc, err := newChain() 63 handleError("can't initialize blockchain", err) 64 65 nbVals, err := bc.GetNextBlockValidators() 66 handleError("can't get next block validators", err) 67 valScript, err := smartcontract.CreateDefaultMultiSigRedeemScript(nbVals) 68 handleError("can't create verification script", err) 69 lastBlock, err := bc.GetBlock(bc.GetHeaderHash(bc.BlockHeight())) 70 handleError("can't fetch last block", err) 71 72 txMoveNeo, err := testchain.NewTransferFromOwner(bc, bc.GoverningTokenHash(), h, native.NEOTotalSupply, 0, 2) 73 handleError("can't transfer NEO", err) 74 txMoveGas, err := testchain.NewTransferFromOwner(bc, bc.UtilityTokenHash(), h, 2_000_000_000_000_000, 0, 2) 75 handleError("can't tranfser GAS", err) 76 lastBlock = addBlock(bc, lastBlock, valScript, txMoveNeo, txMoveGas) 77 78 tx, contractHash, _, err := testchain.NewDeployTx(bc, "DumpContract.go", h, strings.NewReader(contract), nil) 79 handleError("can't create deploy tx", err) 80 tx.NetworkFee = 10_000_000 81 tx.ValidUntilBlock = bc.BlockHeight() + 1 82 handleError("can't sign deploy tx", acc.SignTx(netmode.UnitTestNet, tx)) 83 lastBlock = addBlock(bc, lastBlock, valScript, tx) 84 85 key := make([]byte, 10) 86 value := make([]byte, 10) 87 nonce := uint32(0) 88 89 blocksNum := uint32(*blockCount) 90 txNum := int(*txPerBlock) 91 for i := bc.BlockHeight(); i < blocksNum; i++ { 92 txs := make([]*transaction.Transaction, txNum) 93 for j := 0; j < txNum; j++ { 94 nonce++ 95 _, err = rand.Read(key) 96 handleError("can't get random data for key", err) 97 _, err = rand.Read(value) 98 handleError("can't get random data for value", err) 99 100 script, err := smartcontract.CreateCallScript(contractHash, "put", key, value) 101 handleError("can't create transaction", err) 102 103 tx := transaction.New(script, 4_040_000) 104 tx.ValidUntilBlock = i + 1 105 tx.NetworkFee = 4_000_000 106 tx.Nonce = nonce 107 tx.Signers = []transaction.Signer{{ 108 Account: h, 109 Scopes: transaction.CalledByEntry, 110 }} 111 handleError("can't sign tx", acc.SignTx(netmode.UnitTestNet, tx)) 112 113 txs[j] = tx 114 } 115 lastBlock = addBlock(bc, lastBlock, valScript, txs...) 116 } 117 118 w := io.NewBinWriterFromIO(outStream) 119 w.WriteU32LE(bc.BlockHeight() + 1) 120 handleError("error during dump", chaindump.Dump(bc, w, 0, bc.BlockHeight()+1)) 121 } 122 123 func handleError(msg string, err error) { 124 if err != nil { 125 fmt.Printf("%s: %v\n", msg, err) 126 os.Exit(1) 127 } 128 } 129 130 func newChain() (*core.Blockchain, error) { 131 unitTestNetCfg, err := config.Load("./config", netmode.UnitTestNet) 132 if err != nil { 133 return nil, err 134 } 135 unitTestNetCfg.ApplicationConfiguration.SkipBlockVerification = true 136 zapCfg := zap.NewDevelopmentConfig() 137 zapCfg.Level = zap.NewAtomicLevelAt(zapcore.InfoLevel) 138 log, err := zapCfg.Build() 139 if err != nil { 140 return nil, err 141 } 142 chain, err := core.NewBlockchain(storage.NewMemoryStore(), unitTestNetCfg.Blockchain(), log) 143 if err != nil { 144 return nil, err 145 } 146 go chain.Run() 147 return chain, nil 148 } 149 150 func addBlock(bc *core.Blockchain, lastBlock *block.Block, script []byte, txs ...*transaction.Transaction) *block.Block { 151 b, err := newBlock(bc, lastBlock, script, txs...) 152 if err != nil { 153 handleError("can't create block", err) 154 } 155 if err := bc.AddBlock(b); err != nil { 156 handleError("can't add block", err) 157 } 158 return b 159 } 160 161 func newBlock(bc *core.Blockchain, lastBlock *block.Block, script []byte, txs ...*transaction.Transaction) (*block.Block, error) { 162 witness := transaction.Witness{VerificationScript: script} 163 b := &block.Block{ 164 Header: block.Header{ 165 PrevHash: lastBlock.Hash(), 166 Timestamp: uint64(time.Now().UTC().Unix())*1000 + uint64(lastBlock.Index), 167 Index: lastBlock.Index + 1, 168 NextConsensus: witness.ScriptHash(), 169 Script: witness, 170 }, 171 Transactions: txs, 172 } 173 if bc.GetConfig().StateRootInHeader { 174 sr, err := bc.GetStateModule().GetStateRoot(bc.BlockHeight()) 175 if err != nil { 176 return nil, err 177 } 178 b.StateRootEnabled = true 179 b.PrevStateRoot = sr.Root 180 } 181 b.RebuildMerkleRoot() 182 b.Script.InvocationScript = testchain.Sign(b) 183 return b, nil 184 }