module Bitcoin.BlockChain.Unspent where
import Control.Monad
import Data.Array
import Data.Maybe
import Data.Word
import Data.Int
import Data.Set (Set) ; import qualified Data.Set as Set
import Data.Map (Map) ; import qualified Data.Map as Map
import Data.IORef
import Bitcoin.Protocol
import Bitcoin.BlockChain.Base
import Bitcoin.BlockChain.Load
import Bitcoin.BlockChain.Tx
import Bitcoin.BlockChain.Cache
import Bitcoin.BlockChain.Chain
import Bitcoin.BlockChain.TxLookup
import Bitcoin.Script.Base
data UnspentOutput = UnspentOutput
{ _unspentTxId :: !Hash256
, _unspentTxOut :: !Word32
}
deriving (Eq,Ord,Show)
buildUnspentTable :: ChainTable -> TxLookup -> IO (Map UnspentOutput Amount)
buildUnspentTable chTable txTable = do
let txLkp :: Hash256 -> IO (Maybe (Tx RawScript RawScript))
txLkp = txLookup_ chTable txTable
let (a,b) = bounds (_tableLongest chTable)
unspent <- newIORef Map.empty
forM_ [a..b] $ \(!blkIdx) -> do
block <- loadBlockAt $! _chainLocation (_tableLongest chTable ! blkIdx)
forM_ (_blockTxs block) $ \(!tx) -> do
let !txhash = _txHash tx
forM_ (_txInputs tx) $ \(TxInput !prevhash !prevout _ _) ->
myModifyIORef' unspent $ Map.delete (UnspentOutput prevhash prevout)
forM_ (zip [0..] (_txOutputs tx)) $ \(outidx, TxOutput !amount _) ->
myModifyIORef' unspent $ Map.insert (UnspentOutput txhash outidx ) (Amount $ fromIntegral amount)
readIORef unspent
where
myModifyIORef' :: IORef a -> (a -> a) -> IO ()
myModifyIORef' ref f = do
!old <- readIORef ref
writeIORef ref $! (f old)