github.com/inklabsfoundation/inkchain@v0.17.1-0.20181025012015-c3cef8062f19/orderer/ledger/util.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package ledger 18 19 import ( 20 "github.com/golang/protobuf/proto" 21 "github.com/inklabsfoundation/inkchain/core/wallet" 22 cb "github.com/inklabsfoundation/inkchain/protos/common" 23 ab "github.com/inklabsfoundation/inkchain/protos/orderer" 24 putils "github.com/inklabsfoundation/inkchain/protos/utils" 25 ) 26 27 var closedChan chan struct{} 28 29 func init() { 30 closedChan = make(chan struct{}) 31 close(closedChan) 32 } 33 34 // NotFoundErrorIterator simply always returns an error of cb.Status_NOT_FOUND, 35 // and is generally useful for implementations of the Reader interface 36 type NotFoundErrorIterator struct{} 37 38 // Next returns nil, cb.Status_NOT_FOUND 39 func (nfei *NotFoundErrorIterator) Next() (*cb.Block, cb.Status) { 40 return nil, cb.Status_NOT_FOUND 41 } 42 43 // ReadyChan returns a closed channel 44 func (nfei *NotFoundErrorIterator) ReadyChan() <-chan struct{} { 45 return closedChan 46 } 47 48 // CreateNextBlock provides a utility way to construct the next block from 49 // contents and metadata for a given ledger 50 // XXX This will need to be modified to accept marshaled envelopes 51 // to accommodate non-deterministic marshaling 52 func CreateNextBlock(rl Reader, messages []*cb.Envelope, feeAddress string, blockVersion uint64) *cb.Block { 53 var nextBlockNumber uint64 54 var previousBlockHash []byte 55 56 if rl.Height() > 0 { 57 it, _ := rl.Iterator(&ab.SeekPosition{ 58 Type: &ab.SeekPosition_Newest{ 59 &ab.SeekNewest{}, 60 }, 61 }) 62 <-it.ReadyChan() // Should never block, but just in case 63 block, status := it.Next() 64 if status != cb.Status_SUCCESS { 65 panic("Error seeking to newest block for chain with non-zero height") 66 } 67 nextBlockNumber = block.Header.Number + 1 68 previousBlockHash = block.Header.Hash() 69 } 70 // bubble sort transactions by sender counter 71 tx_number := len(messages) 72 txOrder := make([]int, tx_number) 73 txCounter := make([]uint64, tx_number) 74 var j, i int 75 for i, msg := range messages { 76 txOrder[i] = i 77 cis, _, err := putils.GetActionFromEnvelopePayload(msg.Payload) 78 if err != nil || cis.SenderSpec == nil { 79 txCounter[i] = 0 80 } else { 81 txCounter[i] = cis.SenderSpec.Counter 82 } 83 } 84 var temp uint64 85 var temp_idx int 86 for i = tx_number - 1; i > 0; i-- { 87 for j = tx_number - 1; j > tx_number-1-i; j-- { 88 if txCounter[j] < txCounter[j-1] { 89 temp = txCounter[j] 90 txCounter[j] = txCounter[j-1] 91 txCounter[j-1] = temp 92 temp_idx = txOrder[j] 93 txOrder[j] = txOrder[j-1] 94 txOrder[j-1] = temp_idx 95 } 96 } 97 } 98 data := &cb.BlockData{ 99 Data: make([][]byte, tx_number), 100 } 101 var err error 102 for i, j := range txOrder { 103 data.Data[i], err = proto.Marshal(messages[j]) 104 if err != nil { 105 panic(err) 106 } 107 } 108 block := cb.NewBlock(nextBlockNumber, previousBlockHash, wallet.StringToAddress(feeAddress).ToBytes(), blockVersion) 109 block.Header.DataHash = data.Hash() 110 block.Data = data 111 112 return block 113 } 114 115 // GetBlock is a utility method for retrieving a single block 116 func GetBlock(rl Reader, index uint64) *cb.Block { 117 i, _ := rl.Iterator(&ab.SeekPosition{ 118 Type: &ab.SeekPosition_Specified{ 119 Specified: &ab.SeekSpecified{Number: index}, 120 }, 121 }) 122 select { 123 case <-i.ReadyChan(): 124 block, status := i.Next() 125 if status != cb.Status_SUCCESS { 126 return nil 127 } 128 return block 129 default: 130 return nil 131 } 132 }