neo-go/pkg/core/util.go
Anna Shaleva 8cc32a91b6 *: add GenesisTransaction extension to the protocol configuration
Provide a script that should be deployed in the genesis block.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2023-10-19 18:33:50 +03:00

124 lines
3.2 KiB
Go

package core
import (
"fmt"
"time"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
)
// CreateGenesisBlock creates a genesis block based on the given configuration.
func CreateGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) {
validators, committee, err := validatorsFromConfig(cfg)
if err != nil {
return nil, err
}
nextConsensus, err := getNextConsensusAddress(validators)
if err != nil {
return nil, err
}
txs := []*transaction.Transaction{}
if cfg.Genesis.Transaction != nil {
committeeH, err := getCommitteeAddress(committee)
if err != nil {
return nil, fmt.Errorf("failed to calculate committee address: %w", err)
}
tx := cfg.Genesis.Transaction
signers := []transaction.Signer{
{
Account: nextConsensus,
Scopes: transaction.CalledByEntry,
},
}
scripts := []transaction.Witness{
{
InvocationScript: []byte{},
VerificationScript: []byte{byte(opcode.PUSH1)},
},
}
if !committeeH.Equals(nextConsensus) {
signers = append(signers, []transaction.Signer{
{
Account: committeeH,
Scopes: transaction.CalledByEntry,
},
}...)
scripts = append(scripts, []transaction.Witness{
{
InvocationScript: []byte{},
VerificationScript: []byte{byte(opcode.PUSH1)},
},
}...)
}
txs = append(txs, &transaction.Transaction{
SystemFee: tx.SystemFee,
ValidUntilBlock: 1,
Script: tx.Script,
Signers: signers,
Scripts: scripts,
})
}
base := block.Header{
Version: 0,
PrevHash: util.Uint256{},
Timestamp: uint64(time.Date(2016, 7, 15, 15, 8, 21, 0, time.UTC).Unix()) * 1000, // Milliseconds.
Nonce: 2083236893,
Index: 0,
NextConsensus: nextConsensus,
Script: transaction.Witness{
InvocationScript: []byte{},
VerificationScript: []byte{byte(opcode.PUSH1)},
},
StateRootEnabled: cfg.StateRootInHeader,
}
b := &block.Block{
Header: base,
Transactions: txs,
}
b.RebuildMerkleRoot()
return b, nil
}
func validatorsFromConfig(cfg config.ProtocolConfiguration) ([]*keys.PublicKey, []*keys.PublicKey, error) {
vs, err := keys.NewPublicKeysFromStrings(cfg.StandbyCommittee)
if err != nil {
return nil, nil, err
}
return vs.Copy()[:cfg.GetNumOfCNs(0)], vs, nil
}
func getNextConsensusAddress(validators []*keys.PublicKey) (val util.Uint160, err error) {
raw, err := smartcontract.CreateDefaultMultiSigRedeemScript(validators)
if err != nil {
return val, err
}
return hash.Hash160(raw), nil
}
func getCommitteeAddress(committee []*keys.PublicKey) (val util.Uint160, err error) {
raw, err := smartcontract.CreateMajorityMultiSigRedeemScript(committee)
if err != nil {
return val, err
}
return hash.Hash160(raw), nil
}
// hashSliceReverse reverses the given slice of util.Uint256.
func hashSliceReverse(dest []util.Uint256) {
for i, j := 0, len(dest)-1; i < j; i, j = i+1, j-1 {
dest[i], dest[j] = dest[j], dest[i]
}
}