bsc

创世合约里配置了系统合约,且地址是写死的,比如0x00000000000000001001, 会分配初始钱

然后会在第一个块进行初始化的调用。

使用案例

a: 获取validator ,这个方式是通过eth api 调用,因为不需要网络通信延迟,所以很快

method := "getValidators"
 
// 指定的方法名和参数列表打包成一个 ABI 编码的字节数组
data, err := p.validatorSetABIBeforeLuban.Pack(method)
 
// 系统合约调用 
msgData := (hexutil.Bytes)(data)
	toAddress := common.HexToAddress(systemcontracts.ValidatorContract)
	gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
	result, err := p.ethAPI.Call(ctx, ethapi.TransactionArgs{
		Gas:  &gas,
		To:   &toAddress,
		Data: &msgData,
	}, blockNr, nil)
 
// 将一个 ABI 编码的返回结果反序列化为含有具体类型数据的 Go 结构体(valSet)
var valSet []common.Address
err = p.validatorSetABIBeforeLuban.UnpackIntoInterface(&valSet, method, result)

b: 分配奖励

惩罚和分配奖励是由出块人来做的事情,也就是from是miner,to 是要调用的合约,在finalize阶段会创建,并且在其阶段就会处理完这个交易,直接通过callmsg来生成消息,然后通过applyTransaction底层操作。

// 生成系统交易
	method := "distributeFinalityReward"
	data, err := p.validatorSetABI.Pack(method, validators, weights)
	if err != nil {
		log.Error("Unable to pack tx for distributeFinalityReward", "error", err)
		return err
	}
	msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.ValidatorContract), data, common.Big0)
	return p.applyTransaction(msg, state, header, cx, txs, receipts, systemTxs, usedGas, mining)
 

quorum

预编译合约

以太坊的预编译合约不需要部署到以太坊上,因为它们已经作为区块链客户端(如 geth 或 OpenEthereum)的一部分实现。预编译合约主要用于处理复杂的计算,如加密哈希函数、椭圆曲线签名验证等,它们的地址是预先定义的,通常是较低的地址。

这些预编译合约的主要目的是提高某些计算密集型操作的性能。它们是在客户端的底层代码中实现的,而不是智能合约字节码。当 EVM 遇到一个预编译合约的地址时,它将直接调用相应的底层代码实现,而不是执行合约字节码。这样可以显著提高这些操作的执行速度。

原理:

生成的EVM指令中,Solidity编译器会将预编译合约ecrecover的地址(0x1)作为目标地址。接着,在EVM执行STATICCALL指令时,它会检查这个目标地址并发现它对应一个预编译合约,然后调用相应的底层实现

自定义预编译合约