func (blockchain *blockchain) addPersistenceChangesForNewBlock(ctx context.Context, block *protos.Block, stateHash []byte, writeBatch *gorocksdb.WriteBatch) (uint64, error) { block = blockchain.buildBlock(block, stateHash) if block.NonHashData == nil { block.NonHashData = &protos.NonHashData{LocalLedgerCommitTimestamp: util.CreateUtcTimestamp()} } else { block.NonHashData.LocalLedgerCommitTimestamp = util.CreateUtcTimestamp() } blockNumber := blockchain.size blockHash, err := block.GetHash() if err != nil { return 0, err } blockBytes, blockBytesErr := block.Bytes() if blockBytesErr != nil { return 0, blockBytesErr } writeBatch.PutCF(db.GetDBHandle().BlockchainCF, encodeBlockNumberDBKey(blockNumber), blockBytes) writeBatch.PutCF(db.GetDBHandle().BlockchainCF, blockCountKey, encodeUint64(blockNumber+1)) if blockchain.indexer.isSynchronous() { blockchain.indexer.createIndexesSync(block, blockNumber, blockHash, writeBatch) } blockchain.lastProcessedBlock = &lastProcessedBlock{block, blockNumber, blockHash} return blockNumber, nil }
func TestBlockNonHashData(t *testing.T) { block1 := NewBlock(nil, nil) block2 := NewBlock(nil, nil) time1 := util.CreateUtcTimestamp() time.Sleep(100 * time.Millisecond) time2 := util.CreateUtcTimestamp() block1.NonHashData = &NonHashData{LocalLedgerCommitTimestamp: time1} block2.NonHashData = &NonHashData{LocalLedgerCommitTimestamp: time2} hash1, err := block1.GetHash() if err != nil { t.Fatalf("Error generating block1 hash: %s", err) } hash2, err := block2.GetHash() if err != nil { t.Fatalf("Error generating block2 hash: %s", err) } if bytes.Compare(hash1, hash2) != 0 { t.Fatalf("Expected block hashes to be equal, but there were not") } if time1 != block1.NonHashData.LocalLedgerCommitTimestamp { t.Fatalf("Expected time1 and block1 times to be equal, but there were not") } if time2 != block2.NonHashData.LocalLedgerCommitTimestamp { t.Fatalf("Expected time2 and block2 times to be equal, but there were not") } }
// NewChaincodeDeployTransaction is used to deploy chaincode. func NewChaincodeDeployTransaction(chaincodeDeploymentSpec *ChaincodeDeploymentSpec, uuid string) (*Transaction, error) { transaction := new(Transaction) transaction.Type = Transaction_CHAINCODE_DEPLOY transaction.Uuid = uuid transaction.Timestamp = util.CreateUtcTimestamp() cID := chaincodeDeploymentSpec.ChaincodeSpec.GetChaincodeID() if cID != nil { data, err := proto.Marshal(cID) if err != nil { return nil, fmt.Errorf("Could not marshal chaincode : %s", err) } transaction.ChaincodeID = data } //if chaincodeDeploymentSpec.ChaincodeSpec.GetCtorMsg() != nil { // transaction.Function = chaincodeDeploymentSpec.ChaincodeSpec.GetCtorMsg().Function // transaction.Args = chaincodeDeploymentSpec.ChaincodeSpec.GetCtorMsg().Args //} data, err := proto.Marshal(chaincodeDeploymentSpec) if err != nil { logger.Errorf("Error mashalling payload for chaincode deployment: %s", err) return nil, fmt.Errorf("Could not marshal payload for chaincode deployment: %s", err) } transaction.Payload = data return transaction, nil }
// NewTransaction creates a new transaction. It defines the function to call, // the chaincodeID on which the function should be called, and the arguments // string. The arguments could be a string of JSON, but there is no strict // requirement. func NewTransaction(chaincodeID ChaincodeID, uuid string, function string, arguments []string) (*Transaction, error) { data, err := proto.Marshal(&chaincodeID) if err != nil { return nil, fmt.Errorf("Could not marshal chaincode : %s", err) } transaction := new(Transaction) transaction.ChaincodeID = data transaction.Uuid = uuid transaction.Timestamp = util.CreateUtcTimestamp() /* // Build the spec spec := &pb.ChaincodeSpec{Type: pb.ChaincodeSpec_GOLANG, ChaincodeID: chaincodeID, ChaincodeInput: &pb.ChaincodeInput{Function: function, Args: arguments}} // Build the ChaincodeInvocationSpec message invocation := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec} data, err := proto.Marshal(invocation) if err != nil { return nil, fmt.Errorf("Could not marshal payload for chaincode invocation: %s", err) } transaction.Payload = data */ return transaction, nil }
func (i *Noops) notifyBlockAdded(block *pb.Block, delta *statemgmt.StateDelta) error { //make Payload nil to reduce block size.. //anything else to remove .. do we need StateDelta ? for _, tx := range block.Transactions { tx.Payload = nil } data, err := proto.Marshal(&pb.BlockState{Block: block, StateDelta: delta.Marshal()}) if err != nil { return fmt.Errorf("Fail to marshall BlockState structure: %v", err) } if logger.IsEnabledFor(logging.DEBUG) { logger.Debug("Broadcasting Message_SYNC_BLOCK_ADDED to non-validators") } // Broadcast SYNC_BLOCK_ADDED to connected NVPs // VPs already know about this newly added block since they participate // in the execution. That is, they can compare their current block with // the network block msg := &pb.Message{Type: pb.Message_SYNC_BLOCK_ADDED, Payload: data, Timestamp: util.CreateUtcTimestamp()} if errs := i.stack.Broadcast(msg, pb.PeerEndpoint_NON_VALIDATOR); nil != errs { return fmt.Errorf("Failed to broadcast with errors: %v", errs) } return nil }
func (i *Noops) processTransactions() error { timestamp := util.CreateUtcTimestamp() if logger.IsEnabledFor(logging.DEBUG) { logger.Debugf("Starting TX batch with timestamp: %v", timestamp) } if err := i.stack.BeginTxBatch(timestamp); err != nil { return err } // Grab all transactions from the FIFO queue and run them in order txarr := i.txQ.getTXs() if logger.IsEnabledFor(logging.DEBUG) { logger.Debugf("Executing batch of %d transactions with timestamp %v", len(txarr), timestamp) } _, err := i.stack.ExecTxs(timestamp, txarr) //consensus does not need to understand transaction errors, errors here are //actual ledger errors, and often irrecoverable if err != nil { logger.Debugf("Rolling back TX batch with timestamp: %v", timestamp) i.stack.RollbackTxBatch(timestamp) return fmt.Errorf("Fail to execute transactions: %v", err) } if logger.IsEnabledFor(logging.DEBUG) { logger.Debugf("Committing TX batch with timestamp: %v", timestamp) } if _, err := i.stack.CommitTxBatch(timestamp, nil); err != nil { logger.Debugf("Rolling back TX batch with timestamp: %v", timestamp) i.stack.RollbackTxBatch(timestamp) return err } return nil }
// sendTransactionsToLocalEngine send the transaction to the local engine (This Peer is a validator) func (p *PeerImpl) sendTransactionsToLocalEngine(transaction *pb.Transaction) *pb.Response { peerLogger.Debugf("Marshalling transaction %s to send to local engine", transaction.Type) data, err := proto.Marshal(transaction) if err != nil { return &pb.Response{Status: pb.Response_FAILURE, Msg: []byte(fmt.Sprintf("Error sending transaction to local engine: %s", err))} } var response *pb.Response msg := &pb.Message{Type: pb.Message_CHAIN_TRANSACTION, Payload: data, Timestamp: util.CreateUtcTimestamp()} peerLogger.Debugf("Sending message %s with timestamp %v to local engine", msg.Type, msg.Timestamp) response = p.engine.ProcessTransactionMsg(msg, transaction) return response }
func TestBlockchainBlockLedgerCommitTimestamp(t *testing.T) { testDBWrapper.CleanDB(t) blockchainTestWrapper := newTestBlockchainWrapper(t) block1 := protos.NewBlock(nil, nil) startTime := util.CreateUtcTimestamp() time.Sleep(2 * time.Second) blockchainTestWrapper.addNewBlock(block1, []byte("stateHash1")) lastBlock := blockchainTestWrapper.getLastBlock() if lastBlock.NonHashData == nil { t.Fatal("Expected block to have non-hash-data, but it was nil") } if lastBlock.NonHashData.LocalLedgerCommitTimestamp == nil { t.Fatal("Expected block to have non-hash-data timestamp, but it was nil") } if startTime.Seconds >= lastBlock.NonHashData.LocalLedgerCommitTimestamp.Seconds { t.Fatal("Expected block time to be after start time") } }
// NewChaincodeExecute is used to deploy chaincode. func NewChaincodeExecute(chaincodeInvocationSpec *ChaincodeInvocationSpec, uuid string, typ Transaction_Type) (*Transaction, error) { transaction := new(Transaction) transaction.Type = typ transaction.Uuid = uuid transaction.Timestamp = util.CreateUtcTimestamp() cID := chaincodeInvocationSpec.ChaincodeSpec.GetChaincodeID() if cID != nil { data, err := proto.Marshal(cID) if err != nil { return nil, fmt.Errorf("Could not marshal chaincode : %s", err) } transaction.ChaincodeID = data } data, err := proto.Marshal(chaincodeInvocationSpec) if err != nil { return nil, fmt.Errorf("Could not marshal payload for chaincode invocation: %s", err) } transaction.Payload = data return transaction, nil }
// NewOpenchainDiscoveryHello constructs a new HelloMessage for sending func (p *PeerImpl) NewOpenchainDiscoveryHello() (*pb.Message, error) { helloMessage, err := p.newHelloMessage() if err != nil { return nil, fmt.Errorf("Error getting new HelloMessage: %s", err) } data, err := proto.Marshal(helloMessage) if err != nil { return nil, fmt.Errorf("Error marshalling HelloMessage: %s", err) } // Need to sign the Discovery Hello message newDiscoveryHelloMsg := &pb.Message{Type: pb.Message_DISC_HELLO, Payload: data, Timestamp: util.CreateUtcTimestamp()} err = p.signMessageMutating(newDiscoveryHelloMsg) if err != nil { return nil, fmt.Errorf("Error signing new HelloMessage: %s", err) } return newDiscoveryHelloMsg, nil }