NewChain returns a new Chain using store as the underlying storage.
(ctx context.Context, initialBlock *bc.Block, store Store, heights <-chan uint64)
| 128 | |
| 129 | // NewChain returns a new Chain using store as the underlying storage. |
| 130 | func NewChain(ctx context.Context, initialBlock *bc.Block, store Store, heights <-chan uint64) (*Chain, error) { |
| 131 | c := &Chain{ |
| 132 | InitialBlockHash: initialBlock.Hash(), |
| 133 | bb: NewBlockBuilder(), |
| 134 | store: store, |
| 135 | pendingSnapshots: make(chan *state.Snapshot, 1), |
| 136 | blocksPerSnapshot: defaultBlocksPerSnapshot, |
| 137 | } |
| 138 | |
| 139 | c.state.cond.L = new(sync.Mutex) |
| 140 | c.state.snapshot = state.Empty() |
| 141 | |
| 142 | var err error |
| 143 | c.state.height, err = store.Height(ctx) |
| 144 | if err != nil { |
| 145 | return nil, errors.Wrap(err, "looking up blockchain height") |
| 146 | } |
| 147 | |
| 148 | // Note that c.state.height may still be zero here. |
| 149 | if heights != nil { |
| 150 | go func() { |
| 151 | for { |
| 152 | select { |
| 153 | case <-ctx.Done(): |
| 154 | return |
| 155 | case h := <-heights: |
| 156 | c.setHeight(h) |
| 157 | } |
| 158 | } |
| 159 | }() |
| 160 | } |
| 161 | |
| 162 | go func() { |
| 163 | for { |
| 164 | select { |
| 165 | case <-ctx.Done(): |
| 166 | return |
| 167 | case s := <-c.pendingSnapshots: |
| 168 | err = store.SaveSnapshot(ctx, s) |
| 169 | if err != nil { |
| 170 | log.Error(ctx, err, "at", "saving snapshot") |
| 171 | } |
| 172 | } |
| 173 | } |
| 174 | }() |
| 175 | |
| 176 | return c, nil |
| 177 | } |
| 178 | |
| 179 | // Height returns the current height of the blockchain. |
| 180 | func (c *Chain) Height() uint64 { |