Мы разрабатываем защищенную блокчейн-среду с помощью Ethermint. Компании должны подать заявку на присоединение к среде блокчейна, мы создаем и предоставляем им их учетную запись Ethereum.
Одна из основных проблем заключается в том, как удалить или заблокировать учетную запись из среды, если выяснится, что эта компания ведет себя нехорошо.
Мы думали о том, чтобы пометить контракт организации или уничтожить его, но тогда вам придется поместить модификатор почти в каждый метод, И они все еще смогут совершать транзакции со своей учетной записью Ethereum.
Я не уверен, что даже возможно заблокировать такую учетную запись из разрешенной среды блокчейна, потому что, ну, это то, что касается децентрализации, очевидно :-) Но, возможно, здесь есть обходной путь или «шаблон».
На самом деле очень легко сделать.
Эта функция представляет собой единственную запись для изменения балансов в Ethereum ( core/state_transition.go
):
// TransitionDb will transition the state by applying the current message and
// returning the result including the the used gas. It returns an error if it
// failed. An error indicates a consensus issue.
func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bool, err error) {
if err = st.preCheck(); err != nil {
return
}
msg := st.msg
sender := vm.AccountRef(msg.From())
homestead := st.evm.ChainConfig().IsHomestead(st.evm.BlockNumber)
contractCreation := msg.To() == nil
// Pay intrinsic gas
gas, err := IntrinsicGas(st.data, contractCreation, homestead)
if err != nil {
return nil, 0, false, err
}
if err = st.useGas(gas); err != nil {
return nil, 0, false, err
}
var (
evm = st.evm
// vm errors do not effect consensus and are therefor
// not assigned to err, except for insufficient balance
// error.
vmerr error
)
if contractCreation {
ret, _, st.gas, vmerr = evm.Create(sender, st.data, st.gas, st.value)
} else {
// Increment the nonce for the next transaction
st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)
ret, st.gas, vmerr = evm.Call(sender, st.to(), st.data, st.gas, st.value)
}
if vmerr != nil {
log.Debug("VM returned with error", "err", vmerr)
// The only possible consensus-error would be if there wasn't
// sufficient balance to make the transfer happen. The first
// balance transfer may never fail.
if vmerr == vm.ErrInsufficientBalance {
return nil, 0, false, vmerr
}
}
st.refundGas()
st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
return ret, st.gasUsed(), vmerr != nil, err
}
Вы должны сделать что-то вроде этого:
func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bool, err error) {
if err = st.preCheck(); err != nil {
return
}
msg := st.msg
sender := vm.AccountRef(msg.From())
homestead := st.evm.ChainConfig().IsHomestead(st.evm.BlockNumber)
contractCreation := msg.To() == nil
// here is where your custom code goes:
errAccessDenied:=errors.New("Company isn't playing nice")
blacklisted_address,exists:=blacklists[sender]
if exists {
return ret,0,false, errAccessDenied
}
blacklisted_address,exists=blaclists[st.to()]
if exists {
return ret,0,false,errAccessDenied
}
// here is where your custom code ends
// Pay intrinsic gas
gas, err := IntrinsicGas(st.data, contractCreation, homestead)
if err != nil {
return nil, 0, false, err
}
if err = st.useGas(gas); err != nil {
return nil, 0, false, err
}
var (
evm = st.evm
// vm errors do not effect consensus and are therefor
// not assigned to err, except for insufficient balance
// error.
vmerr error
)
if contractCreation {
ret, _, st.gas, vmerr = evm.Create(sender, st.data, st.gas, st.value)
} else {
// Increment the nonce for the next transaction
st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)
ret, st.gas, vmerr = evm.Call(sender, st.to(), st.data, st.gas, st.value)
}
if vmerr != nil {
log.Debug("VM returned with error", "err", vmerr)
// The only possible consensus-error would be if there wasn't
// sufficient balance to make the transfer happen. The first
// balance transfer may never fail.
if vmerr == vm.ErrInsufficientBalance {
return nil, 0, false, vmerr
}
}
st.refundGas()
st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
return ret, st.gasUsed(), vmerr != nil, err
}
Конечно, это не проверенный код, но вы поняли. Также вы должны включить функцию распределения списка компаний, которые не ладят между узлами. Хэш черного списка должен быть включен в заголовок блока (types.Header)