sendData : ACL付きのファイルを登録

ACL(アクセスコントロール)付きのファイル登録方法について説明します。

API

Z.com Cloud ブロックチェーン / ConoHa ブロックチェーン

処理シーケンス

基本的な処理シーケンスは、ファイル更新処理と同じです。

フローの違いは、登録の場合は対象のキーのデータが登録されて『いる』場合にエラー(400 BadRequest)になり、更新の場合はキーのデータが登録されて『いない』場合にエラー(400 BadRequest)になります。

sendFile SomeContract

  • 1 AltExecCnsContract#sendFile

    クライアントのロジックから、AltExecCnsContractを呼出を行います。

    呼出の際に、最終的に呼び出すコントラクトの「名称」「関数名」「パラメータ」「ファイル名」「保存対象のファイル」なども含めて呼出を行います。

  • 1.1 API POST file

    本サービスが提供するクライアントのモジュールが、すべての引数から導出したハッシュ値に対してサインをした上でAPIの呼出を行います。

  • 1.1.1 ContractNameService#getLatestcontract

    APIサーバが、CNSに最新のバージョンのContractのアドレスを問い合わせます。

  • 1.1.2 checkExistance

    APIサーバが指定されたオブジェクトIDの存在チェックを行います。

    (オブジェクトIDのデータが存在『する』場合にエラー(400 BadRequest))

  • 1.1.3 SomeContract#someMethod

    APIサーバが、エンドユーザの命令通りにコントラクトを呼び出します。

    呼び出しの際に、第2引数が bytes32 : objectId、第3引数が bytes32 : fileNameHash、第4引数が bytes32 : dataHash となります。

    コントラクトのメソッド内で、指定されたオブジェクトIDを元にFileObjectの生成処理を行い、その中でデータのHash値の設定、ファイル名のHash値設定を行います。

    サービスプロバイダのコントラクトだけでは、Hash値の設定は完了せず、この後APIサーバ側のデータ検証完了後のトランザクションによって、Hash値登録が完了します。

    詳細は、FileObjectLogic をご参照ください。

  • 1.1.4 isWriter

    APIサーバ内で、エンドユーザ(のアドレス)が対象のデータに対する書込み権限があるかEthereum上のデータを確認します。

  • 1.1.5 put

    APIサーバが、データストレージ領域に対象のデータの書き込みを行います。

  • 1.1.6 fixData

    APIサーバが、本サービスのキーを用いてHash値のFix処理を行います。

    FileObjectに書込み権限のあるユーザによるHash値書き込み(1.1.3)と、本サービスのキーによるHash値書き込みの両方がない限り、FileObjectのHash値は変更できないようになっています。

    これにより、サービスプロバイダーや本サービスによる一方的なHash値の書き込みを防いでいます。

サービスプロバイダ側の実装内容

フローは多少複雑ですが、サービスプロバイダの実装は非常にシンプルなものになっています。

  • ClientSide

    • AltExecCnsContract#sendFile

      var contract = new AltExecCnsContract(account, '__CNS_ADDRESS__');
      contract.sendFile('__PASSWORD__', 'SomeContract', 'someMethod', '__OBJECT_ID__', 'fileName.png', file, ['p0', 1, 'p2'], abi, function(err, txHash) {
          if (err) console.error(err);
          else console.log(txHash);
      }
      
  • Contract

    • SomeContract

      実装するコントラクトは、エンドユーザが指定した通りのパラメータで呼び出しが行われますが、第2引数が bytes32 : objectId、第3引数が bytes32 : fileNameHash、第4引数が bytes32 : dataHash として渡されます。

      contract SomeContract is VersionContract {
      
          mapping(address => bool) allowUsers;
          ContractNameService constant GMO_CNS = ContractNameService (0x993e5e0dca2d937a2313db2141d4a5abe51d3ed7);
      
          function SomeContract(ContractNameService _cns) VersionContract(_cns, "SomeContract") {}
      
          function someMethod(
                  bytes _sign, 
                  bytes32 _objectId, 
                  bytes32 _fileNameHash, 
                  bytes32 _dataHash, 
                  bytes32 _p0, 
                  uint _p1, 
                  bytes32 _p2) {
      
              // create all parameters hash
              bytes32 hash = calcEnvHash('someMethod');
              hash = sha3(hash, _objectId);
              hash = sha3(hash, _fileNameHash);
              hash = sha3(hash, _dataHash);
              hash = sha3(hash, _p0);
              hash = sha3(hash, _p1);
              hash = sha3(hash, _p2);
              // get end user's addresss
              address endUserAddr = Utils.recoverAddress(hash, _sign);
              if (!allowUsers[endUserAddr]) throw;
      
              // fileobject creation
              FileObject_v1 object = FileObject_v1(GMO_CNS.getLatestContract('FileObject'));
              object.create(_objectId, this, _fileNameHash, _dataHash, cns, 'SomeContract');
              bytes32 readerId = object.getReaderId(_objectId);
              bytes32 writerId = object.getWriterId(_objectId);
      
              // add enduser to reader and writer
              address[] memory userAddrs = new address[](1);
              userAddrs[0] = endUserAddr;
              AddressGroup_v1 addressGroup = AddressGroup_v1(GMO_CNS.getLatestContract('AddressGroup'));
              addressGroup.addMembers(readerId, userAddrs);
              addressGroup.addMembers(writerId, userAddrs);
          }
      }
      

注意点

  • msg.sender

    POST /transaction でのContract関数の呼出は、代払い用のアカウントのサインで行われます。

    msg.senderは、各サービスプロバイダの代払い用のアカウントとなり、本来の呼出元のエンドユーザではありません。

    エンドユーザのサインは、第一引数の、bytes _sign として渡されていて、ここからサインの検証と、エンドユーザのアドレス取得を行います。

  • 実装の簡略化

    上記の例は、要点を説明するため、SomeContractに直接ロジックを実装していますが、実際には 基本コントラクト構成 の形式での実装が必要です。

    本来のContractの実装方法については、下記ソースを参考にしてください。

results matching ""

    No results matching ""