//ExecuteTransactions - will execute transactions on the array one by one //will return an array of errors one for each transaction. If the execution //succeeded, array element will be nil. returns []byte of state hash or //error func ExecuteTransactions(ctxt context.Context, cname ChainName, xacts []*pb.Transaction) (succeededTXs []*pb.Transaction, stateHash []byte, ccevents []*pb.ChaincodeEvent, txerrs []error, err error) { var chain = GetChain(cname) if chain == nil { // TODO: We should never get here, but otherwise a good reminder to better handle panic(fmt.Sprintf("[ExecuteTransactions]Chain %s not found\n", cname)) } txerrs = make([]error, len(xacts)) ccevents = make([]*pb.ChaincodeEvent, len(xacts)) var succeededTxs = make([]*pb.Transaction, 0) for i, t := range xacts { _, ccevents[i], txerrs[i] = Execute(ctxt, chain, t) if txerrs[i] == nil { succeededTxs = append(succeededTxs, t) } } var lgr *ledger.Ledger lgr, err = ledger.GetLedger() if err == nil { stateHash, err = lgr.GetTempStateHash() } return succeededTxs, stateHash, ccevents, txerrs, err }
// Invoke or query a chaincode. func invoke(ctx context.Context, spec *pb.ChaincodeSpec, typ pb.Transaction_Type) (*pb.ChaincodeEvent, string, []byte, error) { chaincodeInvocationSpec := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec} // Now create the Transactions message and send to Peer. uuid := util.GenerateUUID() var transaction *pb.Transaction var err error transaction, err = pb.NewChaincodeExecute(chaincodeInvocationSpec, uuid, typ) if err != nil { return nil, uuid, nil, fmt.Errorf("Error invoking chaincode: %s ", err) } var retval []byte var execErr error var ccevt *pb.ChaincodeEvent if typ == pb.Transaction_CHAINCODE_QUERY { retval, ccevt, execErr = chaincode.Execute(ctx, chaincode.GetChain(chaincode.DefaultChain), transaction) } else { ledger, _ := ledger.GetLedger() ledger.BeginTxBatch("1") retval, ccevt, execErr = chaincode.Execute(ctx, chaincode.GetChain(chaincode.DefaultChain), transaction) if err != nil { return nil, uuid, nil, fmt.Errorf("Error invoking chaincode: %s ", err) } ledger.CommitTxBatch("1", []*pb.Transaction{transaction}, nil, nil) } return ccevt, uuid, retval, execErr }
// NewPeerWithHandler returns a Peer which uses the supplied handler factory function for creating new handlers on new Chat service invocations. func NewPeerWithEngine(secHelperFunc func() crypto.Peer, engFactory EngineFactory) (peer *PeerImpl, err error) { peer = new(PeerImpl) peer.handlerMap = &handlerMap{m: make(map[pb.PeerID]MessageHandler)} peer.isValidator = ValidatorEnabled() peer.secHelper = secHelperFunc() // Install security object for peer if SecurityEnabled() { if peer.secHelper == nil { return nil, fmt.Errorf("Security helper not provided") } } peer.engine, err = engFactory(peer) if err != nil { return nil, err } peer.handlerFactory = peer.engine.GetHandlerFactory() if peer.handlerFactory == nil { return nil, errors.New("Cannot supply nil handler factory") } ledgerPtr, err := ledger.GetLedger() if err != nil { return nil, fmt.Errorf("Error constructing NewPeerWithHandler: %s", err) } peer.ledgerWrapper = &ledgerWrapper{ledger: ledgerPtr} go peer.chatWithPeer(viper.GetString("peer.discovery.rootnode")) return peer, nil }
// Deploy a chaincode - i.e., build and initialize. func deploy(ctx context.Context, spec *pb.ChaincodeSpec) ([]byte, error) { // First build and get the deployment spec chaincodeDeploymentSpec, err := getDeploymentSpec(ctx, spec) if err != nil { return nil, err } tid := chaincodeDeploymentSpec.ChaincodeSpec.ChaincodeID.Name // Now create the Transactions message and send to Peer. transaction, err := createDeployTransaction(chaincodeDeploymentSpec, tid) if err != nil { return nil, fmt.Errorf("Error deploying chaincode: %s ", err) } ledger, err := ledger.GetLedger() if err != nil { return nil, fmt.Errorf("Failed to get handle to ledger: %s ", err) } ledger.BeginTxBatch("1") b, err := Execute(ctx, GetChain(DefaultChain), transaction) if err != nil { return nil, fmt.Errorf("Error deploying chaincode: %s", err) } ledger.CommitTxBatch("1", []*pb.Transaction{transaction}, nil, nil) return b, err }
// NewPeerWithHandler returns a Peer which uses the supplied handler factory function for creating new handlers on new Chat service invocations. func NewPeerWithHandler(secHelperFunc func() crypto.Peer, handlerFact HandlerFactory, discInstance discovery.Discovery) (*PeerImpl, error) { peer := new(PeerImpl) peer.discoverySvc = discInstance if handlerFact == nil { return nil, errors.New("Cannot supply nil handler factory") } peer.handlerFactory = handlerFact peer.handlerMap = &handlerMap{m: make(map[pb.PeerID]MessageHandler)} peer.secHelper = secHelperFunc() // Install security object for peer if SecurityEnabled() { if peer.secHelper == nil { return nil, fmt.Errorf("Security helper not provided") } } ledgerPtr, err := ledger.GetLedger() if err != nil { return nil, fmt.Errorf("Error constructing NewPeerWithHandler: %s", err) } peer.ledgerWrapper = &ledgerWrapper{ledger: ledgerPtr} peer.chatWithSomePeers(peer.discoverySvc.GetRootNodes()) return peer, nil }
// VerifyBlockchain checks the integrity of the blockchain between indices start and finish, // returning the first block who's PreviousBlockHash field does not match the hash of the previous block func (h *Helper) VerifyBlockchain(start, finish uint64) (uint64, error) { ledger, err := ledger.GetLedger() if err != nil { return finish, fmt.Errorf("Failed to get the ledger :%v", err) } return ledger.VerifyChain(start, finish) }
// GetBlock returns a block from the chain func (h *Helper) GetBlock(blockNumber uint64) (block *pb.Block, err error) { ledger, err := ledger.GetLedger() if err != nil { return nil, fmt.Errorf("Failed to get the ledger :%v", err) } return ledger.GetBlockByNumber(blockNumber) }
func (i *Noops) getBlockData() (*pb.Block, *statemgmt.StateDelta, error) { ledger, err := ledger.GetLedger() if err != nil { return nil, nil, fmt.Errorf("Fail to get the ledger: %v", err) } blockHeight := ledger.GetBlockchainSize() if logger.IsEnabledFor(logging.DEBUG) { logger.Debugf("Preparing to broadcast with block number %v", blockHeight) } block, err := ledger.GetBlockByNumber(blockHeight - 1) if nil != err { return nil, nil, err } //delta, err := ledger.GetStateDeltaBytes(blockHeight) delta, err := ledger.GetStateDelta(blockHeight - 1) if nil != err { return nil, nil, err } if logger.IsEnabledFor(logging.DEBUG) { logger.Debugf("Got the delta state of block number %v", blockHeight) } return block, delta, nil }
func transferOwnership(owner crypto.Client, ownerCert crypto.CertificateHandler, asset string, newOwnerCert crypto.CertificateHandler) error { // Get a transaction handler to be used to submit the execute transaction // and bind the chaincode access control logic using the binding submittingCertHandler, err := owner.GetTCertificateHandlerNext() if err != nil { return err } txHandler, err := submittingCertHandler.GetTransactionHandler() if err != nil { return err } binding, err := txHandler.GetBinding() if err != nil { return err } chaincodeInput := &pb.ChaincodeInput{Function: "transfer", Args: []string{asset, string(newOwnerCert.GetCertificate())}} chaincodeInputRaw, err := proto.Marshal(chaincodeInput) if err != nil { return err } // Access control. Owner signs chaincodeInputRaw || binding to confirm his identity sigma, err := ownerCert.Sign(append(chaincodeInputRaw, binding...)) if err != nil { return err } // Prepare spec and submit spec := &pb.ChaincodeSpec{ Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "mycc"}, CtorMsg: chaincodeInput, Metadata: sigma, // Proof of identity ConfidentialityLevel: pb.ConfidentialityLevel_PUBLIC, } var ctx = context.Background() chaincodeInvocationSpec := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec} tid := chaincodeInvocationSpec.ChaincodeSpec.ChaincodeID.Name // Now create the Transactions message and send to Peer. transaction, err := txHandler.NewChaincodeExecute(chaincodeInvocationSpec, tid) if err != nil { return fmt.Errorf("Error deploying chaincode: %s ", err) } ledger, err := ledger.GetLedger() ledger.BeginTxBatch("1") _, err = chaincode.Execute(ctx, chaincode.GetChain(chaincode.DefaultChain), transaction) if err != nil { return fmt.Errorf("Error deploying chaincode: %s", err) } ledger.CommitTxBatch("1", []*pb.Transaction{transaction}, nil, nil) return err }
// GetCurrentStateHash returns the current/temporary state hash func (h *Helper) GetCurrentStateHash() (stateHash []byte, err error) { ledger, err := ledger.GetLedger() if err != nil { return nil, fmt.Errorf("Failed to get the ledger :%v", err) } return ledger.GetTempStateHash() }
// CommitTxBatch gets invoked when the current transaction-batch needs // to be committed. This function returns successfully iff the // transactions details and state changes (that may have happened // during execution of this transaction-batch) have been committed to // permanent storage. func (h *Helper) CommitTxBatch(id interface{}, metadata []byte) (*pb.Block, error) { ledger, err := ledger.GetLedger() if err != nil { return nil, fmt.Errorf("Failed to get the ledger: %v", err) } // TODO fix this one the ledger has been fixed to implement if err := ledger.CommitTxBatch(id, h.curBatch, h.curBatchErrs, metadata); err != nil { return nil, fmt.Errorf("Failed to commit transaction to the ledger: %v", err) } size := ledger.GetBlockchainSize() defer func() { h.curBatch = nil // TODO, remove after issue 579 h.curBatchErrs = nil // TODO, remove after issue 579 }() block, err := ledger.GetBlockByNumber(size - 1) if err != nil { return nil, fmt.Errorf("Failed to get the block at the head of the chain: %v", err) } logger.Debugf("Committed block with %d transactions, intended to include %d", len(block.Transactions), len(h.curBatch)) return block, nil }
// GetBlockchainSize returns the current size of the blockchain func (h *Helper) GetBlockchainSize() (uint64, error) { ledger, err := ledger.GetLedger() if err != nil { return 0, fmt.Errorf("Failed to get the ledger :%v", err) } return ledger.GetBlockchainSize(), nil }
// EmptyState completely empties the state and prepares it to restore a snapshot func (h *Helper) EmptyState() error { ledger, err := ledger.GetLedger() if err != nil { return fmt.Errorf("Failed to get the ledger :%v", err) } return ledger.DeleteALLStateKeysAndValues() }
func deploy(admCert crypto.CertificateHandler) error { // Prepare the spec. The metadata includes the identity of the administrator spec := &pb.ChaincodeSpec{ Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "mycc"}, CtorMsg: &pb.ChaincodeInput{Args: util.ToChaincodeArgs("init")}, Metadata: admCert.GetCertificate(), ConfidentialityLevel: pb.ConfidentialityLevel_PUBLIC, } // First build and get the deployment spec var ctx = context.Background() chaincodeDeploymentSpec, err := getDeploymentSpec(ctx, spec) if err != nil { return err } tid := chaincodeDeploymentSpec.ChaincodeSpec.ChaincodeID.Name // Now create the Transactions message and send to Peer. transaction, err := administrator.NewChaincodeDeployTransaction(chaincodeDeploymentSpec, tid) if err != nil { return fmt.Errorf("Error deploying chaincode: %s ", err) } ledger, err := ledger.GetLedger() ledger.BeginTxBatch("1") _, _, err = chaincode.Execute(ctx, chaincode.GetChain(chaincode.DefaultChain), transaction) if err != nil { return fmt.Errorf("Error deploying chaincode: %s", err) } ledger.CommitTxBatch("1", []*pb.Transaction{transaction}, nil, nil) return err }
// RollbackStateDelta undoes the results of ApplyStateDelta to revert // the current state back to the state before ApplyStateDelta was invoked func (h *Helper) RollbackStateDelta(id interface{}) error { ledger, err := ledger.GetLedger() if err != nil { return fmt.Errorf("Failed to get the ledger :%v", err) } return ledger.RollbackStateDelta(id) }
// ApplyStateDelta applies a state delta to the current state // The result of this function can be retrieved using GetCurrentStateDelta // To commit the result, call CommitStateDelta, or to roll it back // call RollbackStateDelta func (h *Helper) ApplyStateDelta(id interface{}, delta *statemgmt.StateDelta) error { ledger, err := ledger.GetLedger() if err != nil { return fmt.Errorf("Failed to get the ledger :%v", err) } return ledger.ApplyStateDelta(id, delta) }
// PutBlock inserts a raw block into the blockchain at the specified index, nearly no error checking is performed func (h *Helper) PutBlock(blockNumber uint64, block *pb.Block) error { ledger, err := ledger.GetLedger() if err != nil { return fmt.Errorf("Failed to get the ledger :%v", err) } return ledger.PutRawBlock(block, blockNumber) }
func whoIsTheOwner(asset string) ([]byte, error) { chaincodeInput := &pb.ChaincodeInput{Args: util.ToChaincodeArgs("query", asset)} // Prepare spec and submit spec := &pb.ChaincodeSpec{ Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "mycc"}, CtorMsg: chaincodeInput, ConfidentialityLevel: pb.ConfidentialityLevel_PUBLIC, } var ctx = context.Background() chaincodeInvocationSpec := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec} tid := chaincodeInvocationSpec.ChaincodeSpec.ChaincodeID.Name // Now create the Transactions message and send to Peer. transaction, err := administrator.NewChaincodeQuery(chaincodeInvocationSpec, tid) if err != nil { return nil, fmt.Errorf("Error deploying chaincode: %s ", err) } ledger, err := ledger.GetLedger() ledger.BeginTxBatch("1") result, _, err := chaincode.Execute(ctx, chaincode.GetChain(chaincode.DefaultChain), transaction) if err != nil { return nil, fmt.Errorf("Error deploying chaincode: %s", err) } ledger.CommitTxBatch("1", []*pb.Transaction{transaction}, nil, nil) return result, err }
func (t *SystemChaincode) getLedger() ledgerHandler { if t.mockLedgerH == nil { lh, err := ld.GetLedger() if err == nil { return lh } panic("Chaincode is unable to get the ledger.") } else { return t.mockLedgerH } }
// RollbackTxBatch discards all the state changes that may have taken // place during the execution of current transaction-batch func (h *Helper) RollbackTxBatch(id interface{}) error { ledger, err := ledger.GetLedger() if err != nil { return fmt.Errorf("Failed to get the ledger: %v", err) } if err := ledger.RollbackTxBatch(id); err != nil { return fmt.Errorf("Failed to rollback transaction with the ledger: %v", err) } h.curBatch = nil // TODO, remove after issue 579 return nil }
// NewOpenchainServerWithPeerInfo creates a new instance of the ServerOpenchain. func NewOpenchainServerWithPeerInfo(peerServer PeerInfo) (*ServerOpenchain, error) { // Get a handle to the Ledger singleton. ledger, err := ledger.GetLedger() if err != nil { return nil, err } s := &ServerOpenchain{ledger: ledger, peerInfo: peerServer} return s, nil }
// GetBlockHeadMetadata returns metadata from block at the head of the blockchain func (h *Helper) GetBlockHeadMetadata() ([]byte, error) { ledger, err := ledger.GetLedger() if err != nil { return nil, err } head := ledger.GetBlockchainSize() block, err := ledger.GetBlockByNumber(head - 1) if err != nil { return nil, err } return block.ConsensusMetadata, nil }
func transferOwnership(owner crypto.Client, ownerCert crypto.CertificateHandler, fromAttributes string, newOwnerCert crypto.CertificateHandler, toAttributes string, amount string) error { // Get a transaction handler to be used to submit the execute transaction // and bind the chaincode access control logic using the binding submittingCertHandler, err := owner.GetTCertificateHandlerNext("role") if err != nil { return err } txHandler, err := submittingCertHandler.GetTransactionHandler() if err != nil { return err } chaincodeInput := &pb.ChaincodeInput{Args: util.ToChaincodeArgs( "transferOwnership", base64.StdEncoding.EncodeToString(ownerCert.GetCertificate()), fromAttributes, base64.StdEncoding.EncodeToString(newOwnerCert.GetCertificate()), toAttributes, amount)} // Prepare spec and submit spec := &pb.ChaincodeSpec{ Type: 1, ChaincodeID: &pb.ChaincodeID{Name: "mycc"}, CtorMsg: chaincodeInput, ConfidentialityLevel: pb.ConfidentialityLevel_PUBLIC, } var ctx = context.Background() chaincodeInvocationSpec := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec} tid := chaincodeInvocationSpec.ChaincodeSpec.ChaincodeID.Name // Now create the Transactions message and send to Peer. transaction, err := txHandler.NewChaincodeExecute(chaincodeInvocationSpec, tid) if err != nil { return fmt.Errorf("Error deploying chaincode: %s ", err) } ledger, err := ledger.GetLedger() ledger.BeginTxBatch("1") _, _, err = chaincode.Execute(ctx, chaincode.GetChain(chaincode.DefaultChain), transaction) if err != nil { return fmt.Errorf("Error deploying chaincode: %s", err) } ledger.CommitTxBatch("1", []*pb.Transaction{transaction}, nil, nil) return err }
func (validator *validatorImpl) verifyValidityPeriod(tx *obc.Transaction) (*obc.Transaction, error) { if tx.Cert != nil && tx.Signature != nil { // Unmarshal cert cert, err := utils.DERToX509Certificate(tx.Cert) if err != nil { validator.error("verifyValidityPeriod: failed unmarshalling cert %s:", err) return tx, err } cid := viper.GetString("pki.validity-period.chaincodeHash") ledger, err := ledger.GetLedger() if err != nil { validator.error("verifyValidityPeriod: failed getting access to the ledger %s:", err) return tx, err } vpBytes, err := ledger.GetState(cid, "system.validity.period", true) if err != nil { validator.error("verifyValidityPeriod: failed reading validity period from the ledger %s:", err) return tx, err } i, err := strconv.ParseInt(string(vpBytes[:]), 10, 64) if err != nil { validator.error("verifyValidityPeriod: failed to parse validity period %s:", err) return tx, err } vp := time.Unix(i, 0) var errMsg string // Verify the validity period of the TCert switch { case cert.NotAfter.Before(cert.NotBefore): errMsg = "verifyValidityPeriod: certificate validity period is invalid" case vp.Before(cert.NotBefore): errMsg = "verifyValidityPeriod: certificate validity period is in the future" case vp.After(cert.NotAfter): errMsg = "verifyValidityPeriod: certificate validity period is in the past" } if errMsg != "" { validator.error(errMsg) return tx, errors.New(errMsg) } } return tx, nil }
// PreviewCommitTxBatch retrieves a preview of the block info blob (as // returned by GetBlockchainInfoBlob) that would describe the // blockchain if CommitTxBatch were invoked. The blockinfo will // change if additional ExecTXs calls are invoked. func (h *Helper) PreviewCommitTxBatch(id interface{}, metadata []byte) ([]byte, error) { ledger, err := ledger.GetLedger() if err != nil { return nil, fmt.Errorf("Failed to get the ledger: %v", err) } // TODO fix this once the underlying API is fixed blockInfo, err := ledger.GetTXBatchPreviewBlockInfo(id, h.curBatch, metadata) if err != nil { return nil, fmt.Errorf("Failed to preview commit: %v", err) } rawInfo, _ := proto.Marshal(blockInfo) return rawInfo, nil }
// MakeGenesis creates the genesis block and adds it to the blockchain. func MakeGenesis() error { once.Do(func() { ledger, err := ledger.GetLedger() if err != nil { makeGenesisError = err return } if ledger.GetBlockchainSize() == 0 { genesisLogger.Info("Creating genesis block.") if makeGenesisError = ledger.BeginTxBatch(0); makeGenesisError == nil { makeGenesisError = ledger.CommitTxBatch(0, nil, nil, nil) } } }) return makeGenesisError }
//ExecuteTransactions - will execute transactions on the array one by one //will return an array of errors one for each transaction. If the execution //succeeded, array element will be nil. returns state hash func ExecuteTransactions(ctxt context.Context, cname ChainName, xacts []*pb.Transaction) ([]byte, []error) { var chain = GetChain(cname) if chain == nil { // TODO: We should never get here, but otherwise a good reminder to better handle panic(fmt.Sprintf("[ExecuteTransactions]Chain %s not found\n", cname)) } errs := make([]error, len(xacts)+1) for i, t := range xacts { _, errs[i] = Execute(ctxt, chain, t) } ledger, hasherr := ledger.GetLedger() var statehash []byte if hasherr == nil { statehash, hasherr = ledger.GetTempStateHash() } errs[len(errs)-1] = hasherr return statehash, errs }
func deploy2(ctx context.Context, chaincodeDeploymentSpec *pb.ChaincodeDeploymentSpec) ([]byte, error) { tid := chaincodeDeploymentSpec.ChaincodeSpec.ChaincodeID.Name // Now create the Transactions message and send to Peer. transaction, err := createDeployTransaction(chaincodeDeploymentSpec, tid) if err != nil { return nil, fmt.Errorf("Error deploying chaincode: %s ", err) } ledger, err := ledger.GetLedger() ledger.BeginTxBatch("1") b, _, err := Execute(ctx, GetChain(DefaultChain), transaction) if err != nil { return nil, fmt.Errorf("Error deploying chaincode: %s", err) } ledger.CommitTxBatch("1", []*pb.Transaction{transaction}, nil, nil) return b, err }
func getTimeout(cID *pb.ChaincodeID) (time.Duration, error) { ledger, err := ledger.GetLedger() if err == nil { chaincodeID := cID.Name txUUID, err := ledger.GetState(chaincodeID, "github.com_openblockchain_obc-peer_chaincode_id", true) if err == nil { tx, err := ledger.GetTransactionByUUID(string(txUUID)) if err == nil { chaincodeDeploymentSpec := &pb.ChaincodeDeploymentSpec{} proto.Unmarshal(tx.Payload, chaincodeDeploymentSpec) chaincodeSpec := chaincodeDeploymentSpec.GetChaincodeSpec() timeout := time.Duration(time.Duration(chaincodeSpec.Timeout) * time.Millisecond) return timeout, nil } } } return -1, errFailedToGetChainCodeSpecForTransaction }
// CommitTxBatch gets invoked when the current transaction-batch needs // to be committed. This function returns successfully iff the // transactions details and state changes (that may have happened // during execution of this transaction-batch) have been committed to // permanent storage. func (h *Helper) CommitTxBatch(id interface{}, metadata []byte) (*pb.Block, error) { ledger, err := ledger.GetLedger() if err != nil { return nil, fmt.Errorf("Failed to get the ledger: %v", err) } // TODO fix this one the ledger has been fixed to implement if err := ledger.CommitTxBatch(id, h.curBatch, nil, metadata); err != nil { return nil, fmt.Errorf("Failed to commit transaction to the ledger: %v", err) } size := ledger.GetBlockchainSize() h.curBatch = nil // TODO, remove after issue 579 block, err := ledger.GetBlockByNumber(size - 1) if err != nil { return nil, fmt.Errorf("Failed to get the block at the head of the chain: %v", err) } return block, nil }