65503aa9b4
1. Closes #840: added Nonce field to transaction.Transaction and removed Nonce field from transaction.MinerTx 2. Added following methods to different tx types: - NewMinerTx() - NewMinerTxWithNonce(...) - NewEnrollmentTx(...) - NewIssueTx() - NewPublishTx(...) - NewRegisterTx(...) - NewStateTx(...) in order to avoid code duplication when new transaction is created. 3. Commented out test cases where binary transaction/block are used. These test cases marked with `TODO NEO3.0: Update binary` and need to be updated. 4. Updated other tests 5. Added constant Nonce to GoveringTockenTx, UtilityTokenTx and genesis block to avoid data variability. Also marked with TODO.
171 lines
4.6 KiB
Go
171 lines
4.6 KiB
Go
package core
|
|
|
|
import (
|
|
"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"
|
|
)
|
|
|
|
var (
|
|
// governingTokenTX represents transaction that is used to create
|
|
// governing (NEO) token. It's a part of the genesis block.
|
|
governingTokenTX transaction.Transaction
|
|
|
|
// utilityTokenTX represents transaction that is used to create
|
|
// utility (GAS) token. It's a part of the genesis block. It's mostly
|
|
// useful for its hash that represents GAS asset ID.
|
|
utilityTokenTX transaction.Transaction
|
|
)
|
|
|
|
// createGenesisBlock creates a genesis block based on the given configuration.
|
|
func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) {
|
|
validators, err := getValidators(cfg)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
nextConsensus, err := getNextConsensusAddress(validators)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
base := block.Base{
|
|
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,
|
|
Script: transaction.Witness{
|
|
InvocationScript: []byte{},
|
|
VerificationScript: []byte{byte(opcode.PUSHT)},
|
|
},
|
|
}
|
|
|
|
rawScript, err := smartcontract.CreateMultiSigRedeemScript(
|
|
len(cfg.StandbyValidators)/2+1,
|
|
validators,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
scriptOut := hash.Hash160(rawScript)
|
|
|
|
minerTx := transaction.NewMinerTXWithNonce(2083236893)
|
|
|
|
issueTx := transaction.NewIssueTX()
|
|
// TODO NEO3.0: nonce should be constant to avoid variability of genesis block
|
|
issueTx.Nonce = 0
|
|
issueTx.Outputs = []transaction.Output{
|
|
{
|
|
AssetID: governingTokenTX.Hash(),
|
|
Amount: governingTokenTX.Data.(*transaction.RegisterTX).Amount,
|
|
ScriptHash: scriptOut,
|
|
},
|
|
}
|
|
issueTx.Scripts = []transaction.Witness{
|
|
{
|
|
InvocationScript: []byte{},
|
|
VerificationScript: []byte{byte(opcode.PUSHT)},
|
|
},
|
|
}
|
|
|
|
b := &block.Block{
|
|
Base: base,
|
|
Transactions: []*transaction.Transaction{
|
|
minerTx,
|
|
&governingTokenTX,
|
|
&utilityTokenTX,
|
|
issueTx,
|
|
},
|
|
}
|
|
|
|
if err = b.RebuildMerkleRoot(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return b, nil
|
|
}
|
|
|
|
func init() {
|
|
admin := hash.Hash160([]byte{byte(opcode.PUSHT)})
|
|
registerTX := &transaction.RegisterTX{
|
|
AssetType: transaction.GoverningToken,
|
|
Name: "[{\"lang\":\"zh-CN\",\"name\":\"小蚁股\"},{\"lang\":\"en\",\"name\":\"AntShare\"}]",
|
|
Amount: util.Fixed8FromInt64(100000000),
|
|
Precision: 0,
|
|
Admin: admin,
|
|
}
|
|
|
|
governingTokenTX = *transaction.NewRegisterTX(registerTX)
|
|
// TODO NEO3.0: nonce should be constant to avoid variability of token hash
|
|
governingTokenTX.Nonce = 0
|
|
|
|
admin = hash.Hash160([]byte{byte(opcode.PUSHF)})
|
|
registerTX = &transaction.RegisterTX{
|
|
AssetType: transaction.UtilityToken,
|
|
Name: "[{\"lang\":\"zh-CN\",\"name\":\"小蚁币\"},{\"lang\":\"en\",\"name\":\"AntCoin\"}]",
|
|
Amount: calculateUtilityAmount(),
|
|
Precision: 8,
|
|
Admin: admin,
|
|
}
|
|
utilityTokenTX = *transaction.NewRegisterTX(registerTX)
|
|
// TODO NEO3.0: nonce should be constant to avoid variability of token hash
|
|
utilityTokenTX.Nonce = 0
|
|
}
|
|
|
|
// GoverningTokenID returns the governing token (NEO) hash.
|
|
func GoverningTokenID() util.Uint256 {
|
|
return governingTokenTX.Hash()
|
|
}
|
|
|
|
// UtilityTokenID returns the utility token (GAS) hash.
|
|
func UtilityTokenID() util.Uint256 {
|
|
return utilityTokenTX.Hash()
|
|
}
|
|
|
|
func getValidators(cfg config.ProtocolConfiguration) ([]*keys.PublicKey, error) {
|
|
validators := make([]*keys.PublicKey, len(cfg.StandbyValidators))
|
|
for i, pubKeyStr := range cfg.StandbyValidators {
|
|
pubKey, err := keys.NewPublicKeyFromString(pubKeyStr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
validators[i] = pubKey
|
|
}
|
|
return validators, nil
|
|
}
|
|
|
|
func getNextConsensusAddress(validators []*keys.PublicKey) (val util.Uint160, err error) {
|
|
vlen := len(validators)
|
|
raw, err := smartcontract.CreateMultiSigRedeemScript(
|
|
vlen-(vlen-1)/3,
|
|
validators,
|
|
)
|
|
if err != nil {
|
|
return val, err
|
|
}
|
|
return hash.Hash160(raw), nil
|
|
}
|
|
|
|
func calculateUtilityAmount() util.Fixed8 {
|
|
sum := 0
|
|
for i := 0; i < len(genAmount); i++ {
|
|
sum += genAmount[i]
|
|
}
|
|
return util.Fixed8FromInt64(int64(sum * decrementInterval))
|
|
}
|
|
|
|
// headerSliceReverse reverses the given slice of *Header.
|
|
func headerSliceReverse(dest []*block.Header) {
|
|
for i, j := 0, len(dest)-1; i < j; i, j = i+1, j-1 {
|
|
dest[i], dest[j] = dest[j], dest[i]
|
|
}
|
|
}
|