Git Product home page Git Product logo

Comments (6)

shohu avatar shohu commented on August 29, 2024

https://github.com/loucho/hyperledger-fabric/blob/master/fabcar/javascript-low-level/query.js#L23-L28
この辺りにhintが。

以下で実現できてるっぽい

var firstnetwork_path = path.resolve('..', '..', 'first-network');
var org1tlscacert_path = path.resolve(firstnetwork_path, 'crypto-config', 'peerOrganizations', 'org1.example.com', 'tlsca', 'tlsca.org1.example.com-cert.pem');
var org1tlscacert = fs.readFileSync(org1tlscacert_path, 'utf8');
: 
// setup the fabric network
var channel = fabric_client.newChannel('mychannel');
var peer = fabric_client.newPeer('grpcs://localhost:7051', {
	'ssl-target-name-override': 'peer0.org1.example.com',
	pem: org1tlscacert
});
channel.addPeer(peer);

// queryCar chaincode function - requires 1 argument, ex: args: ['CAR4'],
// queryAllCars chaincode function - requires no arguments , ex: args: [''],
const request = {
  //targets : --- letting this default to the peers assigned to the channel
  chaincodeId: 'fabcar',
  fcn: 'queryAllCars',
  args: ['']
};

// send the query proposal to the peer
return channel.queryByChaincode(request);

ただ、以下のように実装しても

    var request = {
        fcn: 'find',
        args: [
            'apart',
            '000001',
        ],
        chaincodeId: 'estate'
    };
    let response_payloads = await channel.queryByChaincode(request);

以下エラー

Error: No identity has been assigned to this client

from estate-sample.

shohu avatar shohu commented on August 29, 2024

以下部分で "No identity has been assigned to this client" を出している。

_getSigningIdentity(admin) {
  logger.debug('_getSigningIdentity - admin parameter is %s :%s', (typeof admin), admin);
  if (admin && this._adminSigningIdentity) {
    return this._adminSigningIdentity;
  } else {
    if (this._userContext) {
      return this._userContext.getSigningIdentity();
    } else {
      throw new Error('No identity has been assigned to this client');
    }
  }
}

user.js

/**
 * Get the {@link SigningIdentity} object for this User instance, used to generate signatures
 * @returns {SigningIdentity} the identity object that encapsulates the user's private key for signing
 */
getSigningIdentity() {
  return this._signingIdentity;
}

queryByChaincode

/**
 * Sends a proposal to one or more endorsing peers that will be handled by the chaincode.
 * There is no difference in how the endorsing peers process a request
 * to invoke a chaincode for transaction vs. to invoke a chaincode for query. All requests
 * will be presented to the target chaincode's 'Invoke' method which must be implemented to
 * understand from the arguments that this is a query request. The chaincode must also return
 * results in the byte array format and the caller will have to be able to decode
 * these results.
 *
 * If the request contains a <code>txId</code> property, that transaction ID will be used, and its administrative
 * privileges will apply. In this case the <code>useAdmin</code> parameter to this function will be ignored.
 *
 * @param {ChaincodeQueryRequest} request
 * @param {boolean} useAdmin - Optional. Indicates that the admin credentials should be used in making
 *                  this call. Ignored if the <code>request</code> contains a <code>txId</code> property.
 * @returns {Promise} A Promise for an array of byte array results returned from the chaincode
 *                    on all Endorsing Peers
 * @example
 * <caption>Get the list of query results returned by the chaincode</caption>
 * const responsePayloads = await channel.queryByChaincode(request);
 * for (let i = 0; i < responsePayloads.length; i++) {
 *     console.log(util.format('Query result from peer [%s]: %s', i, responsePayloads[i].toString('utf8')));
 * }
 */
async queryByChaincode(request, useAdmin) {
  logger.debug('queryByChaincode - start');
  if (!request) {
    throw new Error('Missing request object for this queryByChaincode call.');
  }

  if (request.txId) {
    useAdmin = request.txId.isAdmin();
  }

  const targets = this._getTargets(request.targets, Constants.NetworkConfig.CHAINCODE_QUERY_ROLE);
  const signer = this._clientContext._getSigningIdentity(useAdmin);
  const txId = request.txId || new TransactionID(signer, useAdmin);

const proposalResults = await Channel.sendTransactionProposal(query_request, this._name, this._clientContext, request.request_timeout);
  const responses = proposalResults[0];
  logger.debug('queryByChaincode - results received');

  if (!responses || !Array.isArray(responses)) {
    throw new Error('Payload results are missing from the chaincode query');
  }

  const results = [];
  responses.forEach((response) => {
    if (response instanceof Error) {
      results.push(response);
    } else if (response.response && response.response.payload) {
      if (response.response.status === 200) {
        results.push(response.response.payload);
      } else {
        if (response.response.message) {
          results.push(new Error(response.response.message));
        } else {
          results.push(new Error(response));
        }
      }
    } else {
      logger.error('queryByChaincode - unknown or missing results in query ::' + results);
      results.push(new Error(response));
    }
  });

  return results;
/*
 * Internal static method to allow transaction proposals to be called without
 * creating a new channel
 */
static async sendTransactionProposal(request, channelId, client_context, timeout) {
  const method = 'sendTransactionProposal(static)';
  logger.debug('%s - start', method);

  let errorMsg = client_utils.checkProposalRequest(request, true);

  if (errorMsg) {
    // do nothing so we skip the rest of the checks
  } else if (!request.args) {
    // args is not optional because we need for transaction to execute
    errorMsg = 'Missing "args" in Transaction proposal request';
  } else if (!request.targets || request.targets.length < 1) {
    errorMsg = 'Missing peer objects in Transaction proposal';
  }

  if (errorMsg) {
    logger.error('%s error %s', method, errorMsg);
    throw new Error(errorMsg);
  }

  const proposal = Channel._buildSignedProposal(request, channelId, client_context);

  const responses = await client_utils.sendPeersProposal(request.targets, proposal.signed, timeout);
  return [responses, proposal.source];
}

adminで実行してしまうとまずいので、_userContext があればいいと。
_userContext が設定されている箇所は以下

/**
 * Sets an instance of the {@link User} class as the security context of this client instance. This user’s
 * signing identity (the private key and its corresponding certificate), will be used to sign all requests
 * with the fabric backend.
 * <br><br>
 * Upon setting the user context, the SDK saves the object in a persistence cache if the “state store”
 * has been set on the Client instance. If no state store has been set, this cache will not be established
 * and the application is responsible for setting the user context again if the application crashes and is recovered.
 *
 * @param {User | UserNamePasswordObject} user - An instance of the User class encapsulating the authenticated
 *                      user’s signing materials (private key and enrollment certificate).
 *                      The parameter may also be a {@link UserNamePasswordObject} that contains the username
 *                      and optionally the password and caName. A common connection profile must has been loaded to use the
 *                      {@link UserNamePasswordObject} which will also create the user context and set it on
 *                      this client instance. The created user context will be based on the current network
 *                      configuration( i.e. the current organization's CA, current persistence stores).
 * @param {boolean} skipPersistence - Whether to skip saving the user object into persistence. Default is false and the
 *                                    method will attempt to save the user object to the state store. When using a
 *                                    common connection profile and {@link UserNamePasswordObject}, the user object will
 *                                    always be stored to the persistence store.
 * @returns {Promise} Promise of the 'user' object upon successful persistence of the user to the state store
 */
async setUserContext(user, skipPersistence) {
  logger.debug(`setUserContext - user: ${user}, skipPersistence: ${skipPersistence}`);
  if (!user) {
    logger.debug('setUserContext, Cannot save null userContext.');
    throw new Error('Cannot save null userContext.');
  }

  if (user && user.constructor && user.constructor.name === 'User') {
    this._userContext = user;
    if (!skipPersistence) {
      logger.debug('setUserContext - begin promise to saveUserToStateStore');
      return this.saveUserToStateStore();
    }
    logger.debug('setUserContext - resolved user');
    return user;
  }
  // must be they have passed in an object
  logger.debug('setUserContext - will try to use common connection profile to set the user');
  return this._setUserFromConfig(user);
}

from estate-sample.

shohu avatar shohu commented on August 29, 2024

以下作ってみたが相変わらず "Error: No identity has been assigned to this client"

    const testclient = new Client();
    var testchannel = testclient.newChannel('mychannel');
    const peerTLSCertPath = path.resolve(
        __dirname,
        '../../first-network/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp/tlscacerts/tlsca.org1.example.com-cert.pem'
    )
    const peerPEMCert = fs.readFileSync(peerTLSCertPath, 'utf8')
    const peer = testclient.newPeer('grpcs://localhost:7051', {
        pem: peerPEMCert,
        'ssl-target-name-override': 'peer0.org1.example.com'
    })
    testchannel.addPeer(peer);

    const request = {
        fcn: 'find',
        args: [
            'apart',
            '000001',
        ],
        chaincodeId: 'estate'
    };
    let response = await testchannel.queryByChaincode(request);
    console.log('evaluteTest ====== ', response);

やはり、setUserContext を作る必要がある。
ただ、setUserContext には以下のように password 渡すことになるから、サーバー側にpassword渡ってしまう?

client.setUserContext({username:'user1', password:secret});

from estate-sample.

shohu avatar shohu commented on August 29, 2024

fabcarでqueryByChaincodeを試してみる

動かす

$ ./startFabric.sh javascript
$ cd javascript-low-level/
$ npm install
$ node enrollAdmin.js
 Store path:/Users/shohu33/sc/estate-sample/fabcar/javascript-low-level/hfc-key-store
Successfully enrolled admin user "admin"
Assigned the admin user to the fabric client ::{"name":"admin","mspid":"Org1MSP","roles":null,"affiliation":"","enrollmentSecret":"","enrollment":{"signingIdentity":"7d25ef56083b2cb85cef53ae1352283b613ca19006953a81a17f9e8f3c3e0707","identity":{"certificate":"-----BEGIN CERTIFICATE-----\nMIICAjCCAaigAwIBAgIUGx1pRPdexcGhZ5GBUxsZzA6AKDcwCgYIKoZIzj0EAwIw\nczELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh\nbiBGcmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMT\nE2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMTkwNjE5MDE1NzAwWhcNMjAwNjE4MDIw\nMjAwWjAhMQ8wDQYDVQQLEwZjbGllbnQxDjAMBgNVBAMTBWFkbWluMFkwEwYHKoZI\nzj0CAQYIKoZIzj0DAQcDQgAE5wyP3hVtaFTYg0fx3IC8d33IDVpUEHw4WwWQO1le\nWrR9O/KxOn2kf5BtVKNPdGAYF2CfmK7+BvBSh8quhzbDjaNsMGowDgYDVR0PAQH/\nBAQDAgeAMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFPPjMBDvuOOQe0Vl+GXxfLez\nTEBSMCsGA1UdIwQkMCKAIBe2+SNa4mfmXrND5Psf5M3vNpBSTZhMQXHBoyyJ8LMJ\nMAoGCCqGSM49BAMCA0gAMEUCIQCKHgLSe2uuBwsXjetoljQjbADSVAcrMOUlxUME\nJLwKPAIgYBKosJojR4awlXj7iAwOUpCQ2e1hl4gnq36Gf376Zqg=\n-----END CERTIFICATE-----\n"}}}
$ node registerUser.js
 Store path:/Users/shohu33/sc/estate-sample/fabcar/javascript-low-level/hfc-key-store
Successfully loaded admin from persistence
Successfully registered user1 - secret:NmrTRXobGVVP
Successfully enrolled member user "user1"
User1 was successfully registered and enrolled and is ready to interact with the fabric network
$ node invoke.js
 --- invoke.js - start
Setting up client side network objects
Created client side object to represent the channel
Created client side object to represent the peer
Setting up the user store at path:/Users/shohu33/sc/estate-sample/fabcar/javascript-low-level/hfc-key-store
Successfully loaded "user1" from user store
Successfully setup client side

Start invoke processing
Used service discovery to initialize the channel

Created a transaction ID: 93b98c97519fcdaa77ad20ddc270d0d6cdc80686abf8fd52d4c55868f1f94903
Successfully sent Proposal and received response: Status - 200
Registered transaction listener with the peer event service for transaction ID:93b98c97519fcdaa77ad20ddc270d0d6cdc80686abf8fd52d4c55868f1f94903
Sending endorsed transaction to the orderer
The transaction has been committed on peer localhost:7051
Successfully sent transaction to the orderer
Successfully committed the change to the ledger by the peer
 - try running "node query.js" to see the results
 --- invoke.js - end

同じ書き方で、以下のようにデータ取得できるんだよな、、、なぞ

$ node query.js
Store path:/Users/shohu33/sc/estate-sample/fabcar/javascript-low-level/hfc-key-store
Successfully loaded user1 from persistence
Query has completed, checking results
Response is  "[{\"Key\":\"CAR0\",\"Record\":{\"color\":\"blue\",\"docType\":\"car\",\"make\":\"Toyota\",\"model\":\"Prius\",\"owner\":\"Tomoko\"}},{\"Key\":\"CAR1\",\"Record\":{\"color\":\"red\",\"docType\":\"car\",\"make\":\"Ford\",\"model\":\"Mustang\",\"owner\":\"Brad\"}},{\"Key\":\"CAR12\",\"Record\":{\"color\":\"Black\",\"docType\":\"car\",\"make\":\"Honda\",\"model\":\"Accord\",\"owner\":\"Tom\"}},{\"Key\":\"CAR2\",\"Record\":{\"color\":\"green\",\"docType\":\"car\",\"make\":\"Hyundai\",\"model\":\"Tucson\",\"owner\":\"Jin Soo\"}},{\"Key\":\"CAR3\",\"Record\":{\"color\":\"yellow\",\"docType\":\"car\",\"make\":\"Volkswagen\",\"model\":\"Passat\",\"owner\":\"Max\"}},{\"Key\":\"CAR4\",\"Record\":{\"color\":\"black\",\"docType\":\"car\",\"make\":\"Tesla\",\"model\":\"S\",\"owner\":\"Adriana\"}},{\"Key\":\"CAR5\",\"Record\":{\"color\":\"purple\",\"docType\":\"car\",\"make\":\"Peugeot\",\"model\":\"205\",\"owner\":\"Michel\"}},{\"Key\":\"CAR6\",\"Record\":{\"color\":\"white\",\"docType\":\"car\",\"make\":\"Chery\",\"model\":\"S22L\",\"owner\":\"Aarav\"}},{\"Key\":\"CAR7\",\"Record\":{\"color\":\"violet\",\"docType\":\"car\",\"make\":\"Fiat\",\"model\":\"Punto\",\"owner\":\"Pari\"}},{\"Key\":\"CAR8\",\"Record\":{\"color\":\"indigo\",\"docType\":\"car\",\"make\":\"Tata\",\"model\":\"Nano\",\"owner\":\"Valeria\"}},{\"Key\":\"CAR9\",\"Record\":{\"color\":\"brown\",\"docType\":\"car\",\"make\":\"Holden\",\"model\":\"Barina\",\"owner\":\"Shotaro\"}}]"

わかった

newDefaultKeyValueStoreとかで前処理やってるのか。これだ。

// create the key value store as defined in the fabric-client/config/default.json 'key-value-store' setting
Fabric_Client.newDefaultKeyValueStore({ path: store_path
}).then((state_store) => {
	// assign the store to the fabric client
	fabric_client.setStateStore(state_store);
	var crypto_suite = Fabric_Client.newCryptoSuite();
	// use the same location for the state store (where the users' certificate are kept)
	// and the crypto store (where the users' keys are kept)
	var crypto_store = Fabric_Client.newCryptoKeyStore({path: store_path});
	crypto_suite.setCryptoKeyStore(crypto_store);
	fabric_client.setCryptoSuite(crypto_suite);

	// get the enrolled user from persistence, this user will sign all requests
	return fabric_client.getUserContext('user1', true);
}).then((user_from_store) => {
	if (user_from_store && user_from_store.isEnrolled()) {
		console.log('Successfully loaded user1 from persistence');
	} else {
		throw new Error('Failed to get user1.... run registerUser.js');
	}

	// queryCar chaincode function - requires 1 argument, ex: args: ['CAR4'],
	// queryAllCars chaincode function - requires no arguments , ex: args: [''],
	const request = {
		//targets : --- letting this default to the peers assigned to the channel
		chaincodeId: 'fabcar',
		fcn: 'queryAllCars',
		args: ['']
	};

	// send the query proposal to the peer
	return channel.queryByChaincode(request);

from estate-sample.

shohu avatar shohu commented on August 29, 2024

queryByChaincode は client. setUserContext つかわなければ access できなさそうで、これは secret をサーバーに通信しなければいけなさそうだから、offlineじゃないっぽい?

from estate-sample.

shohu avatar shohu commented on August 29, 2024

#13 で解決

from estate-sample.

Related Issues (15)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.