github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/core/util.go (about) 1 package core 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/nspcc-dev/neo-go/pkg/config" 8 "github.com/nspcc-dev/neo-go/pkg/core/block" 9 "github.com/nspcc-dev/neo-go/pkg/core/transaction" 10 "github.com/nspcc-dev/neo-go/pkg/crypto/hash" 11 "github.com/nspcc-dev/neo-go/pkg/crypto/keys" 12 "github.com/nspcc-dev/neo-go/pkg/smartcontract" 13 "github.com/nspcc-dev/neo-go/pkg/util" 14 "github.com/nspcc-dev/neo-go/pkg/vm/opcode" 15 ) 16 17 // CreateGenesisBlock creates a genesis block based on the given configuration. 18 func CreateGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) { 19 validators, committee, err := validatorsFromConfig(cfg) 20 if err != nil { 21 return nil, err 22 } 23 24 nextConsensus, err := getNextConsensusAddress(validators) 25 if err != nil { 26 return nil, err 27 } 28 29 txs := []*transaction.Transaction{} 30 if cfg.Genesis.Transaction != nil { 31 committeeH, err := getCommitteeAddress(committee) 32 if err != nil { 33 return nil, fmt.Errorf("failed to calculate committee address: %w", err) 34 } 35 tx := cfg.Genesis.Transaction 36 signers := []transaction.Signer{ 37 { 38 Account: nextConsensus, 39 Scopes: transaction.CalledByEntry, 40 }, 41 } 42 scripts := []transaction.Witness{ 43 { 44 InvocationScript: []byte{}, 45 VerificationScript: []byte{byte(opcode.PUSH1)}, 46 }, 47 } 48 if !committeeH.Equals(nextConsensus) { 49 signers = append(signers, []transaction.Signer{ 50 { 51 Account: committeeH, 52 Scopes: transaction.CalledByEntry, 53 }, 54 }...) 55 scripts = append(scripts, []transaction.Witness{ 56 { 57 InvocationScript: []byte{}, 58 VerificationScript: []byte{byte(opcode.PUSH1)}, 59 }, 60 }...) 61 } 62 63 txs = append(txs, &transaction.Transaction{ 64 SystemFee: tx.SystemFee, 65 ValidUntilBlock: 1, 66 Script: tx.Script, 67 Signers: signers, 68 Scripts: scripts, 69 }) 70 } 71 72 base := block.Header{ 73 Version: 0, 74 PrevHash: util.Uint256{}, 75 Timestamp: uint64(time.Date(2016, 7, 15, 15, 8, 21, 0, time.UTC).Unix()) * 1000, // Milliseconds. 76 Nonce: 2083236893, 77 Index: 0, 78 NextConsensus: nextConsensus, 79 Script: transaction.Witness{ 80 InvocationScript: []byte{}, 81 VerificationScript: []byte{byte(opcode.PUSH1)}, 82 }, 83 StateRootEnabled: cfg.StateRootInHeader, 84 } 85 86 b := &block.Block{ 87 Header: base, 88 Transactions: txs, 89 } 90 b.RebuildMerkleRoot() 91 92 return b, nil 93 } 94 95 func validatorsFromConfig(cfg config.ProtocolConfiguration) ([]*keys.PublicKey, []*keys.PublicKey, error) { 96 vs, err := keys.NewPublicKeysFromStrings(cfg.StandbyCommittee) 97 if err != nil { 98 return nil, nil, err 99 } 100 return vs.Copy()[:cfg.GetNumOfCNs(0)], vs, nil 101 } 102 103 func getNextConsensusAddress(validators []*keys.PublicKey) (val util.Uint160, err error) { 104 raw, err := smartcontract.CreateDefaultMultiSigRedeemScript(validators) 105 if err != nil { 106 return val, err 107 } 108 return hash.Hash160(raw), nil 109 } 110 111 func getCommitteeAddress(committee []*keys.PublicKey) (val util.Uint160, err error) { 112 raw, err := smartcontract.CreateMajorityMultiSigRedeemScript(committee) 113 if err != nil { 114 return val, err 115 } 116 return hash.Hash160(raw), nil 117 } 118 119 // hashSliceReverse reverses the given slice of util.Uint256. 120 func hashSliceReverse(dest []util.Uint256) { 121 for i, j := 0, len(dest)-1; i < j; i, j = i+1, j-1 { 122 dest[i], dest[j] = dest[j], dest[i] 123 } 124 }