PDX公有链将面向全球征集节点算力,为下一步主网上线打下坚实基础。想成为PDX“共识委员会”成员(愿意参与生成区块的、有一定数量的押金、活跃的节点,都可以是共识委员会成员)的话,你必须先来了解一下PDX共识委员会的质押规则。下面就为大家详细介绍一下该质押机制的具体内容。
区块链,正在一步步改变我们的生活。
设计初衷
为了极大程度的保证共识委员会防止有恶意节点大量且频繁的进出委员会对Utopia共识算法机制产生影响,并且给予参与到共识委员当中的成员产生最大的收益。对恶意退出委员会的节点作出一定的限制的惩罚。
职责和收益
共识委员主要负责以下事务:
收集网络里的交易;
验证交易并把交易打包到区块;
广播区块给其他节点,在通过验证后将区块添加到自己本地区块链上。
共识委员有什么收益:
成为共识委员获得的直接收益来自区块生产奖励,可以理解为系统中的矿工。
共识委员=挖矿权+挖矿奖励+手续费收入。虽然现在币价不高,但会有更多的人进行锁仓,价格可能会有较大飞跃,静候。
质押与解除质押介绍
质押
用户当启动一个节点链接Utopia主网的时候,会累计活跃度,当活跃度满足一定条 件的时候,这个节点拥有参与到共识机制并且称为共识委员会成员之一的机会,这个 时候用户可以通过购买PDX token的方式,将token转账给这个节点的挖矿地址,然后 通过发起质押交易的方式,向Utopia质押合约发起转账,即调用质押合约的方式,也 可以通过已拥有足够PDX币的账户发起质押交易,赋予需要参与到共识机制的节点地 址质押标识的方式。质押地址是一个固定的十六进制地址,合约名称为hypothecation,转换成地址信息以后为:
0x04D2FBC88555e90F457F814819224460519e73A1
当用户发起质押交易, Utopia在接收到质押交易以后,会根据发起质押合约交易的账户地址进行校验。
校验步骤如下:
1.首先校验用户发起质押交易的质押金额与当前准许进入委员会的质押金金额的关 系,不小于质押门槛金额进行下一步,小于则调用合约失败 。
2.其次检查用户是否进行过质押操作,如果有质押记录那么质押金额进行累加,如果 没有则创建相应的质押记录。
需要说明的是:进入共识委员会的质押金额是与节点数量正相关的,规则为共识会会员每增加128个成员,质押金额翻倍的规则。那么最初的质押金额为:100万个pdx 币。Utopia鼓励用户进行质押,质押金额越多额外的分红奖励也会越多。
当用户的质押金额满足条件以后,质押交易的合约执行成功,该用户拥有进入委员 会的资格,如果质押的金额不够,质押交易的合约会执行失败,用户可以通过增加质押金的方式重新发起质押交易。
解除质押
当用户由于个人原因,想主动退出共识委员会,取回质押金额的时候,Utopia允许用 户进行解除质押操作。与质押交易类似,用户也可以通过发起解除质押交易,解除质 押合约的名称为redamption,转换成地址信息以后为:
0x60e1e88eadf16458dacDBAe83D472CA17c960aCA
Utopia在接收到解除质押交易以后,会根据该账户地址的质押记录进行退款。如果,退款账户在发起退款的时候, 已不在共识委员会,或者需要被惩罚(惩罚办法稍后介绍),解除质押的合约对该账户惩罚以后,将剩余的质押金退还。
惩罚机制
为了让参与到共识机制的成员中少数恶意节点作恶有所顾忌,以及增加作恶成本。Utopia引入惩罚机制。
惩罚对象:进行过质押交易的账户并且在连续几个区间内,没有发送assertion,而导 致活跃度不足,被踢除出委员会的。
惩罚措施:扣除该账户第一次质押金额的百分之十,作为惩罚。
交易发送代码示例
质押交易
package vmimport ( "context" "fmt" "math/big" "pdx-chain/common" "pdx-chain/core/types" "pdx-chain/crypto" "pdx-chain/p2p/discover" "pdx-chain/rlp" "pdx-chain/utopia/utils/client" "testing")func TestHypothecation_Run(t *testing.T) { if client, err := client.Connect("http://10.0.0.42:8546"); err != n il { fmt.Printf(err.Error()) return } else {if privKey, err := crypto.HexToECDSA("9ee905a8b9afcdc23a33d6f2d a3cdae63a0e873bf24f27b99e97f6acc034af9a"); err != nil { fmt.Printf(err.Error()) return } else { nodeID := discover.PubkeyID(&privKey.PublicKey) fmt.Printf("nodeID:%s \n", nodeID.String()) from := crypto.PubkeyToAddress(privKey.PublicKey) fmt.Printf("from:%s\n", from.String()) //质押 to := common.BytesToAddress(crypto.Keccak256([]byte("hypoth ecation"))[12:])fmt.Printf("to:%s\n", to.String()) fmt.Println(from.String()) if nonce, err := client.EthClient.NonceAt(context.TODO(), f rom, nil); err != nil { fmt.Printf("ddddd:%s", err.Error()) return } else { amount := big.NewInt(3000000000000000000) gasLimit := uint64(4712388) gasPrice := big.NewInt(240000000000) //todo ྌ॒உ᯿ᥝ҅ӧ ᚆտಸunderpriceᲙ҅ीय़ᧆ꧊੪ဌํᳯ᷌ԧݢզॡ҅֗ type HypothecationAddress struct { Address common.Address `json:"address"` //ᩙԨಽೀᩒ ໒ጱ࣎ࣈ }addr := common.HexToAddress("0x0297545eCb2686062fF91D18 7bf21CDdE63ca28B") recaption := &HypothecationAddress{ addr, } payload, _ := rlp.EncodeToBytes(recaption) tx := types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, payload) //EIP155 signer signer := types.NewEIP155Signer(big.NewInt(739)) //signer := types.HomesteadSigner{} signedTx, _ := types.SignTx(tx, signer, privKey) // client.EthClient.SendTransaction(context.TODO(), sig nedTx) if txHash, err := client.SendRawTransaction(context.TOD O(), signedTx); err != nil { fmt.Println("yerror", err.Error()) } else { fmt.Printf("Transaction hash: %s\n", txHash.String( )) } } } }
}
解除质押
package vmimport ( "context" "fmt" "math/big" "pdx-chain/common" "pdx-chain/core/types" "pdx-chain/crypto" "pdx-chain/log" "pdx-chain/p2p/discover" "pdx-chain/rlp" "pdx-chain/utopia/utils/client" "testing")func TestHypothecation_Run2(t *testing.T) {if client, err := client.Connect("http://10.0.0.42:8546"); err != n il { fmt.Printf(err.Error()) return } else { if privKey, err := crypto.HexToECDSA("de69eae2e01673b54aa8ea69f ae874cd1930af923bebd54015066942ca7732bc"); err != nil { fmt.Printf(err.Error()) return } else { nodeID := discover.PubkeyID(&privKey.PublicKey) fmt.Printf("nodeID:%s \n", nodeID.String()) from := crypto.PubkeyToAddress(privKey.PublicKey) fmt.Printf("from:%s\n", from.String()) to := common.BytesToAddress(crypto.Keccak256([]byte("redamp tion"))[12:]) fmt.Printf("to:%s\n", to.String()) fmt.Println(from.String()) if nonce, err := client.EthClient.NonceAt(context.TODO(), f rom, nil); err != nil { fmt.Printf("ddddd:%s", err.Error()) return } else { amount := big.NewInt(3000000000000000000) gasLimit := uint64(4712388) gasPrice := big.NewInt(240000000000) type RecaptionInfo struct { RecaptionAddress common.Address `json:"recaption_ad dress"` VoluntarilyExit bool `json:"voluntarily_ exit"` //ฎވฎԆۖᭅڊ } recaption := &RecaptionInfo{ from, true, } payload, err := rlp.EncodeToBytes(recaption) log.Info("payload", "payload", string(payload))if err != nil { fmt.Printf("marshal XChainTransferWithdraw err:%s", err) return } tx := types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, payload) //EIP155 signer signer := types.NewEIP155Signer(big.NewInt(111)) //signer := types.HomesteadSigner{} signedTx, _ := types.SignTx(tx, signer, privKey) // client.EthClient.SendTransaction(context.TODO(), sig nedTx) if txHash, err := client.SendRawTransaction(context.TOD O(), signedTx); err != nil { fmt.Println("yerror", err.Error()) } else { fmt.Printf("Transaction hash: %s\n", txHash.String( )) } } }
对于以上示例,在pdx-chain/core/vm路径下有所提供的相应文件,分别名为hypothecation_test.go与hypothecation-Red_test.go.
利用PDX钱包发送质押交易
PDX官方钱包网站地址为http://dev.wallet.pdx.ltd,使用浏览器打开以后具体操作如图:
1.打开PDX官方钱包并登录钱包
2.发起质押交易
如果没有质押地址的选型,操作如下:
利用MyEtherWallet发送质押交易
打开MyEtherWallet,添加自定义节点进行连接,具体操作如图所示:
1.解锁账户
点击添加自定义节点以后会弹出添加页面,具体操作如图:
当连接成功以后,刷新一下页面,选择需要发送质押交易的keystore账户进行解锁,在 发送质押交易之前请先确保账户里面有充足的余额。
点击选择钱包按钮以后,会弹出选择keystore文件的页面,选择要质押的账户keystore:
选好以后,输入解锁账户的密码,即可对账户进行解锁。
2.发送交易
解锁成功以后,并且账户余额充足的话,即可发送质押交易,ps:示例图片中的质押金 额仅供参考,质押合约的地址为:0x04D2FBC88555e90F457F814819224460519e73A1