<p>I was able to resolve this issue by converting (encoding) the BuiltinByteString from getTxId into a hex format.   From there I was able to inpsect the hex digits.   Below is an onchain encodeHex function that I used (thanks Minswap!).</p>
<pre><code>-- Convert from a byte string to its hex (base16) representation. Example: [2, 14, 255] =&gt; &quot;020eff&quot;
{-# INLINEABLE encodeHex #-}
encodeHex :: BuiltinByteString -&gt; BuiltinByteString
encodeHex input = go 0
  where
    len = lengthOfByteString input
    go :: Integer -&gt; BuiltinByteString
    go i
      | i == len = emptyByteString
      | otherwise =
        consByteString (toChar $ byte `quotient` 16) $
          consByteString (toChar $ byte `remainder` 16) (go $ i + 1)
      where
        byte = indexByteString input i

        toChar :: Integer -&gt; Integer
        toChar x
          -- 48 is ASCII code for '0'
          | x &lt; 10 = x + 48
          -- 97 is ASCII code for 'a'
          -- x - 10 + 97 = x + 87
          | otherwise = x + 87
</code></pre>

CC BY-SA 4.0
2022-04-04T20:46:20.477Z
2022-04-04T20:46:20.477Z
lley154
<blockquote>
<p>but then I need to get the base16 representation so I can compare and
inspect the hex digits.</p>
</blockquote>
<p>Not sure this is correct, I was able to inspect the txId directly with <code>getTxId</code>, take a look at the following code</p>
<pre><code>import           Data.Aeson           hiding (Value)
import           GHC.Generics
import           Ledger               hiding (singleton)
import           Ledger.Scripts
import           Ledger.Typed.Scripts as Scripts
import           Ledger.Value
import           Plutus.ChainIndex
import qualified PlutusTx
import PlutusTx.Builtins
import qualified PlutusTx.AssocMap    as PlutusMap
import           PlutusTx.Prelude
import qualified PlutusTx.Ratio       as R
import qualified Prelude

...

{-# INLINEABLE mkNFTPolicy #-}
mkNFTPolicy :: Integer -&gt; TxOutRef -&gt; ScriptContext -&gt; Bool
mkNFTPolicy size oref ctx = 
    nftPolicyTraceIfFalse &quot;UTxO not consumed&quot; hasUTxO &amp;&amp;
    nftPolicyTraceIfFalse &quot;Invalid token name or amount&quot; validMinting
  where
    refId :: BuiltinByteString
    refId = case intToBuiltinByteString $ txOutRefIdx oref of
        bbs | lengthOfByteString bbs == 1 -&gt; &quot;0&quot; `appendByteString` bbs
            | lengthOfByteString bbs == 2 -&gt; bbs
        _ -&gt; nftPolicyTraceError &quot;Invalid ref id&quot;
    
    ...

    validTokenName :: TokenName -&gt; Bool
    validTokenName (TokenName bs) = sliceByteString 0 (size + 2) bs == expected
      where
        expected :: BuiltinByteString
        expected = sliceByteString 0 size (getTxId $ txOutRefId oref) `appendByteString` refId
    ...
</code></pre>

CC BY-SA 4.0
2022-04-04T20:34:45.407Z
Thanks Mateus.  I was able to resolve the issue, I needed to convert (encode) the onchain reprentation proivded by getTxId into a hex format.   From there I was able to look at each of the hex digits.   I'll post the encodeHex function on the main thread.
lley154
CC BY-SA 4.0
2022-04-01T12:52:36.913Z
2022-04-01T12:52:36.913Z
Mateus
<p>You might just need to use the fromBuiltin fn to get a ByteString:</p>
<pre><code>...
import Data.ByteString.Char8 as C
import Prelude as Haskell
...


converted :: BuiltinByteString -&gt; BuiltinString
converted bbs' = let b = C.unpack( fromBuiltin bbs' ) :: Haskell.String
                              -- in toBuiltin b
                              in stringToBuiltinString b 
</code></pre>
<p>Update: I'm not sure I've figured out how to set up the toBuiltin fn. It's not compiling in my test project.</p>
<p>Update: the actual fn is stringToBuiltinString</p>

CC BY-SA 4.0
2022-04-01T12:45:55.910Z
This does not work on-chain
Mateus
CC BY-SA 4.0
2022-05-02T04:59:35.007Z
@Mateus  is correct, this doesn't work onchain. I'll add another answer with what I've found.
marcel_g
CC BY-SA 4.0
2022-03-02T10:37:12.020Z
2022-03-02T10:52:20.117Z
2022-03-02T10:52:20.117Z
marcel_g
<p>I am trying to find a way to inspect the base16 hash from a Tx on-chain using plutus.</p>
<p>I get a BuiltinByteString from the txInputs here:</p>
<pre><code>getTxIdBBS :: TxInInfo -&gt; BuiltinByteString
getTxIdBBS txInfo' = getTxId(txOutRefId (txInInfoOutRef txInfo'))
</code></pre>
<p>but then I need to get the base16 representation so I can compare and inspect the hex digits.  
 
Ideally, I would like to use a function similar to below, but this only works off-chain (due to conversion to non-builtin).</p>
<pre><code>import qualified Data.ByteString.Base16 as B16 (encode)

txId    = getTxIdBBS (txInfo)
txId'   = fromBuiltin(txId)
txIdHex = toBuiltin(B16.encode txId')
</code></pre>
<p>I've also tried the following, but this does not work either.</p>
<pre><code>import Data.Text.Encoding qualified as E
import PlutusTx.Builtins.Internal qualified as BI

{-# INLINABLE txEncodeUtf16 #-}
txEncodeUtf16 :: BI.BuiltinString -&gt; BI.BuiltinByteString
txEncodeUtf16 (BI.BuiltinString s) = BI.BuiltinByteString $ E.encodeUtf16BE s

txHash = txEncodeUtf16(decodeUtf8(txId))
</code></pre>
<p>I am not able to use decodeUtf8 on a BuiltinByteString generated by sha2_256 and get the following error:</p>
<pre><code>decodeUtf8*** Exception: Cannot decode byte '\xc6': Data.Text.Internal.Encoding.decodeUtf8: Invalid UTF-8 stream
</code></pre>
<p>I also can’t use encodeUtf16BE due to the following compiler error:</p>
<pre><code>GHC Core to PLC plugin: E042:Error: Unsupported feature: Type constructor: GHC.Prim.ByteArray#
</code></pre>
<p>Any help or suggestions on how to convert the BuiltinByteString from getTxId into a BuiltinString  &quot;on-chain&quot; where I can inspect the hex digits would be awesome.</p>
<p>Thanks,</p>
<p>Lawrence</p>

CC BY-SA 4.0
2022-03-01T00:58:07.623Z
What is `BuiltinByteString` ?
Erik de Castro Lopo
<plutus><plutustx><on-chain><hash><converter>
How to get a base 16 hex BuiltinString from getTxId
# How to get a base 16 hex BuiltinString from getTxId

(Asked by: username_0 on 2022-03-01)

I am trying to find a way to inspect the base16 hash from a Tx on-chain using plutus.
I get a BuiltinByteString from the txInputs here:
getTxIdBBS :: TxInInfo -> BuiltinByteString
getTxIdBBS txInfo' = getTxId(txOutRefId (txInInfoOutRef txInfo'))

but then I need to get the base16 representation so I can compare and inspect the hex digits.  
 
Ideally, I would like to use a function similar to below, but this only works off-chain (due to conversion to non-builtin).
import qualified Data.ByteString.Base16 as B16 (encode)

txId    = getTxIdBBS (txInfo)
txId'   = fromBuiltin(txId)
txIdHex = toBuiltin(B16.encode txId')

I've also tried the following, but this does not work either.
import Data.Text.Encoding qualified as E
import PlutusTx.Builtins.Internal qualified as BI

{-# INLINABLE txEncodeUtf16 #-}
txEncodeUtf16 :: BI.BuiltinString -> BI.BuiltinByteString
txEncodeUtf16 (BI.BuiltinString s) = BI.BuiltinByteString $ E.encodeUtf16BE s

txHash = txEncodeUtf16(decodeUtf8(txId))

I am not able to use decodeUtf8 on a BuiltinByteString generated by sha2_256 and get the following error:
decodeUtf8*** Exception: Cannot decode byte '\xc6': Data.Text.Internal.Encoding.decodeUtf8: Invalid UTF-8 stream

I also can’t use encodeUtf16BE due to the following compiler error:
GHC Core to PLC plugin: E042:Error: Unsupported feature: Type constructor: GHC.Prim.ByteArray#

Any help or suggestions on how to convert the BuiltinByteString from getTxId into a BuiltinString  "on-chain" where I can inspect the hex digits would be awesome.
Thanks,
Lawrence

**Tags:** plutus, plutustx, on-chain, hash, converter
> **Comments:**
> **username_1**: What is `BuiltinByteString` ?  

---

## 3 answers

### Answer by username_0 on 2022-04-04. Score: 2

I was able to resolve this issue by converting (encoding) the BuiltinByteString from getTxId into a hex format.   From there I was able to inpsect the hex digits.   Below is an onchain encodeHex function that I used (thanks Minswap!).
-- Convert from a byte string to its hex (base16) representation. Example: [2, 14, 255] => "020eff"
{-# INLINEABLE encodeHex #-}
encodeHex :: BuiltinByteString -> BuiltinByteString
encodeHex input = go 0
  where
    len = lengthOfByteString input
    go :: Integer -> BuiltinByteString
    go i
      | i == len = emptyByteString
      | otherwise =
        consByteString (toChar $ byte `quotient` 16) $
          consByteString (toChar $ byte `remainder` 16) (go $ i + 1)
      where
        byte = indexByteString input i

        toChar :: Integer -> Integer
        toChar x
          -- 48 is ASCII code for '0'
          | x < 10 = x + 48
          -- 97 is ASCII code for 'a'
          -- x - 10 + 97 = x + 87
          | otherwise = x + 87


---

### Answer by username_2 on 2022-04-01. Score: 0

but then I need to get the base16 representation so I can compare and
inspect the hex digits.

Not sure this is correct, I was able to inspect the txId directly with getTxId, take a look at the following code
import           Data.Aeson           hiding (Value)
import           GHC.Generics
import           Ledger               hiding (singleton)
import           Ledger.Scripts
import           Ledger.Typed.Scripts as Scripts
import           Ledger.Value
import           Plutus.ChainIndex
import qualified PlutusTx
import PlutusTx.Builtins
import qualified PlutusTx.AssocMap    as PlutusMap
import           PlutusTx.Prelude
import qualified PlutusTx.Ratio       as R
import qualified Prelude

...

{-# INLINEABLE mkNFTPolicy #-}
mkNFTPolicy :: Integer -> TxOutRef -> ScriptContext -> Bool
mkNFTPolicy size oref ctx = 
    nftPolicyTraceIfFalse "UTxO not consumed" hasUTxO &&
    nftPolicyTraceIfFalse "Invalid token name or amount" validMinting
  where
    refId :: BuiltinByteString
    refId = case intToBuiltinByteString $ txOutRefIdx oref of
        bbs | lengthOfByteString bbs == 1 -> "0" `appendByteString` bbs
            | lengthOfByteString bbs == 2 -> bbs
        _ -> nftPolicyTraceError "Invalid ref id"
    
    ...

    validTokenName :: TokenName -> Bool
    validTokenName (TokenName bs) = sliceByteString 0 (size + 2) bs == expected
      where
        expected :: BuiltinByteString
        expected = sliceByteString 0 size (getTxId $ txOutRefId oref) `appendByteString` refId
    ...

> **Comments:**
> **username_0**: Thanks Mateus.  I was able to resolve the issue, I needed to convert (encode) the onchain reprentation proivded by getTxId into a hex format.   From there I was able to look at each of the hex digits.   I'll post the encodeHex function on the main thread.  

---

### Answer by username_3 on 2022-03-02. Score: 0

You might just need to use the fromBuiltin fn to get a ByteString:
...
import Data.ByteString.Char8 as C
import Prelude as Haskell
...


converted :: BuiltinByteString -> BuiltinString
converted bbs' = let b = C.unpack( fromBuiltin bbs' ) :: Haskell.String
                              -- in toBuiltin b
                              in stringToBuiltinString b 

Update: I'm not sure I've figured out how to set up the toBuiltin fn. It's not compiling in my test project.
Update: the actual fn is stringToBuiltinString

> **Comments:**
> **username_2**: This does not work on-chain  
> **username_3**: @Mateus  is correct, this doesn't work onchain. I'll add another answer with what I've found.  

---

