Azarus - это токенизированная игровая платформа, построенная на EOS. Вступая в этот стек технологий EOS, мы хотели поделиться процессом сборки и открытиями.
Следите за нами в:
web: https://azarus.io
twitter: https : //twitter.com/azarusio
Discord: https://discord.gg/ESma8zx

Как и в любом блокчейне, каждая транзакция, отправляемая узлам, подписывается закрытым ключом вызывающей стороны. Если вы кодировали на Ethereum / Solidity, вам, вероятно, пришлось добавить в свои контракты методы, устанавливающие и обновляющие адреса, которые были бы единственными разрешенными для некоторых критических функций. Одним из таких примеров является аварийный выключатель генерального директора в контрактах с криптокотиками…. который может быть вызван только генеральным директором.

Задачи игры Azarus, называемые внутри «кольцами», предъявляли некоторые особые требования:
* Контракт на кольцо должен иметь возможность получать депозит в монетах AZA и позволять выплату победителю или возмещение, если контракт не выполняется. не выполнено
* Внесенная сумма не должна быть доступна из других колец
* Клиентское приложение Dapp не может выполнять какие-либо операции по переводу монет, кроме внесения первоначальных средств
* Оракул, отвечающий за сообщение результаты игры должны иметь возможность инициировать выплату.
Это похоже на идеальную площадку для проверки нашего понимания схемы авторизации и делегирования EOS.

Подход, который мы использовали, сузился до создания «корзин» для депонирования средств… и обработки этих корзин как учетных записей, а не контрактов, что было бы ожидаемым подходом для других блокчейнов.

Поскольку мы сосредоточены на разрешительной стороне вещей, приведенный ниже код основан на eosjs, и мы проигнорируем фактическое содержание контрактов. Мы также создали прототип, используя монету EOS в качестве хранилища стоимости, в реальной производственной версии мы, очевидно, будем использовать вместо этого токен AZA.

Заключение договоров

Мы начинаем с публикации наших кольцевых контрактов

const eosioTokenClientAccount = await eos.newaccount({
  creator: 'eosio',
  name: eosioToken,
  owner: eosioTokenClientPublic,
  active: eosioTokenClientPublic,
  recovery: 'eosio',
  deposit: '0 EOS'});
const eosioTokenClientContractPath = eosContractsPath + '/eosio.token/eosio.token';
const wast = fs.readFileSync(eosioTokenClientContractPath + '.wast')
const abi = fs.readFileSync(eosioTokenClientContractPath + '.abi')
const actions = await eos.getActions({
  account_name:'eosio',
  pos: -1,
  offset: 0
});
try {
  const res_code = await  eos.setcode(eosioToken, 0, 0, wast);
  const res_abi = await eos.setabi(eosioToken, JSON.parse(abi));
} catch(e) {
  console.log(e);
}
let eosioTokenContract = await eos.contract(eosioToken);

Затем мы создаем набор из 10 корзин в качестве новых учетных записей.

const nbMaxBucket = 10;
var nbBucket = 0;
for (i=1; i<6; i++) {
  for (j=1; j<6; j++) {
  const azaOracleBucket = 'azabucket' + i.toString() + j.toString();
  const azaOracleBucketAccount = await eos.newaccount({
    creator: azaOracle,
    name: azaOracleBucket,
    owner: azaBucketPublic,
    active: azaBucketPublic,
    recovery: azaOracle,
    deposit: '0 EOS'});
  console.log("Account " + azaOracleBucket + " created");
  const bucket_account = await eos.getAccount(azaOracleBucket);
  const permRes = await permission(azaOracle, azaOracleBucket, azaBucketPublic);
  const bucket_account2 = await eos.getAccount(azaOracleBucket);
  nbBucket++;
  if (nbBucket >= nbMaxBucket) {
      break;
    }
  }
  if (nbBucket >= nbMaxBucket) {
      break;
    }
  }
  console.log("Account and Contract created for " + azaOracle);
} catch(err) {
  console.log(err);
}

Авторизация Oracle

Эта следующая часть дает право Оракулу выплатить победителю розыгрыша, в конечном итоге получая доступ к средствам в корзине. Этот вызов должен выполняться из той же учетной записи «владельца», которая создала корзину.

async function permission(delegate, bucketName, publicKey) {
  try {
    const permRes = await eos.updateauth({
      account: bucketName,
      permission: "active",
      parent: "owner",
      data: {
        threshold: 1,
        keys: [{key: publicKey, weight: 1}],
        accounts: [{permission:{ actor:delegate, permission:"active"},    weight:1}]
      },
      delay: 0
    });
    return permRes;
  } catch(e) {
    console.log(e);
    return e;
  }
}

Что действительно примечательно, так это то, что без необходимости предоставлять Oracle доступ к закрытому ключу корзины, мы разрешаем ему доступ как «активному» делегату.

В качестве дополнительной функции вы также можете каскадировать эти авторизации, создавая, например, разрешение «azarus», позволяющее delegate2 также получать доступ к корзине в качестве делегата начальному делегату.

const permRes2 = await eos.updateauth({
  account: bucketName,
  permission: "azarus",
  parent: "active",
  data: {
    threshold: 1,
    keys: [{key: publicKey, weight: 1}],
    accounts: [{permission:{ actor:delegate2, permission:"active"}, weight:1}]
  },
  delay: 0
});

Вращая колеса

Теперь у нас есть корзины, в которые вы можете вносить средства и где Oracle должен иметь возможность инициировать выплату ... давайте сделаем это

Вот как вы можете отправить монеты в ведро - ничего особенного, это простой перевод монет EOS.

const eosioTokenContract = await eos.contract('eosio.token');
const azaOracleBucket = 'azabucket11'
let token_transfer_user = await eosioTokenContract.transfer({
  from: userName,
  to: azaOracleBucket,
  quantity: prize + ' EOS',
  memo: 'deposit'},
  { authorization: userName });
console.log("Payment from " + userName + " TO " + azaOracle + " for " + prize + ' -> OK');

А теперь последний штрих: Оракул вызывает ведро, чтобы приступить к выплате!

const eosioTokenContract = await eos.contract('eosio.token');
const azaOracleBucket = 'azabucket11'
const bucket_account2 = await eos.getAccount(azaOracleBucket);
let token_transfer_user = await eosioTokenContract.transfer({
  from: azaOracleBucket,
  to: beneficiary,
  quantity: 100 + ' EOS',
  memo: 'deposit'},
  { 
    authorization: [{
      actor: azaOracleBucket, permission: 'active',
   }],
  }
);

Здесь Oracle смог перейти к выплате, только вызвав ведро, используя его идентификатор «azaOracleBucket», который ранее был настроен как делегат.

Вот схема архитектуры, которую мы только что собрали, с упором на расположение различных закрытых ключей (pKeys):

Вывод

Впечатляет то, как всего за несколько звонков мы можем создавать учетные записи и разрешать элементам системы взаимодействовать с ней без необходимости раскрывать или передавать их закрытый ключ. В конечном итоге это устраняет большую сложность самих контрактов, которые больше не отвечают за контроль доступа и могут сосредоточиться на обработке транзакционных данных, позволяя инфраструктуре EOS управлять контролем доступа!

Поделитесь своими мыслями и не стесняйтесь оспаривать наш подход - это новая платформа, и мы учимся по мере создания Azarus ... и по мере создания EOS!