Example #1
0
// getAccountIDsFromAttribute retrieves account IDs stored in  TCert attributes
// cert: TCert to read account IDs from
// attributeNames: attribute names inside TCert that stores the entity's account IDs
func (t *certHandler) getAccountIDsFromAttribute(cert []byte, attributeNames []string) ([]string, error) {
	if cert == nil || attributeNames == nil {
		return nil, errors.New("cert or accountIDs list is empty")
	}

	//decleare return object (slice of account IDs)
	var acctIds []string

	// for each attribute name, look for that attribute name inside TCert,
	// the correspounding value of that attribute is the account ID
	for _, attributeName := range attributeNames {
		myLogger.Debugf("get value from attribute = v%", attributeName)
		//get the attribute value from the corresbonding attribute name
		accountID, err := attr.GetValueFrom(attributeName, cert)
		if err != nil {
			myLogger.Errorf("system error %v", err)
			return nil, errors.New("unable to find user contact information")
		}

		acctIds = append(acctIds, string(accountID))
	}

	myLogger.Debugf("ids = %v", acctIds)
	return acctIds, nil
}
func (t *AssetManagementChaincode) assign(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	fmt.Println("Assigning Asset...")

	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting 2")
	}

	asset := args[0]
	owner, err := base64.StdEncoding.DecodeString(args[1])
	if err != nil {
		fmt.Printf("Error decoding [%v] \n", err)
		return nil, errors.New("Failed decodinf owner")
	}

	// Recover the role that is allowed to make assignments
	assignerRole, err := stub.GetState("assignerRole")
	if err != nil {
		fmt.Printf("Error getting role [%v] \n", err)
		return nil, errors.New("Failed fetching assigner role")
	}

	callerRole, err := stub.ReadCertAttribute("role")
	if err != nil {
		fmt.Printf("Error reading attribute [%v] \n", err)
		return nil, fmt.Errorf("Failed fetching caller role. Error was [%v]", err)
	}

	caller := string(callerRole[:])
	assigner := string(assignerRole[:])

	if caller != assigner {
		fmt.Printf("Caller is not assigner - caller %v assigner %v\n", caller, assigner)
		return nil, fmt.Errorf("The caller does not have the rights to invoke assign. Expected role [%v], caller role [%v]", assigner, caller)
	}

	account, err := attr.GetValueFrom("account", owner)
	if err != nil {
		fmt.Printf("Error reading account [%v] \n", err)
		return nil, fmt.Errorf("Failed fetching recipient account. Error was [%v]", err)
	}

	// Register assignment
	myLogger.Debugf("New owner of [%s] is [% x]", asset, owner)

	ok, err := stub.InsertRow("AssetsOwnership", shim.Row{
		Columns: []*shim.Column{
			&shim.Column{Value: &shim.Column_String_{String_: asset}},
			&shim.Column{Value: &shim.Column_Bytes{Bytes: account}}},
	})

	if !ok && err == nil {
		fmt.Println("Error inserting row")
		return nil, errors.New("Asset was already assigned.")
	}

	return nil, err
}
Example #3
0
// getContactInfo retrieves the contact info stored as an attribute in a Tcert
// cert: TCert
func (t *certHandler) getContactInfo(cert []byte) (string, error) {
	if len(cert) == 0 {
		return "", errors.New("cert is empty")
	}

	contactInfo, err := attr.GetValueFrom(contactInfo, cert)
	if err != nil {
		myLogger.Errorf("system error %v", err)
		return "", errors.New("unable to find user contact information")
	}

	return string(contactInfo), err
}
func (t *AssetManagementChaincode) transfer(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting 2")
	}

	asset := args[0]

	newOwner, err := base64.StdEncoding.DecodeString(args[1])
	if err != nil {
		fmt.Printf("Error decoding [%v] \n", err)
		return nil, errors.New("Failed decoding owner")
	}

	// Verify the identity of the caller
	// Only the owner can transfer one of his assets
	var columns []shim.Column
	col1 := shim.Column{Value: &shim.Column_String_{String_: asset}}
	columns = append(columns, col1)

	row, err := stub.GetRow("AssetsOwnership", columns)
	if err != nil {
		return nil, fmt.Errorf("Failed retrieving asset [%s]: [%s]", asset, err)
	}

	prvOwner := row.Columns[1].GetBytes()
	myLogger.Debugf("Previous owener of [%s] is [% x]", asset, prvOwner)
	if len(prvOwner) == 0 {
		return nil, fmt.Errorf("Invalid previous owner. Nil")
	}

	// Verify ownership
	callerAccount, err := stub.ReadCertAttribute("account")
	if err != nil {
		return nil, fmt.Errorf("Failed fetching caller account. Error was [%v]", err)
	}

	if bytes.Compare(prvOwner, callerAccount) != 0 {
		return nil, fmt.Errorf("Failed verifying caller ownership.")
	}

	newOwnerAccount, err := attr.GetValueFrom("account", newOwner)
	if err != nil {
		return nil, fmt.Errorf("Failed fetching new owner account. Error was [%v]", err)
	}

	// At this point, the proof of ownership is valid, then register transfer
	err = stub.DeleteRow(
		"AssetsOwnership",
		[]shim.Column{shim.Column{Value: &shim.Column_String_{String_: asset}}},
	)
	if err != nil {
		return nil, errors.New("Failed deliting row.")
	}

	_, err = stub.InsertRow(
		"AssetsOwnership",
		shim.Row{
			Columns: []*shim.Column{
				&shim.Column{Value: &shim.Column_String_{String_: asset}},
				&shim.Column{Value: &shim.Column_Bytes{Bytes: newOwnerAccount}},
			},
		})
	if err != nil {
		return nil, errors.New("Failed inserting row.")
	}

	return nil, nil
}
func TestAssetManagement(t *testing.T) {
	// Administrator deploy the chaicode
	adminCert, err := administrator.GetTCertificateHandlerNext("role")
	if err != nil {
		t.Fatal(err)
	}

	if err := deploy(adminCert); err != nil {
		t.Fatal(err)
	}

	// Administrator assigns ownership of Picasso to Alice
	aliceCert, err := alice.GetTCertificateHandlerNext("role", "account")
	if err != nil {
		t.Fatal(err)
	}

	// This must fail
	if err := assignOwnership(alice, "Picasso", aliceCert); err == nil {
		t.Fatal("Alice doesn't have the assigner role. Assignment should fail.")
	}

	// This must succeed
	if err := assignOwnership(administrator, "Picasso", aliceCert); err != nil {
		t.Fatal(err)
	}

	// Check who is the owner of the Picasso
	theOnwerIs, err := whoIsTheOwner("Picasso")
	if err != nil {
		t.Fatal(err)
	}

	aliceAccount, err := attr.GetValueFrom("account", aliceCert.GetCertificate())
	if !reflect.DeepEqual(theOnwerIs, aliceAccount) {
		fmt.Printf("%v --- %v", string(theOnwerIs), string(aliceAccount))
		t.Fatal("Alice is not the owner of Picasso")
	}

	// Alice transfers ownership of Picasso to Bob
	bobCert, err := bob.GetTCertificateHandlerNext("role", "account")
	if err != nil {
		t.Fatal(err)
	}

	// This must fail
	if err := transferOwnership(bob, bobCert, "Picasso", adminCert); err == nil {
		t.Fatal(err)
	}

	// This must succeed
	if err := transferOwnership(alice, aliceCert, "Picasso", bobCert); err != nil {
		t.Fatal(err)
	}

	// Check who is the owner of the Picasso
	theOnwerIs, err = whoIsTheOwner("Picasso")
	if err != nil {
		t.Fatal(err)
	}

	bobAccount, err := attr.GetValueFrom("account", bobCert.GetCertificate())
	if err != nil {
		t.Fatal(err)
	}

	if !reflect.DeepEqual(theOnwerIs, bobAccount) {
		t.Fatal("Bob is not the owner of Picasso")
	}

	// Check who is the owner of an asset that doesn't exist
	_, err = whoIsTheOwner("Klee")
	if err == nil {
		t.Fatal("This asset doesn't exist. Querying should fail.")
	}
}
//test the ability to transfer assets from owner account IDs to new owner account ID
func TestAssetTransfer(t *testing.T) {

	//test transfer
	// create a new cert for alice used to transfer assets
	// (note this cert include multiple account Ids belong to alice)
	aliceCert, err := alice.GetTCertificateHandlerNext("role", "account1", "account2", "account3")
	if err != nil {
		t.Fatal(err)
	}

	// create a new cert for bob to recieve transfer from Alice
	// note "account2" is a new account ID that was never used before. Since this new account ID
	// will create a new record on the account ledger, you must also pass in all required parameters
	// required to create a new account record in chaincode state (such as user contact info)
	bobCert, err := bob.GetTCertificateHandlerNext("role", "account2", "contactInfo")
	if err != nil {
		t.Fatal(err)
	}

	//transfer 200 assets from Alice to Bob
	if nil != transferOwnership(alice, aliceCert, "account1,account2,account3", bobCert, "account2", "200") {
		t.Fatal(err)
	}

	/***********************
		Codes below check if assets are correctly transfered, first find the actual
		account IDs from cert attributes, then call the getBalance method on the
		chaincode for each account ID
	***********************/

	// check that 200 assets have been transfered to Bob; first step is to collect account Ids
	aliceAccountID1, err := attr.GetValueFrom("account1", aliceCert.GetCertificate())
	aliceAccountID2, err := attr.GetValueFrom("account2", aliceCert.GetCertificate())
	aliceAccountID3, err := attr.GetValueFrom("account3", aliceCert.GetCertificate())
	bobAccountID2, err := attr.GetValueFrom("account2", bobCert.GetCertificate())

	//account1 of alice shouldn't have any balance left, and the account should have been
	//deleted from the asset depository
	alice1BalanceRaw, err := getBalance(string(aliceAccountID1))
	fmt.Println("alice balance", alice1BalanceRaw)

	if alice1BalanceRaw != nil {
		t.Fatal(err)
	}
	fmt.Println("alice balance", alice1BalanceRaw)

	// account2 of alice should still have 100 left on its balance
	alice2BalanceRaw, err := getBalance(string(aliceAccountID2))
	if err != nil {
		t.Fatal(err)
	}

	alicebalance2 := binary.BigEndian.Uint64(alice2BalanceRaw)
	if alicebalance2 != 100 {
		t.Fatal("retreived balance for account1 (alice) does not equal to 100")
	}

	// account3 of alice should still have 300 left on its balance
	alice3BalanceRaw, err := getBalance(string(aliceAccountID3))
	if err != nil {
		t.Fatal(err)
	}

	alicebalance3 := binary.BigEndian.Uint64(alice3BalanceRaw)
	if alicebalance3 != 300 {
		t.Fatal("retreived balance for account1 (alice) does not equal to 300")
	}

	// account2 of bob should now have 200 on its balance
	bobBalanceRaw, err := getBalance(string(bobAccountID2))
	if err != nil {
		t.Fatal(err)
	}

	bobbalance := binary.BigEndian.Uint64(bobBalanceRaw)
	if bobbalance != 200 {
		t.Fatal("retreived balance for account2 (bob) does not equal to 200")
	}

}
// TestAssigningAssets the tests the ```assign``` method by making sure
// authorized users (callers with 'issuer' role) can use the ```assign```
// method to allocate assets to its investors
func TestAssigningAssets(t *testing.T) {

	// create certs carring account IDs for Alice and Bob
	aliceCert1, err := alice.GetTCertificateHandlerNext("role", "account1", "contactInfo")
	if err != nil {
		t.Fatal(err)
	}

	aliceCert2, err := alice.GetTCertificateHandlerNext("role", "account2", "contactInfo")
	if err != nil {
		t.Fatal(err)
	}

	aliceCert3, err := alice.GetTCertificateHandlerNext("role", "account3", "contactInfo")
	if err != nil {
		t.Fatal(err)
	}

	bobCert1, err := bob.GetTCertificateHandlerNext("role", "account1", "contactInfo")
	if err != nil {
		t.Fatal(err)
	}

	//issuer assign balances to assets to first batch of owners
	if err := assignOwnership(administrator, aliceCert1, "account1", "100"); err != nil {
		t.Fatal(err)
	}

	if err := assignOwnership(administrator, aliceCert2, "account2", "200"); err != nil {
		t.Fatal(err)
	}

	if err := assignOwnership(administrator, aliceCert3, "account3", "300"); err != nil {
		t.Fatal(err)
	}

	if err := assignOwnership(administrator, bobCert1, "account1", "1000"); err != nil {
		t.Fatal(err)
	}

	aliceAccountID1, err := attr.GetValueFrom("account1", aliceCert1.GetCertificate())
	aliceAccountID2, err := attr.GetValueFrom("account2", aliceCert2.GetCertificate())
	aliceAccountID3, err := attr.GetValueFrom("account3", aliceCert3.GetCertificate())
	bobAccountID1, err := attr.GetValueFrom("account1", bobCert1.GetCertificate())

	// Check if balances are assigned correctly
	alice1BalanceRaw, err := getBalance(string(aliceAccountID1))
	if err != nil {
		t.Fatal(err)
	}

	alicebalance1 := binary.BigEndian.Uint64(alice1BalanceRaw)
	if alicebalance1 != 100 {
		t.Fatal("retreived balance does not equal to 100")
	}

	alice2BalanceRaw, err := getBalance(string(aliceAccountID2))
	if err != nil {
		t.Fatal(err)
	}

	alicebalance2 := binary.BigEndian.Uint64(alice2BalanceRaw)
	if alicebalance2 != 200 {
		t.Fatal("retreived balance does not equal to 200")
	}

	alice3BalanceRaw, err := getBalance(string(aliceAccountID3))
	if err != nil {
		t.Fatal(err)
	}

	alicebalance3 := binary.BigEndian.Uint64(alice3BalanceRaw)
	if alicebalance3 != 300 {
		t.Fatal("retreived balance does not equal to 300")
	}

	bob1BalanceRaw, err := getBalance(string(bobAccountID1))
	if err != nil {
		t.Fatal(err)
	}

	bobbalance1 := binary.BigEndian.Uint64(bob1BalanceRaw)
	if bobbalance1 != 1000 {
		t.Fatal("retreived balance does not equal to 1000")
	}

	//check if contact info is correctly saved into the chaincode state ledger
	aliceContactInfo, err := getOwnerContactInformation(string(aliceAccountID1))
	if err != nil {
		t.Fatal(err)
	}
	if string(aliceContactInfo) != "*****@*****.**" {
		t.Fatal("retreived contact info does not equal to [email protected]")
	}

	bobContactInfo, err := getOwnerContactInformation(string(bobAccountID1))
	if err != nil {
		t.Fatal(err)
	}

	if string(bobContactInfo) != "*****@*****.**" {
		t.Fatal("retreived contact info does not equal to [email protected]")
	}
}