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  }