forked from TrueCloudLab/neoneo-go
core: export UtilityTokenID and GoverningTokenID
Both are very useful outside of the core, this change also makes respective transactions initialize with the package as they don't depend on any kind of input and it makes no sense recreating them again and again on every use.
This commit is contained in:
parent
b41a5239c6
commit
a4294f4b5f
4 changed files with 42 additions and 33 deletions
|
@ -432,7 +432,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if prevTXOutput.AssetID.Equals(governingTokenTX().Hash()) {
|
if prevTXOutput.AssetID.Equals(GoverningTokenID()) {
|
||||||
spentCoin := NewSpentCoinState(input.PrevHash, prevTXHeight)
|
spentCoin := NewSpentCoinState(input.PrevHash, prevTXHeight)
|
||||||
spentCoin.items[input.PrevIndex] = block.Index
|
spentCoin.items[input.PrevIndex] = block.Index
|
||||||
if err = cache.PutSpentCoinState(input.PrevHash, spentCoin); err != nil {
|
if err = cache.PutSpentCoinState(input.PrevHash, spentCoin); err != nil {
|
||||||
|
@ -648,14 +648,14 @@ func processOutputs(tx *transaction.Transaction, dao *cachedDao) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func processTXWithValidatorsAdd(output *transaction.Output, account *state.Account, dao *cachedDao) error {
|
func processTXWithValidatorsAdd(output *transaction.Output, account *state.Account, dao *cachedDao) error {
|
||||||
if output.AssetID.Equals(governingTokenTX().Hash()) && len(account.Votes) > 0 {
|
if output.AssetID.Equals(GoverningTokenID()) && len(account.Votes) > 0 {
|
||||||
return modAccountVotes(account, dao, output.Amount)
|
return modAccountVotes(account, dao, output.Amount)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func processTXWithValidatorsSubtract(output *transaction.Output, account *state.Account, dao *cachedDao) error {
|
func processTXWithValidatorsSubtract(output *transaction.Output, account *state.Account, dao *cachedDao) error {
|
||||||
if output.AssetID.Equals(governingTokenTX().Hash()) && len(account.Votes) > 0 {
|
if output.AssetID.Equals(GoverningTokenID()) && len(account.Votes) > 0 {
|
||||||
return modAccountVotes(account, dao, -output.Amount)
|
return modAccountVotes(account, dao, -output.Amount)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -724,7 +724,7 @@ func processAccountStateDescriptor(descriptor *transaction.StateDescriptor, dao
|
||||||
}
|
}
|
||||||
|
|
||||||
if descriptor.Field == "Votes" {
|
if descriptor.Field == "Votes" {
|
||||||
balance := account.GetBalanceValues()[governingTokenTX().Hash()]
|
balance := account.GetBalanceValues()[GoverningTokenID()]
|
||||||
if err = modAccountVotes(account, dao, -balance); err != nil {
|
if err = modAccountVotes(account, dao, -balance); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -999,14 +999,14 @@ func (bc *Blockchain) FeePerByte(t *transaction.Transaction) util.Fixed8 {
|
||||||
func (bc *Blockchain) NetworkFee(t *transaction.Transaction) util.Fixed8 {
|
func (bc *Blockchain) NetworkFee(t *transaction.Transaction) util.Fixed8 {
|
||||||
inputAmount := util.Fixed8FromInt64(0)
|
inputAmount := util.Fixed8FromInt64(0)
|
||||||
for _, txOutput := range bc.References(t) {
|
for _, txOutput := range bc.References(t) {
|
||||||
if txOutput.AssetID == utilityTokenTX().Hash() {
|
if txOutput.AssetID == UtilityTokenID() {
|
||||||
inputAmount.Add(txOutput.Amount)
|
inputAmount.Add(txOutput.Amount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
outputAmount := util.Fixed8FromInt64(0)
|
outputAmount := util.Fixed8FromInt64(0)
|
||||||
for _, txOutput := range t.Outputs {
|
for _, txOutput := range t.Outputs {
|
||||||
if txOutput.AssetID == utilityTokenTX().Hash() {
|
if txOutput.AssetID == UtilityTokenID() {
|
||||||
outputAmount.Add(txOutput.Amount)
|
outputAmount.Add(txOutput.Amount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1192,7 +1192,7 @@ func (bc *Blockchain) verifyResults(t *transaction.Transaction) error {
|
||||||
if len(resultsDestroy) > 1 {
|
if len(resultsDestroy) > 1 {
|
||||||
return errors.New("tx has more than 1 destroy output")
|
return errors.New("tx has more than 1 destroy output")
|
||||||
}
|
}
|
||||||
if len(resultsDestroy) == 1 && resultsDestroy[0].AssetID != utilityTokenTX().Hash() {
|
if len(resultsDestroy) == 1 && resultsDestroy[0].AssetID != UtilityTokenID() {
|
||||||
return errors.New("tx destroys non-utility token")
|
return errors.New("tx destroys non-utility token")
|
||||||
}
|
}
|
||||||
sysfee := bc.SystemFee(t)
|
sysfee := bc.SystemFee(t)
|
||||||
|
@ -1208,14 +1208,14 @@ func (bc *Blockchain) verifyResults(t *transaction.Transaction) error {
|
||||||
switch t.Type {
|
switch t.Type {
|
||||||
case transaction.MinerType, transaction.ClaimType:
|
case transaction.MinerType, transaction.ClaimType:
|
||||||
for _, r := range resultsIssue {
|
for _, r := range resultsIssue {
|
||||||
if r.AssetID != utilityTokenTX().Hash() {
|
if r.AssetID != UtilityTokenID() {
|
||||||
return errors.New("miner or claim tx issues non-utility tokens")
|
return errors.New("miner or claim tx issues non-utility tokens")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case transaction.IssueType:
|
case transaction.IssueType:
|
||||||
for _, r := range resultsIssue {
|
for _, r := range resultsIssue {
|
||||||
if r.AssetID == utilityTokenTX().Hash() {
|
if r.AssetID == UtilityTokenID() {
|
||||||
return errors.New("issue tx issues utility tokens")
|
return errors.New("issue tx issues utility tokens")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,17 @@ import (
|
||||||
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
|
"github.com/CityOfZion/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.
|
// createGenesisBlock creates a genesis block based on the given configuration.
|
||||||
func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) {
|
func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error) {
|
||||||
validators, err := getValidators(cfg)
|
validators, err := getValidators(cfg)
|
||||||
|
@ -38,8 +49,6 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
governingTX := governingTokenTX()
|
|
||||||
utilityTX := utilityTokenTX()
|
|
||||||
rawScript, err := smartcontract.CreateMultiSigRedeemScript(
|
rawScript, err := smartcontract.CreateMultiSigRedeemScript(
|
||||||
len(cfg.StandbyValidators)/2+1,
|
len(cfg.StandbyValidators)/2+1,
|
||||||
validators,
|
validators,
|
||||||
|
@ -62,16 +71,16 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error)
|
||||||
Outputs: []transaction.Output{},
|
Outputs: []transaction.Output{},
|
||||||
Scripts: []transaction.Witness{},
|
Scripts: []transaction.Witness{},
|
||||||
},
|
},
|
||||||
governingTX,
|
&governingTokenTX,
|
||||||
utilityTX,
|
&utilityTokenTX,
|
||||||
{
|
{
|
||||||
Type: transaction.IssueType,
|
Type: transaction.IssueType,
|
||||||
Data: &transaction.IssueTX{}, // no fields.
|
Data: &transaction.IssueTX{}, // no fields.
|
||||||
Inputs: []transaction.Input{},
|
Inputs: []transaction.Input{},
|
||||||
Outputs: []transaction.Output{
|
Outputs: []transaction.Output{
|
||||||
{
|
{
|
||||||
AssetID: governingTX.Hash(),
|
AssetID: governingTokenTX.Hash(),
|
||||||
Amount: governingTX.Data.(*transaction.RegisterTX).Amount,
|
Amount: governingTokenTX.Data.(*transaction.RegisterTX).Amount,
|
||||||
ScriptHash: scriptOut,
|
ScriptHash: scriptOut,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -92,7 +101,7 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*block.Block, error)
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func governingTokenTX() *transaction.Transaction {
|
func init() {
|
||||||
admin := hash.Hash160([]byte{byte(opcode.PUSHT)})
|
admin := hash.Hash160([]byte{byte(opcode.PUSHT)})
|
||||||
registerTX := &transaction.RegisterTX{
|
registerTX := &transaction.RegisterTX{
|
||||||
AssetType: transaction.GoverningToken,
|
AssetType: transaction.GoverningToken,
|
||||||
|
@ -102,7 +111,7 @@ func governingTokenTX() *transaction.Transaction {
|
||||||
Admin: admin,
|
Admin: admin,
|
||||||
}
|
}
|
||||||
|
|
||||||
tx := &transaction.Transaction{
|
governingTokenTX = transaction.Transaction{
|
||||||
Type: transaction.RegisterType,
|
Type: transaction.RegisterType,
|
||||||
Data: registerTX,
|
Data: registerTX,
|
||||||
Attributes: []transaction.Attribute{},
|
Attributes: []transaction.Attribute{},
|
||||||
|
@ -111,19 +120,15 @@ func governingTokenTX() *transaction.Transaction {
|
||||||
Scripts: []transaction.Witness{},
|
Scripts: []transaction.Witness{},
|
||||||
}
|
}
|
||||||
|
|
||||||
return tx
|
admin = hash.Hash160([]byte{byte(opcode.PUSHF)})
|
||||||
}
|
registerTX = &transaction.RegisterTX{
|
||||||
|
|
||||||
func utilityTokenTX() *transaction.Transaction {
|
|
||||||
admin := hash.Hash160([]byte{byte(opcode.PUSHF)})
|
|
||||||
registerTX := &transaction.RegisterTX{
|
|
||||||
AssetType: transaction.UtilityToken,
|
AssetType: transaction.UtilityToken,
|
||||||
Name: "[{\"lang\":\"zh-CN\",\"name\":\"小蚁币\"},{\"lang\":\"en\",\"name\":\"AntCoin\"}]",
|
Name: "[{\"lang\":\"zh-CN\",\"name\":\"小蚁币\"},{\"lang\":\"en\",\"name\":\"AntCoin\"}]",
|
||||||
Amount: calculateUtilityAmount(),
|
Amount: calculateUtilityAmount(),
|
||||||
Precision: 8,
|
Precision: 8,
|
||||||
Admin: admin,
|
Admin: admin,
|
||||||
}
|
}
|
||||||
tx := &transaction.Transaction{
|
utilityTokenTX = transaction.Transaction{
|
||||||
Type: transaction.RegisterType,
|
Type: transaction.RegisterType,
|
||||||
Data: registerTX,
|
Data: registerTX,
|
||||||
Attributes: []transaction.Attribute{},
|
Attributes: []transaction.Attribute{},
|
||||||
|
@ -131,8 +136,16 @@ func utilityTokenTX() *transaction.Transaction {
|
||||||
Outputs: []transaction.Output{},
|
Outputs: []transaction.Output{},
|
||||||
Scripts: []transaction.Witness{},
|
Scripts: []transaction.Witness{},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return tx
|
// 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) {
|
func getValidators(cfg config.ProtocolConfiguration) ([]*keys.PublicKey, error) {
|
||||||
|
|
|
@ -50,12 +50,10 @@ func TestGetConsensusAddressMainNet(t *testing.T) {
|
||||||
|
|
||||||
func TestUtilityTokenTX(t *testing.T) {
|
func TestUtilityTokenTX(t *testing.T) {
|
||||||
expect := "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"
|
expect := "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"
|
||||||
tx := utilityTokenTX()
|
assert.Equal(t, expect, UtilityTokenID().StringLE())
|
||||||
assert.Equal(t, expect, tx.Hash().StringLE())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGoverningTokenTX(t *testing.T) {
|
func TestGoverningTokenTX(t *testing.T) {
|
||||||
expect := "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b"
|
expect := "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b"
|
||||||
tx := governingTokenTX()
|
assert.Equal(t, expect, GoverningTokenID().StringLE())
|
||||||
assert.Equal(t, expect, tx.Hash().StringLE())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/CityOfZion/neo-go/pkg/core"
|
||||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||||
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
||||||
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
"github.com/CityOfZion/neo-go/pkg/smartcontract"
|
||||||
|
@ -160,15 +161,12 @@ func (c *Client) SignAndPushInvocationTx(script []byte, wif *keys.WIF, gas util.
|
||||||
var txHash util.Uint256
|
var txHash util.Uint256
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
gasIDB, _ := hex.DecodeString("602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7")
|
|
||||||
gasID, _ := util.Uint256DecodeBytesLE(gasIDB)
|
|
||||||
|
|
||||||
tx := transaction.NewInvocationTX(script, gas)
|
tx := transaction.NewInvocationTX(script, gas)
|
||||||
|
|
||||||
fromAddress := wif.PrivateKey.Address()
|
fromAddress := wif.PrivateKey.Address()
|
||||||
|
|
||||||
if gas > 0 {
|
if gas > 0 {
|
||||||
if err = AddInputsAndUnspentsToTx(tx, fromAddress, gasID, gas, c); err != nil {
|
if err = AddInputsAndUnspentsToTx(tx, fromAddress, core.UtilityTokenID(), gas, c); err != nil {
|
||||||
return txHash, errors.Wrap(err, "failed to add inputs and unspents to transaction")
|
return txHash, errors.Wrap(err, "failed to add inputs and unspents to transaction")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue