2018-03-09 15:55:25 +00:00
|
|
|
package core
|
|
|
|
|
2018-03-17 11:53:21 +00:00
|
|
|
import (
|
2018-03-25 10:45:54 +00:00
|
|
|
"time"
|
2018-03-17 11:53:21 +00:00
|
|
|
|
2018-03-25 10:45:54 +00:00
|
|
|
"github.com/CityOfZion/neo-go/config"
|
2020-01-14 12:32:07 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/core/block"
|
2018-03-21 16:11:04 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
2019-08-23 15:50:45 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
|
2019-08-27 13:29:42 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
2018-03-25 10:45:54 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
2018-03-17 11:53:21 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/util"
|
2019-12-03 14:05:06 +00:00
|
|
|
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
2018-03-17 11:53:21 +00:00
|
|
|
)
|
2018-03-09 15:55:25 +00:00
|
|
|
|
2019-10-22 14:56:03 +00:00
|
|
|
// createGenesisBlock creates a genesis block based on the given configuration.
|
2020-01-14 12:32:07 +00:00
|
|
|
func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) {
|
2018-03-25 10:45:54 +00:00
|
|
|
validators, err := getValidators(cfg)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
nextConsensus, err := getNextConsensusAddress(validators)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-01-14 12:32:07 +00:00
|
|
|
base := block.BlockBase{
|
2018-03-25 10:45:54 +00:00
|
|
|
Version: 0,
|
|
|
|
PrevHash: util.Uint256{},
|
|
|
|
Timestamp: uint32(time.Date(2016, 7, 15, 15, 8, 21, 0, time.UTC).Unix()),
|
|
|
|
Index: 0,
|
|
|
|
ConsensusData: 2083236893,
|
|
|
|
NextConsensus: nextConsensus,
|
2019-12-09 14:14:10 +00:00
|
|
|
Script: transaction.Witness{
|
2018-03-25 10:45:54 +00:00
|
|
|
InvocationScript: []byte{},
|
2019-12-03 14:05:06 +00:00
|
|
|
VerificationScript: []byte{byte(opcode.PUSHT)},
|
2018-03-25 10:45:54 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
governingTX := governingTokenTX()
|
|
|
|
utilityTX := utilityTokenTX()
|
|
|
|
rawScript, err := smartcontract.CreateMultiSigRedeemScript(
|
|
|
|
len(cfg.StandbyValidators)/2+1,
|
|
|
|
validators,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-08-23 15:50:45 +00:00
|
|
|
scriptOut := hash.Hash160(rawScript)
|
2018-03-25 10:45:54 +00:00
|
|
|
|
2020-01-14 12:32:07 +00:00
|
|
|
b := &block.Block{
|
2018-03-25 10:45:54 +00:00
|
|
|
BlockBase: base,
|
|
|
|
Transactions: []*transaction.Transaction{
|
|
|
|
{
|
|
|
|
Type: transaction.MinerType,
|
|
|
|
Data: &transaction.MinerTX{
|
|
|
|
Nonce: 2083236893,
|
|
|
|
},
|
2019-12-09 14:14:10 +00:00
|
|
|
Attributes: []transaction.Attribute{},
|
|
|
|
Inputs: []transaction.Input{},
|
|
|
|
Outputs: []transaction.Output{},
|
|
|
|
Scripts: []transaction.Witness{},
|
2018-03-25 10:45:54 +00:00
|
|
|
},
|
|
|
|
governingTX,
|
|
|
|
utilityTX,
|
|
|
|
{
|
|
|
|
Type: transaction.IssueType,
|
|
|
|
Data: &transaction.IssueTX{}, // no fields.
|
2019-12-09 14:14:10 +00:00
|
|
|
Inputs: []transaction.Input{},
|
|
|
|
Outputs: []transaction.Output{
|
2018-03-25 10:45:54 +00:00
|
|
|
{
|
|
|
|
AssetID: governingTX.Hash(),
|
|
|
|
Amount: governingTX.Data.(*transaction.RegisterTX).Amount,
|
|
|
|
ScriptHash: scriptOut,
|
|
|
|
},
|
|
|
|
},
|
2019-12-09 14:14:10 +00:00
|
|
|
Scripts: []transaction.Witness{
|
2018-03-25 10:45:54 +00:00
|
|
|
{
|
|
|
|
InvocationScript: []byte{},
|
2019-12-03 14:05:06 +00:00
|
|
|
VerificationScript: []byte{byte(opcode.PUSHT)},
|
2018-03-25 10:45:54 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2020-01-14 12:32:07 +00:00
|
|
|
if err = b.RebuildMerkleRoot(); err != nil {
|
2019-01-25 11:20:35 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
2018-03-25 10:45:54 +00:00
|
|
|
|
2020-01-14 12:32:07 +00:00
|
|
|
return b, nil
|
2018-03-25 10:45:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func governingTokenTX() *transaction.Transaction {
|
2019-12-03 14:05:06 +00:00
|
|
|
admin := hash.Hash160([]byte{byte(opcode.PUSHT)})
|
2018-03-25 10:45:54 +00:00
|
|
|
registerTX := &transaction.RegisterTX{
|
|
|
|
AssetType: transaction.GoverningToken,
|
|
|
|
Name: "[{\"lang\":\"zh-CN\",\"name\":\"小蚁股\"},{\"lang\":\"en\",\"name\":\"AntShare\"}]",
|
2019-08-23 12:41:22 +00:00
|
|
|
Amount: util.Fixed8FromInt64(100000000),
|
2018-03-25 10:45:54 +00:00
|
|
|
Precision: 0,
|
|
|
|
Admin: admin,
|
|
|
|
}
|
|
|
|
|
|
|
|
tx := &transaction.Transaction{
|
|
|
|
Type: transaction.RegisterType,
|
|
|
|
Data: registerTX,
|
2019-12-09 14:14:10 +00:00
|
|
|
Attributes: []transaction.Attribute{},
|
|
|
|
Inputs: []transaction.Input{},
|
|
|
|
Outputs: []transaction.Output{},
|
|
|
|
Scripts: []transaction.Witness{},
|
2018-03-25 10:45:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return tx
|
|
|
|
}
|
|
|
|
|
|
|
|
func utilityTokenTX() *transaction.Transaction {
|
2019-12-03 14:05:06 +00:00
|
|
|
admin := hash.Hash160([]byte{byte(opcode.PUSHF)})
|
2018-03-25 10:45:54 +00:00
|
|
|
registerTX := &transaction.RegisterTX{
|
|
|
|
AssetType: transaction.UtilityToken,
|
|
|
|
Name: "[{\"lang\":\"zh-CN\",\"name\":\"小蚁币\"},{\"lang\":\"en\",\"name\":\"AntCoin\"}]",
|
|
|
|
Amount: calculateUtilityAmount(),
|
|
|
|
Precision: 8,
|
|
|
|
Admin: admin,
|
|
|
|
}
|
|
|
|
tx := &transaction.Transaction{
|
|
|
|
Type: transaction.RegisterType,
|
|
|
|
Data: registerTX,
|
2019-12-09 14:14:10 +00:00
|
|
|
Attributes: []transaction.Attribute{},
|
|
|
|
Inputs: []transaction.Input{},
|
|
|
|
Outputs: []transaction.Output{},
|
|
|
|
Scripts: []transaction.Witness{},
|
2018-03-25 10:45:54 +00:00
|
|
|
}
|
2018-03-09 15:55:25 +00:00
|
|
|
|
2018-03-25 10:45:54 +00:00
|
|
|
return tx
|
2018-03-09 15:55:25 +00:00
|
|
|
}
|
2018-03-10 12:04:06 +00:00
|
|
|
|
2019-08-27 13:29:42 +00:00
|
|
|
func getValidators(cfg config.ProtocolConfiguration) ([]*keys.PublicKey, error) {
|
|
|
|
validators := make([]*keys.PublicKey, len(cfg.StandbyValidators))
|
2018-03-25 10:45:54 +00:00
|
|
|
for i, pubKeyStr := range cfg.StandbyValidators {
|
2019-08-27 13:29:42 +00:00
|
|
|
pubKey, err := keys.NewPublicKeyFromString(pubKeyStr)
|
2018-03-25 10:45:54 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
validators[i] = pubKey
|
|
|
|
}
|
|
|
|
return validators, nil
|
2018-03-10 12:04:06 +00:00
|
|
|
}
|
|
|
|
|
2019-08-27 13:29:42 +00:00
|
|
|
func getNextConsensusAddress(validators []*keys.PublicKey) (val util.Uint160, err error) {
|
2018-03-25 10:45:54 +00:00
|
|
|
vlen := len(validators)
|
|
|
|
raw, err := smartcontract.CreateMultiSigRedeemScript(
|
|
|
|
vlen-(vlen-1)/3,
|
|
|
|
validators,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return val, err
|
|
|
|
}
|
2019-08-23 15:50:45 +00:00
|
|
|
return hash.Hash160(raw), nil
|
2018-03-25 10:45:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func calculateUtilityAmount() util.Fixed8 {
|
|
|
|
sum := 0
|
|
|
|
for i := 0; i < len(genAmount); i++ {
|
|
|
|
sum += genAmount[i]
|
|
|
|
}
|
2019-08-23 12:41:22 +00:00
|
|
|
return util.Fixed8FromInt64(int64(sum * decrementInterval))
|
2018-03-10 12:04:06 +00:00
|
|
|
}
|
2018-03-17 11:53:21 +00:00
|
|
|
|
|
|
|
// headerSliceReverse reverses the given slice of *Header.
|
2020-01-14 12:32:07 +00:00
|
|
|
func headerSliceReverse(dest []*block.Header) {
|
2018-03-17 11:53:21 +00:00
|
|
|
for i, j := 0, len(dest)-1; i < j; i, j = i+1, j-1 {
|
|
|
|
dest[i], dest[j] = dest[j], dest[i]
|
|
|
|
}
|
|
|
|
}
|