From: oysheng <33340252+oysheng@users.noreply.github.com> Date: Thu, 11 Jul 2019 06:01:59 +0000 (+0800) Subject: modify general config (#257) X-Git-Tag: v1.0.5~164 X-Git-Url: http://git.osdn.net/view?p=bytom%2Fvapor.git;a=commitdiff_plain;h=73164af54a2587ba479b8b133274e3ecd0559a68 modify general config (#257) * modify general config * move code * modify * optimise --- diff --git a/api/query.go b/api/query.go index c3689833..d65acaac 100644 --- a/api/query.go +++ b/api/query.go @@ -327,7 +327,7 @@ func (a *API) listUnspentOutputs(ctx context.Context, filter struct { // return gasRate func (a *API) gasRate() Response { - gasrate := map[string]int64{"gas_rate": consensus.VMGasRate} + gasrate := map[string]int64{"gas_rate": consensus.ActiveNetParams.VMGasRate} return NewSuccessResponse(gasrate) } diff --git a/blockchain/txbuilder/estimate.go b/blockchain/txbuilder/estimate.go index b769435f..0a0da8ac 100644 --- a/blockchain/txbuilder/estimate.go +++ b/blockchain/txbuilder/estimate.go @@ -37,21 +37,21 @@ func EstimateTxGas(template Template) (*EstimateTxGasInfo, error) { flexibleGas := int64(0) if totalP2WPKHGas > 0 { - flexibleGas += baseP2WPKHGas + (baseSize+baseP2WPKHSize)*consensus.StorageGasRate + flexibleGas += baseP2WPKHGas + (baseSize+baseP2WPKHSize)*consensus.ActiveNetParams.StorageGasRate } else if totalP2WSHGas > 0 { - flexibleGas += baseP2WSHGas + (baseSize+baseP2WSHSize)*consensus.StorageGasRate + flexibleGas += baseP2WSHGas + (baseSize+baseP2WSHSize)*consensus.ActiveNetParams.StorageGasRate } // the total transaction storage gas - totalTxSizeGas := (int64(template.Transaction.TxData.SerializedSize) + totalWitnessSize) * consensus.StorageGasRate + totalTxSizeGas := (int64(template.Transaction.TxData.SerializedSize) + totalWitnessSize) * consensus.ActiveNetParams.StorageGasRate // the total transaction gas is composed of storage and virtual machines totalGas := totalTxSizeGas + totalP2WPKHGas + totalP2WSHGas + flexibleGas return &EstimateTxGasInfo{ - TotalNeu: totalGas * consensus.VMGasRate, - FlexibleNeu: flexibleGas * consensus.VMGasRate, - StorageNeu: totalTxSizeGas * consensus.VMGasRate, - VMNeu: (totalP2WPKHGas + totalP2WSHGas) * consensus.VMGasRate, + TotalNeu: totalGas * consensus.ActiveNetParams.VMGasRate, + FlexibleNeu: flexibleGas * consensus.ActiveNetParams.VMGasRate, + StorageNeu: totalTxSizeGas * consensus.ActiveNetParams.VMGasRate, + VMNeu: (totalP2WPKHGas + totalP2WSHGas) * consensus.ActiveNetParams.VMGasRate, }, nil } diff --git a/common/address.go b/common/address.go index a5162e40..3fe4999f 100644 --- a/common/address.go +++ b/common/address.go @@ -116,7 +116,7 @@ func DecodeAddress(addr string, param *consensus.Params) (Address, error) { oneIndex := strings.LastIndexByte(addr, '1') if oneIndex > 1 { prefix := addr[:oneIndex+1] - if consensus.IsBech32SegwitPrefix(prefix, param) { + if IsBech32SegwitPrefix(prefix, param) { witnessVer, witnessProg, err := decodeSegWitAddress(addr) if err != nil { return nil, err @@ -144,6 +144,13 @@ func DecodeAddress(addr string, param *consensus.Params) (Address, error) { return nil, ErrUnknownAddressType } +// IsBech32SegwitPrefix returns whether the prefix is a known prefix for segwit +// addresses on any default or registered network. This is used when decoding +// an address string into a specific address type. +func IsBech32SegwitPrefix(prefix string, params *consensus.Params) bool { + return strings.ToLower(prefix) == params.Bech32HRPSegwit+"1" +} + // decodeSegWitAddress parses a bech32 encoded segwit address string and // returns the witness version and witness program byte representation. func decodeSegWitAddress(address string) (byte, []byte, error) { diff --git a/consensus/general.go b/consensus/general.go index da54f950..8598e826 100644 --- a/consensus/general.go +++ b/consensus/general.go @@ -2,45 +2,16 @@ package consensus import ( "encoding/binary" - "strings" "github.com/vapor/protocol/bc" ) -//consensus variables +// basic constant const ( - // Max gas that one block contains - MaxBlockGas = uint64(10000000) - VMGasRate = int64(200) - StorageGasRate = int64(1) - MaxGasAmount = int64(200000) - DefaultGasCredit = int64(160000) - - //config parameter for coinbase reward - CoinbasePendingBlockNumber = uint64(100) - - //config parameter for vote - VotePendingBlockNumber = uint64(10000) - - //DPOS parameter - NumOfConsensusNode = 10 - BlockNumEachNode = 12 - RoundVoteBlockNums = NumOfConsensusNode * BlockNumEachNode * 10 - MinConsensusNodeVoteNum = uint64(100000000000000) // min is 1 million BTM - MinVoteOutputAmount = uint64(100000000) // min is 1 BTM - - // BlockTimeInterval indicate product one block per 500 milliseconds - BlockTimeInterval = 500 - - // MaxTimeOffsetMs is the maximum number of seconds a block time is allowed to be ahead of the current time - MaxTimeOffsetMs = uint64(BlockTimeInterval * BlockNumEachNode / 3) - MedianTimeBlocks = 11 + BTMAlias = "BTM" PayToWitnessPubKeyHashDataSize = 20 PayToWitnessScriptHashDataSize = 32 - CoinbaseArbitrarySizeLimit = 128 - - BTMAlias = "BTM" ) // BTMAssetID is BTM's asset id, the soul asset of Bytom @@ -59,22 +30,30 @@ var BTMDefinitionMap = map[string]interface{}{ "description": `Bytom Official Issue`, } -// BlockSubsidy calculate the coinbase rewards on given block height -func BlockSubsidy(height uint64) uint64 { - for _, subsidy := range ActiveNetParams.ProducerSubsidys { - if height >= subsidy.BeginBlock && height <= subsidy.EndBlock { - return subsidy.Subsidy - } - } - return 0 +// BasicConfig indicate the basic config +type BasicConfig struct { + // gas config + MaxBlockGas uint64 // the max used gas for all transactions of a block + MaxGasAmount int64 // the max gas for a transaction + DefaultGasCredit int64 // the max default credit gas for a transaction with non-BTM asset + VMGasRate int64 // the gas rate for VM + StorageGasRate int64 // the gas rate for storage + + // utxo config + VotePendingBlockNumber uint64 // the valid block interval for vote utxo after the vote transaction is confirmed + CoinbasePendingBlockNumber uint64 // the valid block interval for coinbase utxo after the coinbase transaction is confirmed + CoinbaseArbitrarySizeLimit int // the max size for coinbase arbitrary } -// IsBech32SegwitPrefix returns whether the prefix is a known prefix for segwit -// addresses on any default or registered network. This is used when decoding -// an address string into a specific address type. -func IsBech32SegwitPrefix(prefix string, params *Params) bool { - prefix = strings.ToLower(prefix) - return prefix == params.Bech32HRPSegwit+"1" +// DPOSConfig indicate the dpos consensus config +type DPOSConfig struct { + NumOfConsensusNode int64 // the number of consensus node + BlockNumEachNode uint64 // the number of generated continuous blocks for each node + RoundVoteBlockNums uint64 // the block interval which count the vote result in a round + MinConsensusNodeVoteNum uint64 // the min BTM amount for becoming consensus node(the unit is neu) + MinVoteOutputAmount uint64 // the min BTM amount for voting output in a transaction(the unit is neu) + BlockTimeInterval uint64 // the block time interval for producting a block + MaxTimeOffsetMs uint64 // the max number of seconds a block time is allowed to be ahead of the current time } // Checkpoint identifies a known good point in the block chain. Using @@ -95,79 +74,112 @@ type ProducerSubsidy struct { // Params store the config for different network type Params struct { // Name defines a human-readable identifier for the network. - Name string + Name string + + // Bech32HRPSegwit defines the prefix of address for the network Bech32HRPSegwit string + // DefaultPort defines the default peer-to-peer port for the network. DefaultPort string + // BasicConfig defines the gas and utxo relatived paramters. + BasicConfig + + // DPOSConfig defines the dpos consensus paramters. + DPOSConfig + // DNSSeeds defines a list of DNS seeds for the network that are used // as one method to discover peers. - DNSSeeds []string - Checkpoints []Checkpoint + DNSSeeds []string + + // Checkpoints defines the checkpoint blocks + Checkpoints []Checkpoint + + // ProducerSubsidys defines the producer subsidy by block height ProducerSubsidys []ProducerSubsidy } -// ActiveNetParams is ... -var ActiveNetParams = MainNetParams +// VaporDPOSConfig return the dpos consensus config +func VaporDPOSConfig() DPOSConfig { + dpos := DPOSConfig{ + NumOfConsensusNode: 10, + BlockNumEachNode: 12, + MinConsensusNodeVoteNum: uint64(100000000000000), + MinVoteOutputAmount: uint64(100000000), + BlockTimeInterval: 500, + } + + dpos.RoundVoteBlockNums = uint64(uint64(dpos.NumOfConsensusNode) * dpos.BlockNumEachNode * 10) + dpos.MaxTimeOffsetMs = uint64(uint64(dpos.BlockTimeInterval) * dpos.BlockNumEachNode / 3) + return dpos +} + +// ActiveNetParams is the active NetParams +var ActiveNetParams = VaporNetParams // NetParams is the correspondence between chain_id and Params var NetParams = map[string]Params{ "mainnet": MainNetParams, "wisdom": TestNetParams, - "solonet": SoloNetParams, "vapor": VaporNetParams, + "solonet": SoloNetParams, } -// MainNetParams is the config for production +// MainNetParams is the config for bytom main-net var MainNetParams = Params{ Name: "main", Bech32HRPSegwit: "bm", DefaultPort: "46657", DNSSeeds: []string{"www.mainnetseed.bytom.io"}, - Checkpoints: []Checkpoint{ - {10000, bc.NewHash([32]byte{0x93, 0xe1, 0xeb, 0x78, 0x21, 0xd2, 0xb4, 0xad, 0x0f, 0x5b, 0x1c, 0xea, 0x82, 0xe8, 0x43, 0xad, 0x8c, 0x09, 0x9a, 0xb6, 0x5d, 0x8f, 0x70, 0xc5, 0x84, 0xca, 0xa2, 0xdd, 0xf1, 0x74, 0x65, 0x2c})}, - {20000, bc.NewHash([32]byte{0x7d, 0x38, 0x61, 0xf3, 0x2c, 0xc0, 0x03, 0x81, 0xbb, 0xcd, 0x9a, 0x37, 0x6f, 0x10, 0x5d, 0xfe, 0x6f, 0xfe, 0x2d, 0xa5, 0xea, 0x88, 0xa5, 0xe3, 0x42, 0xed, 0xa1, 0x17, 0x9b, 0xa8, 0x0b, 0x7c})}, - {30000, bc.NewHash([32]byte{0x32, 0x36, 0x06, 0xd4, 0x27, 0x2e, 0x35, 0x24, 0x46, 0x26, 0x7b, 0xe0, 0xfa, 0x48, 0x10, 0xa4, 0x3b, 0xb2, 0x40, 0xf1, 0x09, 0x51, 0x5b, 0x22, 0x9f, 0xf3, 0xc3, 0x83, 0x28, 0xaa, 0x4a, 0x00})}, - {40000, bc.NewHash([32]byte{0x7f, 0xe2, 0xde, 0x11, 0x21, 0xf3, 0xa9, 0xa0, 0xee, 0x60, 0x8d, 0x7d, 0x4b, 0xea, 0xcc, 0x33, 0xfe, 0x41, 0x25, 0xdc, 0x2f, 0x26, 0xc2, 0xf2, 0x9c, 0x07, 0x17, 0xf9, 0xe4, 0x4f, 0x9d, 0x46})}, - {50000, bc.NewHash([32]byte{0x5e, 0xfb, 0xdf, 0xf5, 0x35, 0x38, 0xa6, 0x0b, 0x75, 0x32, 0x02, 0x61, 0x83, 0x54, 0x34, 0xff, 0x3e, 0x82, 0x2e, 0xf8, 0x64, 0xae, 0x2d, 0xc7, 0x6c, 0x9d, 0x5e, 0xbd, 0xa3, 0xd4, 0x50, 0xcf})}, - {62000, bc.NewHash([32]byte{0xd7, 0x39, 0x8f, 0x23, 0x57, 0xf9, 0x4c, 0xa0, 0x28, 0xa7, 0x00, 0x2b, 0x53, 0x9e, 0x51, 0x2d, 0x3e, 0xca, 0xc9, 0x22, 0x59, 0xfc, 0xd0, 0x3f, 0x67, 0x1a, 0x0a, 0xb1, 0x02, 0xbf, 0x2b, 0x03})}, - {72000, bc.NewHash([32]byte{0x66, 0x02, 0x31, 0x19, 0xf1, 0x60, 0x35, 0x61, 0xa4, 0xf1, 0x38, 0x04, 0xcc, 0xe4, 0x59, 0x8f, 0x55, 0x39, 0xba, 0x22, 0xf2, 0x6d, 0x90, 0xbf, 0xc1, 0x87, 0xef, 0x98, 0xcc, 0x70, 0x4d, 0x94})}, - {83700, bc.NewHash([32]byte{0x7f, 0x26, 0xc9, 0x11, 0xe8, 0x46, 0xd0, 0x6e, 0x36, 0xbb, 0xac, 0xce, 0x99, 0xa2, 0x19, 0x89, 0x3f, 0xf7, 0x84, 0x2a, 0xcb, 0x44, 0x7f, 0xbb, 0x0e, 0x3b, 0xa3, 0x68, 0xd6, 0x2b, 0xe8, 0x0d})}, - {93700, bc.NewHash([32]byte{0x70, 0x44, 0x70, 0xe5, 0xb3, 0x9b, 0xd3, 0x67, 0x19, 0x20, 0x08, 0x42, 0x1b, 0x59, 0xe8, 0xdc, 0xb5, 0xbb, 0xb9, 0x2d, 0xd3, 0xdc, 0x28, 0x4e, 0xcb, 0x7b, 0x0b, 0xbf, 0x21, 0x51, 0xe1, 0xba})}, - {106600, bc.NewHash([32]byte{0x31, 0x15, 0x2b, 0x00, 0xd4, 0x07, 0xe1, 0xa7, 0x06, 0xe1, 0xae, 0x2e, 0x98, 0x69, 0x8f, 0x47, 0xff, 0x44, 0x97, 0x01, 0xa7, 0x9e, 0x08, 0xdb, 0xeb, 0x0f, 0x1f, 0x5a, 0xdd, 0xf5, 0x26, 0xb9})}, - {116600, bc.NewHash([32]byte{0x08, 0xeb, 0xf7, 0x6c, 0x27, 0xed, 0x81, 0xe7, 0xe7, 0xfe, 0x13, 0xca, 0x80, 0x71, 0x29, 0x26, 0x28, 0x72, 0x25, 0xa5, 0x2a, 0xa0, 0x36, 0x30, 0x58, 0xaa, 0x58, 0xc6, 0xdd, 0xf2, 0xa0, 0xe7})}, - {126600, bc.NewHash([32]byte{0xac, 0x10, 0x41, 0x08, 0x24, 0x80, 0xe9, 0x5a, 0x9f, 0x32, 0x0a, 0x5e, 0x17, 0x7b, 0x01, 0x8d, 0x0d, 0x0d, 0x3d, 0xfc, 0xa7, 0x1d, 0x81, 0x5f, 0x13, 0xb4, 0xad, 0x0f, 0xc6, 0xde, 0x7a, 0x10})}, - {131260, bc.NewHash([32]byte{0xdf, 0x18, 0xb5, 0xb1, 0x6f, 0x5f, 0xd2, 0x77, 0x7c, 0xab, 0xb8, 0x59, 0xcb, 0x13, 0x64, 0xce, 0x06, 0x06, 0x51, 0x39, 0x89, 0x30, 0x1b, 0x69, 0xd6, 0x00, 0xec, 0xd8, 0xfa, 0xd2, 0x09, 0x93})}, - {157000, bc.NewHash([32]byte{0xb7, 0x70, 0x38, 0x4c, 0x81, 0x32, 0xaf, 0x12, 0x8d, 0xfa, 0xb4, 0xeb, 0x46, 0x4e, 0xb7, 0xeb, 0x66, 0x14, 0xd9, 0x24, 0xc2, 0xd1, 0x0c, 0x9c, 0x14, 0x20, 0xc9, 0xea, 0x0e, 0x85, 0xc8, 0xc3})}, - {180000, bc.NewHash([32]byte{0x3c, 0x2a, 0x91, 0x55, 0xf3, 0x36, 0x6a, 0x5a, 0x60, 0xcf, 0x84, 0x42, 0xec, 0x4d, 0x0c, 0x63, 0xbc, 0x34, 0xe9, 0x1d, 0x1c, 0x6b, 0xb0, 0xf0, 0x50, 0xf3, 0xfb, 0x2d, 0xf6, 0xa1, 0xd9, 0x5c})}, - {191000, bc.NewHash([32]byte{0x09, 0x4f, 0xe3, 0x23, 0x91, 0xb5, 0x11, 0x18, 0x68, 0xcc, 0x99, 0x9f, 0xeb, 0x95, 0xf9, 0xcc, 0xa5, 0x27, 0x6a, 0xf9, 0x0e, 0xda, 0x1b, 0xc6, 0x2e, 0x03, 0x29, 0xfe, 0x08, 0xdd, 0x2b, 0x01})}, - {205000, bc.NewHash([32]byte{0x6f, 0xdd, 0x87, 0x26, 0x73, 0x3f, 0x0b, 0xc7, 0x58, 0x64, 0xa4, 0xdf, 0x45, 0xe4, 0x50, 0x27, 0x68, 0x38, 0x18, 0xb9, 0xa9, 0x44, 0x56, 0x20, 0x34, 0x68, 0xd8, 0x68, 0x72, 0xdb, 0x65, 0x6f})}, - {219700, bc.NewHash([32]byte{0x98, 0x49, 0x8d, 0x4b, 0x7e, 0xe9, 0x44, 0x55, 0xc1, 0x07, 0xdd, 0x9a, 0xba, 0x6b, 0x49, 0x92, 0x61, 0x15, 0x03, 0x4f, 0x59, 0x42, 0x35, 0x74, 0xea, 0x3b, 0xdb, 0x2c, 0x53, 0x11, 0x75, 0x74})}, - }, + Checkpoints: []Checkpoint{}, } -// TestNetParams is the config for test-net +// TestNetParams is the config for bytom test-net var TestNetParams = Params{ Name: "test", Bech32HRPSegwit: "tm", DefaultPort: "46656", DNSSeeds: []string{"www.testnetseed.bytom.io"}, - Checkpoints: []Checkpoint{ - {10303, bc.NewHash([32]byte{0x3e, 0x94, 0x5d, 0x35, 0x70, 0x30, 0xd4, 0x3b, 0x3d, 0xe3, 0xdd, 0x80, 0x67, 0x29, 0x9a, 0x5e, 0x09, 0xf9, 0xfb, 0x2b, 0xad, 0x5f, 0x92, 0xc8, 0x69, 0xd1, 0x42, 0x39, 0x74, 0x9a, 0xd1, 0x1c})}, - {40000, bc.NewHash([32]byte{0x6b, 0x13, 0x9a, 0x5b, 0x76, 0x77, 0x9b, 0xd4, 0x1c, 0xec, 0x53, 0x68, 0x44, 0xbf, 0xf4, 0x48, 0x94, 0x3d, 0x16, 0xe3, 0x9b, 0x2e, 0xe8, 0xa1, 0x0f, 0xa0, 0xbc, 0x7d, 0x2b, 0x17, 0x55, 0xfc})}, - {78000, bc.NewHash([32]byte{0xa9, 0x03, 0xc0, 0x0c, 0x62, 0x1a, 0x3d, 0x00, 0x7f, 0xd8, 0x5d, 0x51, 0xba, 0x43, 0xe4, 0xd0, 0xe3, 0xc5, 0xd4, 0x8f, 0x30, 0xb5, 0x5f, 0xa5, 0x77, 0x62, 0xd8, 0x8b, 0x11, 0x81, 0x5f, 0xb4})}, - {82000, bc.NewHash([32]byte{0x56, 0xb1, 0xba, 0x23, 0x69, 0x5c, 0x8f, 0x51, 0x4e, 0x23, 0xc0, 0xae, 0xaa, 0x25, 0x08, 0xc5, 0x85, 0xf3, 0x7c, 0xd1, 0xc6, 0x15, 0xa2, 0x51, 0xda, 0x79, 0x4f, 0x08, 0x13, 0x66, 0xc9, 0x85})}, - {83200, bc.NewHash([32]byte{0xb4, 0x6f, 0xc5, 0xcf, 0xa3, 0x3d, 0xe1, 0x11, 0x71, 0x68, 0x40, 0x68, 0x0c, 0xe7, 0x4c, 0xaf, 0x5a, 0x11, 0xfe, 0x82, 0xbc, 0x36, 0x88, 0x0f, 0xbd, 0x04, 0xf0, 0xc4, 0x86, 0xd4, 0xd6, 0xd5})}, - {93000, bc.NewHash([32]byte{0x6f, 0x4f, 0x37, 0x5f, 0xe9, 0xfb, 0xdf, 0x66, 0x60, 0x0e, 0xf0, 0x39, 0xb7, 0x18, 0x26, 0x75, 0xa0, 0x9a, 0xa5, 0x9b, 0x83, 0xc9, 0x9a, 0x25, 0x45, 0xb8, 0x7d, 0xd4, 0x99, 0x24, 0xa2, 0x8a})}, - {113300, bc.NewHash([32]byte{0x7a, 0x69, 0x75, 0xa5, 0xf6, 0xb6, 0x94, 0xf3, 0x94, 0xa2, 0x63, 0x91, 0x28, 0xb6, 0xab, 0x7e, 0xf9, 0x71, 0x27, 0x5a, 0xe2, 0x59, 0xd3, 0xff, 0x70, 0x6e, 0xcb, 0xd8, 0xd8, 0x30, 0x9c, 0xc4})}, + Checkpoints: []Checkpoint{}, +} + +// VaporNetParams is the config for vapor-net +var VaporNetParams = Params{ + Name: "vapor", + Bech32HRPSegwit: "vp", + BasicConfig: BasicConfig{ + MaxBlockGas: uint64(10000000), + MaxGasAmount: int64(200000), + DefaultGasCredit: int64(160000), + StorageGasRate: int64(1), + VMGasRate: int64(200), + VotePendingBlockNumber: uint64(10000), + CoinbasePendingBlockNumber: uint64(100), + CoinbaseArbitrarySizeLimit: 128, + }, + DPOSConfig: VaporDPOSConfig(), + Checkpoints: []Checkpoint{}, + ProducerSubsidys: []ProducerSubsidy{ + {BeginBlock: 1, EndBlock: 63072000, Subsidy: 15000000}, }, } -// SoloNetParams is the config for test-net +// SoloNetParams is the config for solo test-net var SoloNetParams = Params{ Name: "solo", Bech32HRPSegwit: "sm", - Checkpoints: []Checkpoint{}, + BasicConfig: BasicConfig{ + MaxBlockGas: uint64(10000000), + MaxGasAmount: int64(200000), + DefaultGasCredit: int64(160000), + StorageGasRate: int64(1), + VMGasRate: int64(200), + VotePendingBlockNumber: uint64(10000), + CoinbasePendingBlockNumber: uint64(100), + CoinbaseArbitrarySizeLimit: 128, + }, + DPOSConfig: VaporDPOSConfig(), + Checkpoints: []Checkpoint{}, ProducerSubsidys: []ProducerSubsidy{ {BeginBlock: 0, EndBlock: 0, Subsidy: 24}, {BeginBlock: 1, EndBlock: 840000, Subsidy: 24}, @@ -176,12 +188,12 @@ var SoloNetParams = Params{ }, } -// VaporNetParams is the config for vapor-net -var VaporNetParams = Params{ - Name: "vapor", - Bech32HRPSegwit: "vp", - Checkpoints: []Checkpoint{}, - ProducerSubsidys: []ProducerSubsidy{ - {BeginBlock: 1, EndBlock: 63072000, Subsidy: 15000000}, - }, +// BlockSubsidy calculate the coinbase rewards on given block height +func BlockSubsidy(height uint64) uint64 { + for _, subsidy := range ActiveNetParams.ProducerSubsidys { + if height >= subsidy.BeginBlock && height <= subsidy.EndBlock { + return subsidy.Subsidy + } + } + return 0 } diff --git a/proposal/blockproposer/blockproposer.go b/proposal/blockproposer/blockproposer.go index 0b568cf1..7f8c1da1 100644 --- a/proposal/blockproposer/blockproposer.go +++ b/proposal/blockproposer/blockproposer.go @@ -40,7 +40,7 @@ type BlockProposer struct { func (b *BlockProposer) generateBlocks() { xpub := config.CommonConfig.PrivateKey().XPub() xpubStr := hex.EncodeToString(xpub[:]) - ticker := time.NewTicker(consensus.BlockTimeInterval * time.Millisecond) + ticker := time.NewTicker(time.Duration(consensus.ActiveNetParams.BlockTimeInterval) * time.Millisecond) defer ticker.Stop() for { @@ -58,10 +58,10 @@ func (b *BlockProposer) generateBlocks() { if now < bestBlockHeader.Timestamp { base = bestBlockHeader.Timestamp } - minTimeToNextBlock := consensus.BlockTimeInterval - base%consensus.BlockTimeInterval + minTimeToNextBlock := consensus.ActiveNetParams.BlockTimeInterval - base%consensus.ActiveNetParams.BlockTimeInterval nextBlockTime := base + minTimeToNextBlock - if (nextBlockTime - now) < consensus.BlockTimeInterval/10 { - nextBlockTime += consensus.BlockTimeInterval + if (nextBlockTime - now) < consensus.ActiveNetParams.BlockTimeInterval/10 { + nextBlockTime += consensus.ActiveNetParams.BlockTimeInterval } blocker, err := b.chain.GetBlocker(&bestBlockHash, nextBlockTime) diff --git a/proposal/proposal.go b/proposal/proposal.go index d2d045e8..a4c51e43 100644 --- a/proposal/proposal.go +++ b/proposal/proposal.go @@ -37,7 +37,7 @@ func createCoinbaseTx(accountManager *account.Manager, blockHeight uint64) (tx * return nil, err } - if len(arbitrary) > consensus.CoinbaseArbitrarySizeLimit { + if len(arbitrary) > consensus.ActiveNetParams.CoinbaseArbitrarySizeLimit { return nil, validation.ErrCoinbaseArbitraryOversize } @@ -99,7 +99,7 @@ func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager PreviousBlockHash: preBlockHash, Timestamp: timestamp, BlockCommitment: types.BlockCommitment{}, - BlockWitness: types.BlockWitness{Witness: make([][]byte, consensus.NumOfConsensusNode)}, + BlockWitness: types.BlockWitness{Witness: make([][]byte, consensus.ActiveNetParams.NumOfConsensusNode)}, }, } bcBlock := &bc.Block{BlockHeader: &bc.BlockHeader{Height: nextBlockHeight}} @@ -133,7 +133,7 @@ func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager continue } - if gasUsed+uint64(gasStatus.GasUsed) > consensus.MaxBlockGas { + if gasUsed+uint64(gasStatus.GasUsed) > consensus.ActiveNetParams.MaxBlockGas { break } @@ -149,7 +149,7 @@ func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager b.Transactions = append(b.Transactions, txDesc.Tx) txEntries = append(txEntries, tx) gasUsed += uint64(gasStatus.GasUsed) - if gasUsed == consensus.MaxBlockGas { + if gasUsed == consensus.ActiveNetParams.MaxBlockGas { break } diff --git a/proposal/proposal_test.go b/proposal/proposal_test.go index bfc8fa39..cf6c82a0 100644 --- a/proposal/proposal_test.go +++ b/proposal/proposal_test.go @@ -12,13 +12,11 @@ import ( ) func TestCalCoinbaseTxReward(t *testing.T) { - consensus.ActiveNetParams = consensus.Params{ - ProducerSubsidys: []consensus.ProducerSubsidy{ - {BeginBlock: 0, EndBlock: 0, Subsidy: 24}, - {BeginBlock: 1, EndBlock: 840000, Subsidy: 24}, - {BeginBlock: 840001, EndBlock: 1680000, Subsidy: 12}, - {BeginBlock: 1680001, EndBlock: 3360000, Subsidy: 6}, - }, + consensus.ActiveNetParams.ProducerSubsidys = []consensus.ProducerSubsidy{ + {BeginBlock: 0, EndBlock: 0, Subsidy: 24}, + {BeginBlock: 1, EndBlock: 840000, Subsidy: 24}, + {BeginBlock: 840001, EndBlock: 1680000, Subsidy: 12}, + {BeginBlock: 1680001, EndBlock: 3360000, Subsidy: 6}, } reductionInterval := uint64(840000) @@ -134,13 +132,11 @@ func TestCalCoinbaseTxReward(t *testing.T) { } func TestCountCoinbaseTxRewards(t *testing.T) { - consensus.ActiveNetParams = consensus.Params{ - ProducerSubsidys: []consensus.ProducerSubsidy{ - {BeginBlock: 0, EndBlock: 0, Subsidy: 24}, - {BeginBlock: 1, EndBlock: 840000, Subsidy: 24}, - {BeginBlock: 840001, EndBlock: 1680000, Subsidy: 12}, - {BeginBlock: 1680001, EndBlock: 3360000, Subsidy: 6}, - }, + consensus.ActiveNetParams.ProducerSubsidys = []consensus.ProducerSubsidy{ + {BeginBlock: 0, EndBlock: 0, Subsidy: 24}, + {BeginBlock: 1, EndBlock: 840000, Subsidy: 24}, + {BeginBlock: 840001, EndBlock: 1680000, Subsidy: 12}, + {BeginBlock: 1680001, EndBlock: 3360000, Subsidy: 6}, } cases := []struct { @@ -153,7 +149,7 @@ func TestCountCoinbaseTxRewards(t *testing.T) { desc: "the block height is RoundVoteBlockNums - 1", block: &types.Block{ BlockHeader: types.BlockHeader{ - Height: consensus.RoundVoteBlockNums - 1, + Height: consensus.ActiveNetParams.RoundVoteBlockNums - 1, }, Transactions: []*types.Tx{nil}, }, @@ -168,7 +164,7 @@ func TestCountCoinbaseTxRewards(t *testing.T) { desc: "the block height is RoundVoteBlockNums", block: &types.Block{ BlockHeader: types.BlockHeader{ - Height: consensus.RoundVoteBlockNums, + Height: consensus.ActiveNetParams.RoundVoteBlockNums, }, Transactions: []*types.Tx{nil}, }, @@ -193,7 +189,7 @@ func TestCountCoinbaseTxRewards(t *testing.T) { desc: "the block height is RoundVoteBlockNums + 1", block: &types.Block{ BlockHeader: types.BlockHeader{ - Height: consensus.RoundVoteBlockNums + 1, + Height: consensus.ActiveNetParams.RoundVoteBlockNums + 1, }, Transactions: []*types.Tx{nil}, }, @@ -208,7 +204,7 @@ func TestCountCoinbaseTxRewards(t *testing.T) { desc: "the block height is RoundVoteBlockNums * 2", block: &types.Block{ BlockHeader: types.BlockHeader{ - Height: consensus.RoundVoteBlockNums * 2, + Height: consensus.ActiveNetParams.RoundVoteBlockNums * 2, }, Transactions: []*types.Tx{nil}, }, @@ -238,7 +234,7 @@ func TestCountCoinbaseTxRewards(t *testing.T) { desc: "the block height is 2*RoundVoteBlockNums + 1", block: &types.Block{ BlockHeader: types.BlockHeader{ - Height: 2*consensus.RoundVoteBlockNums + 1, + Height: 2*consensus.ActiveNetParams.RoundVoteBlockNums + 1, }, Transactions: []*types.Tx{nil}, }, diff --git a/protocol/consensus_node_manager.go b/protocol/consensus_node_manager.go index 930e42db..d55e7ccf 100644 --- a/protocol/consensus_node_manager.go +++ b/protocol/consensus_node_manager.go @@ -21,11 +21,11 @@ func (c *Chain) getBestConsensusResult() (*state.ConsensusResult, error) { func getBlockerOrder(startTimestamp, blockTimestamp, numOfConsensusNode uint64) uint64 { // One round of product block time for all consensus nodes - roundBlockTime := consensus.BlockNumEachNode * numOfConsensusNode * consensus.BlockTimeInterval + roundBlockTime := consensus.ActiveNetParams.BlockNumEachNode * numOfConsensusNode * consensus.ActiveNetParams.BlockTimeInterval // The start time of the last round of product block lastRoundStartTime := startTimestamp + (blockTimestamp-startTimestamp)/roundBlockTime*roundBlockTime // Order of blocker - return (blockTimestamp - lastRoundStartTime) / (consensus.BlockNumEachNode * consensus.BlockTimeInterval) + return (blockTimestamp - lastRoundStartTime) / (consensus.ActiveNetParams.BlockNumEachNode * consensus.ActiveNetParams.BlockTimeInterval) } func (c *Chain) getConsensusNode(prevBlockHash *bc.Hash, pubkey string) (*state.ConsensusNode, error) { @@ -89,7 +89,7 @@ func (c *Chain) getPrevRoundLastBlock(prevBlockHash *bc.Hash) (*types.BlockHeade return nil, errNotFoundBlockNode } - for blockHeader.Height%consensus.RoundVoteBlockNums != 0 { + for blockHeader.Height%consensus.ActiveNetParams.RoundVoteBlockNums != 0 { blockHeader, err = c.store.GetBlockHeader(&blockHeader.PreviousBlockHash) if err != nil { return nil, err @@ -147,7 +147,7 @@ func (c *Chain) GetBlocker(prevBlockHash *bc.Hash, timeStamp uint64) (string, er return "", err } - startTimestamp := prevVoteRoundLastBlock.Timestamp + consensus.BlockTimeInterval + startTimestamp := prevVoteRoundLastBlock.Timestamp + consensus.ActiveNetParams.BlockTimeInterval order := getBlockerOrder(startTimestamp, timeStamp, uint64(len(consensusNodeMap))) for xPub, consensusNode := range consensusNodeMap { if consensusNode.Order == order { diff --git a/protocol/state/consensus_result.go b/protocol/state/consensus_result.go index 16fcded0..ff08429c 100644 --- a/protocol/state/consensus_result.go +++ b/protocol/state/consensus_result.go @@ -72,7 +72,7 @@ func CalcVoteSeq(blockHeight uint64) uint64 { if blockHeight == 0 { return 0 } - return (blockHeight-1)/consensus.RoundVoteBlockNums + 1 + return (blockHeight-1)/consensus.ActiveNetParams.RoundVoteBlockNums + 1 } // ConsensusResult represents a snapshot of each round of DPOS voting @@ -141,7 +141,7 @@ func (c *ConsensusResult) AttachCoinbaseReward(block *types.Block) error { return err } - if block.Height%consensus.RoundVoteBlockNums == 1 { + if block.Height%consensus.ActiveNetParams.RoundVoteBlockNums == 1 { c.CoinbaseReward = map[string]uint64{} } @@ -158,7 +158,7 @@ func (c *ConsensusResult) AttachCoinbaseReward(block *types.Block) error { func (c *ConsensusResult) ConsensusNodes() (map[string]*ConsensusNode, error) { var nodes []*ConsensusNode for pubkey, voteNum := range c.NumOfVote { - if voteNum >= consensus.MinConsensusNodeVoteNum { + if voteNum >= consensus.ActiveNetParams.MinConsensusNodeVoteNum { var xpub chainkd.XPub if err := xpub.UnmarshalText([]byte(pubkey)); err != nil { return nil, err @@ -171,7 +171,7 @@ func (c *ConsensusResult) ConsensusNodes() (map[string]*ConsensusNode, error) { // if there is a performance problem, consider the optimization later. sort.Sort(byVote(nodes)) result := make(map[string]*ConsensusNode) - for i := 0; i < len(nodes) && i < consensus.NumOfConsensusNode; i++ { + for i := 0; i < len(nodes) && int64(i) < consensus.ActiveNetParams.NumOfConsensusNode; i++ { nodes[i].Order = uint64(i) result[nodes[i].XPub.String()] = nodes[i] } @@ -232,7 +232,7 @@ func (c *ConsensusResult) DetachBlock(block *types.Block) error { // DetachCoinbaseReward detach coinbase reward func (c *ConsensusResult) DetachCoinbaseReward(block *types.Block) error { - if block.Height%consensus.RoundVoteBlockNums == 0 { + if block.Height%consensus.ActiveNetParams.RoundVoteBlockNums == 0 { for i, output := range block.Transactions[0].Outputs { if i == 0 { continue @@ -281,13 +281,13 @@ func (c *ConsensusResult) Fork() *ConsensusResult { // IsFinalize check if the result is end of consensus round func (c *ConsensusResult) IsFinalize() bool { - return c.BlockHeight%consensus.RoundVoteBlockNums == 0 + return c.BlockHeight%consensus.ActiveNetParams.RoundVoteBlockNums == 0 } // GetCoinbaseRewards convert into CoinbaseReward array and sort it by amount func (c *ConsensusResult) GetCoinbaseRewards(blockHeight uint64) ([]CoinbaseReward, error) { rewards := []CoinbaseReward{} - if blockHeight%consensus.RoundVoteBlockNums != 0 { + if blockHeight%consensus.ActiveNetParams.RoundVoteBlockNums != 0 { return rewards, nil } diff --git a/protocol/state/utxo_view.go b/protocol/state/utxo_view.go index 4e0d56c4..0fd68398 100644 --- a/protocol/state/utxo_view.go +++ b/protocol/state/utxo_view.go @@ -165,12 +165,12 @@ func (view *UtxoViewpoint) applySpendUtxo(block *bc.Block, tx *bc.Tx, statusFail switch entry.Type { case storage.CoinbaseUTXOType: - if (entry.BlockHeight + consensus.CoinbasePendingBlockNumber) > block.Height { + if (entry.BlockHeight + consensus.ActiveNetParams.CoinbasePendingBlockNumber) > block.Height { return errors.New("coinbase utxo is not ready for use") } case storage.VoteUTXOType: - if (entry.BlockHeight + consensus.VotePendingBlockNumber) > block.Height { + if (entry.BlockHeight + consensus.ActiveNetParams.VotePendingBlockNumber) > block.Height { return errors.New("Coin is within the voting lock time") } } diff --git a/protocol/validation/block.go b/protocol/validation/block.go index 8d276f21..5e12cbd9 100644 --- a/protocol/validation/block.go +++ b/protocol/validation/block.go @@ -28,10 +28,10 @@ var ( func checkBlockTime(b *bc.Block, parent *types.BlockHeader) error { now := uint64(time.Now().UnixNano() / 1e6) - if b.Timestamp < (parent.Timestamp + consensus.BlockTimeInterval) { + if b.Timestamp < (parent.Timestamp + consensus.ActiveNetParams.BlockTimeInterval) { return errBadTimestamp } - if b.Timestamp > (now + consensus.MaxTimeOffsetMs) { + if b.Timestamp > (now + consensus.ActiveNetParams.MaxTimeOffsetMs) { return errBadTimestamp } @@ -104,7 +104,7 @@ func ValidateBlock(b *bc.Block, parent *types.BlockHeader, rewards []state.Coinb return err } - if blockGasSum += uint64(validateResult.gasStatus.GasUsed); blockGasSum > consensus.MaxBlockGas { + if blockGasSum += uint64(validateResult.gasStatus.GasUsed); blockGasSum > consensus.ActiveNetParams.MaxBlockGas { return errOverBlockLimit } } diff --git a/protocol/validation/block_test.go b/protocol/validation/block_test.go index 917b039e..6749963e 100644 --- a/protocol/validation/block_test.go +++ b/protocol/validation/block_test.go @@ -40,8 +40,8 @@ func TestCheckBlockTime(t *testing.T) { }, { desc: "timestamp of the block and the parent block are both greater than max limit", - blockTime: uint64(time.Now().UnixNano()/int64(time.Millisecond)) + consensus.MaxTimeOffsetMs + 2000, - parentTime: []uint64{uint64(time.Now().UnixNano()/int64(time.Millisecond)) + consensus.MaxTimeOffsetMs + 1000}, + blockTime: uint64(time.Now().UnixNano()/int64(time.Millisecond)) + consensus.ActiveNetParams.MaxTimeOffsetMs + 2000, + parentTime: []uint64{uint64(time.Now().UnixNano()/int64(time.Millisecond)) + consensus.ActiveNetParams.MaxTimeOffsetMs + 1000}, err: errBadTimestamp, }, } diff --git a/protocol/validation/tx.go b/protocol/validation/tx.go index 8a5bf14f..d52c1055 100644 --- a/protocol/validation/tx.go +++ b/protocol/validation/tx.go @@ -60,15 +60,15 @@ func (g *GasState) setGas(BTMValue int64, txSize int64) error { g.BTMValue = uint64(BTMValue) var ok bool - if g.GasLeft, ok = checked.DivInt64(BTMValue, consensus.VMGasRate); !ok { + if g.GasLeft, ok = checked.DivInt64(BTMValue, consensus.ActiveNetParams.VMGasRate); !ok { return errors.Wrap(ErrGasCalculate, "setGas calc gas amount") } - if g.GasLeft > consensus.MaxGasAmount { - g.GasLeft = consensus.MaxGasAmount + if g.GasLeft > consensus.ActiveNetParams.MaxGasAmount { + g.GasLeft = consensus.ActiveNetParams.MaxGasAmount } - if g.StorageGas, ok = checked.MulInt64(txSize, consensus.StorageGasRate); !ok { + if g.StorageGas, ok = checked.MulInt64(txSize, consensus.ActiveNetParams.StorageGasRate); !ok { return errors.Wrap(ErrGasCalculate, "setGas calc tx storage gas") } return nil @@ -100,7 +100,7 @@ func (g *GasState) updateUsage(gasLeft int64) error { return errors.Wrap(ErrGasCalculate, "updateUsage calc gas diff") } - if !g.GasValid && (g.GasUsed > consensus.DefaultGasCredit || g.StorageGas > g.GasLeft) { + if !g.GasValid && (g.GasUsed > consensus.ActiveNetParams.DefaultGasCredit || g.StorageGas > g.GasLeft) { return ErrOverGasCredit } return nil @@ -238,7 +238,7 @@ func checkValid(vs *validationState, e bc.Entry) (err error) { if err = checkValidSrc(&vs2, e.Source); err != nil { return errors.Wrap(err, "checking vote output source") } - if e.Source.Value.Amount < consensus.MinVoteOutputAmount { + if e.Source.Value.Amount < consensus.ActiveNetParams.MinVoteOutputAmount { return ErrVoteOutputAmount } @@ -269,7 +269,7 @@ func checkValid(vs *validationState, e bc.Entry) (err error) { Code: config.FederationWScript(config.CommonConfig), } - if _, err := vm.Verify(NewTxVMContext(vs, e, prog, e.WitnessArguments), consensus.DefaultGasCredit); err != nil { + if _, err := vm.Verify(NewTxVMContext(vs, e, prog, e.WitnessArguments), consensus.ActiveNetParams.DefaultGasCredit); err != nil { return errors.Wrap(err, "checking cross-chain input control program") } @@ -385,7 +385,7 @@ func checkValid(vs *validationState, e bc.Entry) (err error) { return ErrWrongCoinbaseAsset } - if e.Arbitrary != nil && len(e.Arbitrary) > consensus.CoinbaseArbitrarySizeLimit { + if e.Arbitrary != nil && len(e.Arbitrary) > consensus.ActiveNetParams.CoinbaseArbitrarySizeLimit { return ErrCoinbaseArbitraryOversize } diff --git a/protocol/validation/tx_test.go b/protocol/validation/tx_test.go index c87f3945..17664df3 100644 --- a/protocol/validation/tx_test.go +++ b/protocol/validation/tx_test.go @@ -34,7 +34,7 @@ func TestGasStatus(t *testing.T) { BTMValue: 0, }, output: &GasState{ - GasLeft: 10000 / consensus.VMGasRate, + GasLeft: 10000 / consensus.ActiveNetParams.VMGasRate, GasUsed: 0, BTMValue: 10000, }, @@ -61,7 +61,7 @@ func TestGasStatus(t *testing.T) { }, { input: &GasState{ - GasLeft: consensus.DefaultGasCredit, + GasLeft: consensus.ActiveNetParams.DefaultGasCredit, GasUsed: 0, BTMValue: 0, }, @@ -77,7 +77,7 @@ func TestGasStatus(t *testing.T) { }, { input: &GasState{ - GasLeft: consensus.DefaultGasCredit, + GasLeft: consensus.ActiveNetParams.DefaultGasCredit, GasUsed: 0, BTMValue: 0, }, @@ -557,7 +557,7 @@ func TestTxValidation(t *testing.T) { { desc: "coinbase arbitrary size out of limit", f: func() { - arbitrary := make([]byte, consensus.CoinbaseArbitrarySizeLimit+1) + arbitrary := make([]byte, consensus.ActiveNetParams.CoinbaseArbitrarySizeLimit+1) addCoinbase(consensus.BTMAssetID, 100000, arbitrary) }, err: ErrCoinbaseArbitraryOversize, diff --git a/test/block_test.go b/test/block_test.go index 1aca2826..eeb6c95f 100644 --- a/test/block_test.go +++ b/test/block_test.go @@ -63,7 +63,7 @@ func TestBlockHeader(t *testing.T) { desc: "invalid timestamp, greater than MaxTimeOffsetMs from system time", version: func() uint64 { return chain.BestBlockHeader().Version }, prevHeight: chain.BestBlockHeight, - timestamp: func() uint64 { return uint64(time.Now().Unix()) + consensus.MaxTimeOffsetMs + 60 }, + timestamp: func() uint64 { return uint64(time.Now().Unix()) + consensus.ActiveNetParams.MaxTimeOffsetMs + 60 }, prevHash: chain.BestBlockHash, valid: false, }, diff --git a/test/protocol_test.go b/test/protocol_test.go index b488569f..7be6689d 100644 --- a/test/protocol_test.go +++ b/test/protocol_test.go @@ -107,7 +107,7 @@ func TestDoubleSpentInDiffBlock(t *testing.T) { if err != nil { t.Fatal(err) } - if err := AppendBlocks(chain, consensus.CoinbasePendingBlockNumber+1); err != nil { + if err := AppendBlocks(chain, consensus.ActiveNetParams.CoinbasePendingBlockNumber+1); err != nil { t.Fatal(err) } @@ -148,7 +148,7 @@ func TestDoubleSpentInSameBlock(t *testing.T) { if err != nil { t.Fatal(err) } - if err := AppendBlocks(chain, consensus.CoinbasePendingBlockNumber+1); err != nil { + if err := AppendBlocks(chain, consensus.ActiveNetParams.CoinbasePendingBlockNumber+1); err != nil { t.Fatal(err) } @@ -201,7 +201,7 @@ func TestTxPoolDependencyTx(t *testing.T) { if err != nil { t.Fatal(err) } - if err := AppendBlocks(chain, consensus.CoinbasePendingBlockNumber+1); err != nil { + if err := AppendBlocks(chain, consensus.ActiveNetParams.CoinbasePendingBlockNumber+1); err != nil { t.Fatal(err) } @@ -256,7 +256,7 @@ func TestAddInvalidTxToTxPool(t *testing.T) { t.Fatal(err) } - if err := AppendBlocks(chain, consensus.CoinbasePendingBlockNumber+1); err != nil { + if err := AppendBlocks(chain, consensus.ActiveNetParams.CoinbasePendingBlockNumber+1); err != nil { t.Fatal(err) } diff --git a/wallet/utxo.go b/wallet/utxo.go index 874a94c7..1eec505f 100644 --- a/wallet/utxo.go +++ b/wallet/utxo.go @@ -226,7 +226,7 @@ func txInToUtxos(tx *types.Tx, statusFail bool) []*account.UTXO { func txOutToUtxos(tx *types.Tx, statusFail bool, blockHeight uint64) []*account.UTXO { validHeight := uint64(0) if tx.Inputs[0].InputType() == types.CoinbaseInputType { - validHeight = blockHeight + consensus.CoinbasePendingBlockNumber + validHeight = blockHeight + consensus.ActiveNetParams.CoinbasePendingBlockNumber } utxos := []*account.UTXO{} @@ -258,7 +258,7 @@ func txOutToUtxos(tx *types.Tx, statusFail bool, blockHeight uint64) []*account. continue } - voteValidHeight := blockHeight + consensus.VotePendingBlockNumber + voteValidHeight := blockHeight + consensus.ActiveNetParams.VotePendingBlockNumber if validHeight < voteValidHeight { validHeight = voteValidHeight }