func (mock *MockLedger) simulateStateTransfer(info *protos.BlockchainInfo, peers []*protos.PeerID) {
	var remoteLedger consensus.ReadOnlyLedger
	if len(peers) > 0 {
		var ok bool
		remoteLedger, ok = mock.remoteLedgers.GetLedgerByPeerID(peers[0])
		if !ok {
			panic("Asked for results from a peer which does not exist")
		}
	} else {
		panic("TODO, support state transfer from nil peers")
	}
	fmt.Printf("TEST LEDGER skipping to %+v", info)
	p := 0
	if mock.blockHeight >= info.Height {
		panic(fmt.Sprintf("Asked to skip to a block (%d) which is lower than our current height of %d", info.Height, mock.blockHeight))
	}
	for n := mock.blockHeight; n < info.Height; n++ {
		block, err := remoteLedger.GetBlock(n)

		if nil != err {
			n--
			fmt.Printf("TEST LEDGER: Block not ready yet")
			time.Sleep(100 * time.Millisecond)
			p++
			if p > 10 {
				panic("Tried to get a block 10 times, no luck")
			}
			continue
		}

		mock.blocks[n] = block
	}
	mock.blockHeight = info.Height
}
func (mock *MockLedger) simulateStateTransfer(info *protos.BlockchainInfo, peers []*protos.PeerID) {
	if mock.blockHeight >= info.Height {
		blockCursor := info.Height - 1
		validHash := info.CurrentBlockHash
		for {
			block, ok := mock.blocks[blockCursor]
			if !ok {
				break
			}
			hash, _ := mock.HashBlock(block)
			if !bytes.Equal(hash, validHash) {
				break
			}
			blockCursor--
			validHash = block.PreviousBlockHash
			if blockCursor == ^uint64(0) {
				return
			}
		}
		panic(fmt.Sprintf("Asked to skip to a block (%d) which is lower than our current height of %d.  (Corrupt block at %d with hash %x)", info.Height, mock.blockHeight, blockCursor, validHash))
	}

	var remoteLedger consensus.ReadOnlyLedger
	if len(peers) > 0 {
		var ok bool
		remoteLedger, ok = mock.remoteLedgers.GetLedgerByPeerID(peers[0])
		if !ok {
			panic("Asked for results from a peer which does not exist")
		}
	} else {
		panic("TODO, support state transfer from nil peers")
	}
	fmt.Printf("TEST LEDGER skipping to %+v", info)
	p := 0
	for n := mock.blockHeight; n < info.Height; n++ {
		block, err := remoteLedger.GetBlock(n)

		if nil != err {
			n--
			fmt.Printf("TEST LEDGER: Block not ready yet")
			time.Sleep(100 * time.Millisecond)
			p++
			if p > 10 {
				panic("Tried to get a block 10 times, no luck")
			}
			continue
		}

		mock.blocks[n] = block
	}
	mock.blockHeight = info.Height
}
func (mock *MockLedger) simulateStateTransfer(meta []byte, id []byte, peers []*protos.PeerID) {
	var remoteLedger consensus.ReadOnlyLedger
	if len(peers) > 0 {
		var ok bool
		remoteLedger, ok = mock.remoteLedgers.GetLedgerByPeerID(peers[0])
		if !ok {
			panic("Asked for results from a peer which does not exist")
		}
	} else {
		panic("TODO, support state transfer from nil peers")
	}
	info := &protos.BlockchainInfo{}
	proto.Unmarshal(id, info)
	fmt.Printf("TEST LEDGER skipping to %+v, %+v", meta, info)
	p := 0
	if mock.blockHeight >= info.Height {
		panic(fmt.Sprintf("Asked to skip to a block (%d) which is lower than our current height of %d", info.Height, mock.blockHeight))
	}
	for n := mock.blockHeight; n < info.Height; n++ {
		block, err := remoteLedger.GetBlock(n)

		if nil != err {
			n--
			// To accommodate Sieve, it's possible to ask for a block that hasn't been committed yet
			// because Sieve must broadcast the verify set before it is committed
			fmt.Printf("TEST LEDGER: Block not ready yet")
			time.Sleep(100 * time.Millisecond)
			p++
			if p > 10 {
				panic("Tried to get a block 10 times, no luck")
			}
			continue
		}

		block.ConsensusMetadata = meta
		mock.blocks[n] = block
	}
	mock.blockHeight = info.Height
}