mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 02:42:27 +00:00
Merge pull request #367 from nguyenbatam/create_new_api_get_reward
create new api get rewards
This commit is contained in:
commit
b681865f40
13 changed files with 122 additions and 17 deletions
|
|
@ -122,6 +122,7 @@ var (
|
||||||
//utils.ExtraDataFlag,
|
//utils.ExtraDataFlag,
|
||||||
configFileFlag,
|
configFileFlag,
|
||||||
utils.AnnounceTxsFlag,
|
utils.AnnounceTxsFlag,
|
||||||
|
utils.StoreRewardFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
rpcFlags = []cli.Flag{
|
rpcFlags = []cli.Flag{
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,10 @@ var (
|
||||||
Name: "announce-txs",
|
Name: "announce-txs",
|
||||||
Usage: "Always commit transactions",
|
Usage: "Always commit transactions",
|
||||||
}
|
}
|
||||||
|
StoreRewardFlag = cli.BoolFlag{
|
||||||
|
Name: "store-reward",
|
||||||
|
Usage: "Store reward to file",
|
||||||
|
}
|
||||||
DataDirFlag = DirectoryFlag{
|
DataDirFlag = DirectoryFlag{
|
||||||
Name: "datadir",
|
Name: "datadir",
|
||||||
Usage: "Data directory for the databases and keystore",
|
Usage: "Data directory for the databases and keystore",
|
||||||
|
|
@ -1082,7 +1086,12 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
|
||||||
// TODO(fjl): force-enable this in --dev mode
|
// TODO(fjl): force-enable this in --dev mode
|
||||||
cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name)
|
cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name)
|
||||||
}
|
}
|
||||||
|
if ctx.GlobalIsSet(StoreRewardFlag.Name) {
|
||||||
|
cfg.StoreRewardFolder = filepath.Join(stack.DataDir(), "tomo", "rewards")
|
||||||
|
if _, err := os.Stat(cfg.StoreRewardFolder); os.IsNotExist(err) {
|
||||||
|
os.Mkdir(cfg.StoreRewardFolder, os.ModePerm)
|
||||||
|
}
|
||||||
|
}
|
||||||
// Override any default configs for hard coded networks.
|
// Override any default configs for hard coded networks.
|
||||||
switch {
|
switch {
|
||||||
case ctx.GlobalBool(TestnetFlag.Name):
|
case ctx.GlobalBool(TestnetFlag.Name):
|
||||||
|
|
|
||||||
|
|
@ -215,13 +215,14 @@ type Posv struct {
|
||||||
signatures *lru.ARCCache // Signatures of recent blocks to speed up mining
|
signatures *lru.ARCCache // Signatures of recent blocks to speed up mining
|
||||||
validatorSignatures *lru.ARCCache // Signatures of recent blocks to speed up mining
|
validatorSignatures *lru.ARCCache // Signatures of recent blocks to speed up mining
|
||||||
verifiedHeaders *lru.ARCCache
|
verifiedHeaders *lru.ARCCache
|
||||||
|
rewards *lru.ARCCache
|
||||||
proposals map[common.Address]bool // Current list of proposals we are pushing
|
proposals map[common.Address]bool // Current list of proposals we are pushing
|
||||||
|
|
||||||
signer common.Address // Ethereum address of the signing key
|
signer common.Address // Ethereum address of the signing key
|
||||||
signFn clique.SignerFn // Signer function to authorize hashes with
|
signFn clique.SignerFn // Signer function to authorize hashes with
|
||||||
lock sync.RWMutex // Protects the signer fields
|
lock sync.RWMutex // Protects the signer fields
|
||||||
|
|
||||||
HookReward func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error
|
HookReward func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) (error, map[string]interface{})
|
||||||
HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error)
|
HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error)
|
||||||
HookValidator func(header *types.Header, signers []common.Address) ([]byte, error)
|
HookValidator func(header *types.Header, signers []common.Address) ([]byte, error)
|
||||||
HookVerifyMNs func(header *types.Header, signers []common.Address) error
|
HookVerifyMNs func(header *types.Header, signers []common.Address) error
|
||||||
|
|
@ -240,6 +241,7 @@ func New(config *params.PosvConfig, db ethdb.Database) *Posv {
|
||||||
signatures, _ := lru.NewARC(inmemorySnapshots)
|
signatures, _ := lru.NewARC(inmemorySnapshots)
|
||||||
validatorSignatures, _ := lru.NewARC(inmemorySnapshots)
|
validatorSignatures, _ := lru.NewARC(inmemorySnapshots)
|
||||||
verifiedHeaders, _ := lru.NewARC(inmemorySnapshots)
|
verifiedHeaders, _ := lru.NewARC(inmemorySnapshots)
|
||||||
|
rewards, _ := lru.NewARC(inmemorySnapshots)
|
||||||
return &Posv{
|
return &Posv{
|
||||||
config: &conf,
|
config: &conf,
|
||||||
db: db,
|
db: db,
|
||||||
|
|
@ -247,6 +249,7 @@ func New(config *params.PosvConfig, db ethdb.Database) *Posv {
|
||||||
signatures: signatures,
|
signatures: signatures,
|
||||||
verifiedHeaders: verifiedHeaders,
|
verifiedHeaders: verifiedHeaders,
|
||||||
validatorSignatures: validatorSignatures,
|
validatorSignatures: validatorSignatures,
|
||||||
|
rewards: rewards,
|
||||||
proposals: make(map[common.Address]bool),
|
proposals: make(map[common.Address]bool),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -847,9 +850,11 @@ func (c *Posv) Finalize(chain consensus.ChainReader, header *types.Header, state
|
||||||
rCheckpoint := chain.Config().Posv.RewardCheckpoint
|
rCheckpoint := chain.Config().Posv.RewardCheckpoint
|
||||||
|
|
||||||
if c.HookReward != nil && number%rCheckpoint == 0 {
|
if c.HookReward != nil && number%rCheckpoint == 0 {
|
||||||
if err := c.HookReward(chain, state, header); err != nil {
|
err, rewardResults := c.HookReward(chain, state, header)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
c.rewards.Add(header.Hash(), rewardResults)
|
||||||
}
|
}
|
||||||
|
|
||||||
// the state remains as is and uncles are dropped
|
// the state remains as is and uncles are dropped
|
||||||
|
|
@ -1079,3 +1084,15 @@ func Hop(len, pre, cur int) int {
|
||||||
return len - 1
|
return len - 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Posv) GetRewards(hash common.Hash) map[string]interface{} {
|
||||||
|
rewards, ok := c.rewards.Get(hash)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return rewards.(map[string]interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Posv) InsertRewards(hash common.Hash, rewards map[string]interface{}) {
|
||||||
|
c.rewards.Add(hash, rewards)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -387,17 +387,17 @@ func GetCandidatesOwnerBySigner(validator *contractValidator.TomoValidator, sign
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate reward for holders.
|
// Calculate reward for holders.
|
||||||
func CalculateRewardForHolders(foudationWalletAddr common.Address, validator *contractValidator.TomoValidator, state *state.StateDB, signer common.Address, calcReward *big.Int) error {
|
func CalculateRewardForHolders(foudationWalletAddr common.Address, validator *contractValidator.TomoValidator, state *state.StateDB, signer common.Address, calcReward *big.Int) (error, map[common.Address]*big.Int) {
|
||||||
rewards, err := GetRewardBalancesRate(foudationWalletAddr, signer, calcReward, validator)
|
rewards, err := GetRewardBalancesRate(foudationWalletAddr, signer, calcReward, validator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err, nil
|
||||||
}
|
}
|
||||||
if len(rewards) > 0 {
|
if len(rewards) > 0 {
|
||||||
for holder, reward := range rewards {
|
for holder, reward := range rewards {
|
||||||
state.AddBalance(holder, reward)
|
state.AddBalance(holder, reward)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil, rewards
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get reward balance rates for master node, founder and holders.
|
// Get reward balance rates for master node, founder and holders.
|
||||||
|
|
|
||||||
|
|
@ -141,9 +141,10 @@ type BlockChain struct {
|
||||||
validator Validator // block and state validator interface
|
validator Validator // block and state validator interface
|
||||||
vmConfig vm.Config
|
vmConfig vm.Config
|
||||||
|
|
||||||
badBlocks *lru.Cache // Bad block cache
|
badBlocks *lru.Cache // Bad block cache
|
||||||
IPCEndpoint string
|
IPCEndpoint string
|
||||||
Client *ethclient.Client // Global ipc client instance.
|
Client *ethclient.Client // Global ipc client instance.
|
||||||
|
HookWriteRewards func(header *types.Header)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlockChain returns a fully initialised block chain using information
|
// NewBlockChain returns a fully initialised block chain using information
|
||||||
|
|
@ -1222,6 +1223,9 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if bc.HookWriteRewards != nil {
|
||||||
|
bc.HookWriteRewards(block.Header())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Append a single chain head event if we've progressed the chain
|
// Append a single chain head event if we've progressed the chain
|
||||||
if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() {
|
if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() {
|
||||||
|
|
@ -1428,6 +1432,9 @@ func (bc *BlockChain) insertBlock(block *types.Block) ([]interface{}, []*types.L
|
||||||
events = append(events, ChainHeadEvent{block})
|
events = append(events, ChainHeadEvent{block})
|
||||||
log.Debug("New ChainHeadEvent from fetcher ", "number", block.NumberU64(), "hash", block.Hash())
|
log.Debug("New ChainHeadEvent from fetcher ", "number", block.NumberU64(), "hash", block.Hash())
|
||||||
}
|
}
|
||||||
|
if bc.HookWriteRewards != nil {
|
||||||
|
bc.HookWriteRewards(block.Header())
|
||||||
|
}
|
||||||
return events, coalescedLogs, nil
|
return events, coalescedLogs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package eth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/posv"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
|
|
@ -233,3 +234,13 @@ func (b *EthApiBackend) GetIPCClient() (*ethclient.Client, error) {
|
||||||
func (b *EthApiBackend) GetEngine() consensus.Engine {
|
func (b *EthApiBackend) GetEngine() consensus.Engine {
|
||||||
return b.eth.engine
|
return b.eth.engine
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *EthApiBackend) GetRewardByHash(hash common.Hash) map[string]interface{} {
|
||||||
|
if c, ok := s.eth.Engine().(*posv.Posv); ok {
|
||||||
|
rewards := c.GetRewards(hash)
|
||||||
|
if rewards != nil {
|
||||||
|
return rewards
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return make(map[string]interface{})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,12 @@
|
||||||
package eth
|
package eth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
@ -286,10 +289,11 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hook calculates reward for masternodes
|
// Hook calculates reward for masternodes
|
||||||
c.HookReward = func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error {
|
c.HookReward = func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) (error, map[string]interface{}) {
|
||||||
client, err := eth.blockchain.GetClient()
|
client, err := eth.blockchain.GetClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Fail to connect IPC client for blockSigner", "error", err)
|
log.Error("Fail to connect IPC client for blockSigner", "error", err)
|
||||||
|
return err, nil
|
||||||
}
|
}
|
||||||
number := header.Number.Uint64()
|
number := header.Number.Uint64()
|
||||||
rCheckpoint := chain.Config().Posv.RewardCheckpoint
|
rCheckpoint := chain.Config().Posv.RewardCheckpoint
|
||||||
|
|
@ -297,6 +301,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||||
if foudationWalletAddr == (common.Address{}) {
|
if foudationWalletAddr == (common.Address{}) {
|
||||||
log.Error("Foundation Wallet Address is empty", "error", foudationWalletAddr)
|
log.Error("Foundation Wallet Address is empty", "error", foudationWalletAddr)
|
||||||
}
|
}
|
||||||
|
rewards := make(map[string]interface{})
|
||||||
if number > 0 && number-rCheckpoint > 0 && foudationWalletAddr != (common.Address{}) {
|
if number > 0 && number-rCheckpoint > 0 && foudationWalletAddr != (common.Address{}) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
// Get signers in blockSigner smartcontract.
|
// Get signers in blockSigner smartcontract.
|
||||||
|
|
@ -309,30 +314,36 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||||
signers, err := contracts.GetRewardForCheckpoint(chain, addr, number, rCheckpoint, client, totalSigner)
|
signers, err := contracts.GetRewardForCheckpoint(chain, addr, number, rCheckpoint, client, totalSigner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Fail to get signers for reward checkpoint", "error", err)
|
log.Error("Fail to get signers for reward checkpoint", "error", err)
|
||||||
|
return err, nil
|
||||||
}
|
}
|
||||||
|
rewards["signers"] = signers
|
||||||
rewardSigners, err := contracts.CalculateRewardForSigner(chainReward, signers, *totalSigner)
|
rewardSigners, err := contracts.CalculateRewardForSigner(chainReward, signers, *totalSigner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Fail to calculate reward for signers", "error", err)
|
log.Error("Fail to calculate reward for signers", "error", err)
|
||||||
|
return err, nil
|
||||||
}
|
}
|
||||||
// Get validator.
|
// Get validator.
|
||||||
validator, err := contract.NewTomoValidator(common.HexToAddress(common.MasternodeVotingSMC), client)
|
validator, err := contract.NewTomoValidator(common.HexToAddress(common.MasternodeVotingSMC), client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Fail get instance of Tomo Validator", "error", err)
|
log.Error("Fail get instance of Tomo Validator", "error", err)
|
||||||
|
return err, nil
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
// Add reward for coin holders.
|
// Add reward for coin holders.
|
||||||
|
voterResults := make(map[common.Address]interface{})
|
||||||
if len(signers) > 0 {
|
if len(signers) > 0 {
|
||||||
for signer, calcReward := range rewardSigners {
|
for signer, calcReward := range rewardSigners {
|
||||||
err := contracts.CalculateRewardForHolders(foudationWalletAddr, validator, state, signer, calcReward)
|
err, rewards := contracts.CalculateRewardForHolders(foudationWalletAddr, validator, state, signer, calcReward)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Fail to calculate reward for holders.", "error", err)
|
log.Error("Fail to calculate reward for holders.", "error", err)
|
||||||
|
return err, nil
|
||||||
}
|
}
|
||||||
|
voterResults[signer] = rewards
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rewards["rewards"] = voterResults
|
||||||
log.Debug("Time Calculated HookReward ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
|
log.Debug("Time Calculated HookReward ", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
|
||||||
}
|
}
|
||||||
return nil
|
return nil, rewards
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hook verifies masternodes set
|
// Hook verifies masternodes set
|
||||||
|
|
@ -363,8 +374,28 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
eth.blockchain.HookWriteRewards = func(header *types.Header) {
|
||||||
|
if len(config.StoreRewardFolder) > 0 {
|
||||||
|
rewards := c.GetRewards(header.Hash())
|
||||||
|
if rewards == nil {
|
||||||
|
rewards = c.GetRewards(header.HashNoValidator())
|
||||||
|
if rewards != nil {
|
||||||
|
c.InsertRewards(header.Hash(), rewards)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if rewards == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data, err := json.Marshal(rewards)
|
||||||
|
if err == nil {
|
||||||
|
err = ioutil.WriteFile(filepath.Join(config.StoreRewardFolder, header.Number.String()+"."+header.Hash().Hex()), data, 0644)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error when save reward info ", "number", header.Number, "hash", header.Hash().Hex(), "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return eth, nil
|
return eth, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,8 @@ type Config struct {
|
||||||
|
|
||||||
// Miscellaneous options
|
// Miscellaneous options
|
||||||
DocRoot string `toml:"-"`
|
DocRoot string `toml:"-"`
|
||||||
|
|
||||||
|
StoreRewardFolder string
|
||||||
}
|
}
|
||||||
|
|
||||||
type configMarshaling struct {
|
type configMarshaling struct {
|
||||||
|
|
|
||||||
|
|
@ -492,6 +492,17 @@ func (s *PublicBlockChainAPI) BlockNumber() *big.Int {
|
||||||
return header.Number
|
return header.Number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BlockNumber returns the block number of the chain head.
|
||||||
|
func (s *PublicBlockChainAPI) GetRewardByHash(hash common.Hash) map[string]interface{} {
|
||||||
|
if c, ok := s.b.GetEngine().(*posv.Posv); ok {
|
||||||
|
rewards := c.GetRewards(hash)
|
||||||
|
if rewards != nil {
|
||||||
|
return rewards
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return make(map[string]interface{})
|
||||||
|
}
|
||||||
|
|
||||||
// GetBalance returns the amount of wei for the given address in the state of the
|
// GetBalance returns the amount of wei for the given address in the state of the
|
||||||
// given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta
|
// given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta
|
||||||
// block numbers are also allowed.
|
// block numbers are also allowed.
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,7 @@ type Backend interface {
|
||||||
CurrentBlock() *types.Block
|
CurrentBlock() *types.Block
|
||||||
GetIPCClient() (*ethclient.Client, error)
|
GetIPCClient() (*ethclient.Client, error)
|
||||||
GetEngine() consensus.Engine
|
GetEngine() consensus.Engine
|
||||||
|
GetRewardByHash(hash common.Hash) map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAPIs(apiBackend Backend) []rpc.API {
|
func GetAPIs(apiBackend Backend) []rpc.API {
|
||||||
|
|
|
||||||
|
|
@ -460,6 +460,11 @@ web3._extend({
|
||||||
call: 'eth_getRawTransactionByHash',
|
call: 'eth_getRawTransactionByHash',
|
||||||
params: 1
|
params: 1
|
||||||
}),
|
}),
|
||||||
|
new web3._extend.Method({
|
||||||
|
name: 'getRewardByHash',
|
||||||
|
call: 'eth_getRewardByHash',
|
||||||
|
params: 1
|
||||||
|
}),
|
||||||
new web3._extend.Method({
|
new web3._extend.Method({
|
||||||
name: 'getRawTransactionFromBlock',
|
name: 'getRawTransactionFromBlock',
|
||||||
call: function(args) {
|
call: function(args) {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package les
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/posv"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
|
|
@ -200,3 +201,12 @@ func (b *LesApiBackend) GetIPCClient() (*ethclient.Client, error) {
|
||||||
func (b *LesApiBackend) GetEngine() consensus.Engine {
|
func (b *LesApiBackend) GetEngine() consensus.Engine {
|
||||||
return b.eth.engine
|
return b.eth.engine
|
||||||
}
|
}
|
||||||
|
func (s *LesApiBackend) GetRewardByHash(hash common.Hash) map[string]interface{} {
|
||||||
|
if c, ok := s.eth.Engine().(*posv.Posv); ok {
|
||||||
|
rewards := c.GetRewards(hash)
|
||||||
|
if rewards != nil {
|
||||||
|
return rewards
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return make(map[string]interface{})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
VersionMajor = 1 // Major version component of the current release
|
VersionMajor = 1 // Major version component of the current release
|
||||||
VersionMinor = 1 // Minor version component of the current release
|
VersionMinor = 2 // Minor version component of the current release
|
||||||
VersionPatch = 3 // Patch version component of the current release
|
VersionPatch = 0 // Patch version component of the current release
|
||||||
VersionMeta = "stable" // Version metadata to append to the version string
|
VersionMeta = "stable" // Version metadata to append to the version string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue