diff --git a/core/state/state_test.go b/core/state/state_test.go
index 689e7dbc423671b8371a5934e05bcde3955f855c..53e0fa1fb38a6a1edb9859028a37814e4390e909 100644
--- a/core/state/state_test.go
+++ b/core/state/state_test.go
@@ -19,7 +19,6 @@ package state
 import (
 	"bytes"
 	"math/big"
-	"os"
 	"testing"
 
 	"context"
@@ -326,11 +325,6 @@ func TestDump(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	f, _ := os.Create("/Users/boris/go/src/github.com/ledgerwatch/turbo-geth/debug/trie_wrong.txt")
-	tds.tMu.Lock()
-	tds.t.Print(f)
-	tds.tMu.Unlock()
-
 	// check that dump contains the state objects that are in trie
 	got := string(tds.DefaultDump())
 	want := `{
diff --git a/trie/debug.go b/trie/debug.go
index d3ae43e2d4509305ec6cd12f9c0ac1e63c374a9c..7ede19426be15addc00adae108a35f6d0b4d542b 100644
--- a/trie/debug.go
+++ b/trie/debug.go
@@ -19,171 +19,44 @@
 package trie
 
 import (
-	"bufio"
 	"bytes"
-	"encoding/hex"
 	"fmt"
 	"io"
-	"strconv"
 
 	"github.com/ledgerwatch/turbo-geth/common"
 	"github.com/ledgerwatch/turbo-geth/common/pool"
 )
 
 func (t *Trie) Print(w io.Writer) {
-	if t.root != nil {
-		t.root.print(w)
-	}
-	fmt.Fprintf(w, "\n")
-}
-
-func (t *Trie) PrintTrie() {
-	if t.root == nil {
-		fmt.Printf("nil Trie\n")
-	} else {
-		fmt.Printf("%s\n", t.root.fstring(""))
-	}
-}
-
-func loadNode(br *bufio.Reader) (node, error) {
-	nodeType, err := br.ReadString('(')
-	if err != nil {
-		return nil, err
-	}
-	switch nodeType[len(nodeType)-2:] {
-	case "f(":
-		return loadFull(br)
-	case "d(":
-		return loadDuo(br)
-	case "s(":
-		return loadShort(br)
-	case "h(":
-		return loadHash(br)
-	case "v(":
-		return loadValue(br)
-	}
-	return nil, fmt.Errorf("unknown node type: %s", nodeType)
-}
-
-func loadFull(br *bufio.Reader) (*fullNode, error) {
-	n := fullNode{}
-	for {
-		next, err := br.Peek(1)
-		if err != nil {
-			return nil, err
-		}
-		if next[0] == ')' {
-			break
-		}
-		idxStr, err := br.ReadBytes(':')
-		if err != nil {
-			return nil, err
-		}
-		idxStr = idxStr[:len(idxStr)-1] // chop off ":"
-		idx, err := strconv.ParseInt(string(idxStr), 10, 64)
-		if err != nil {
-			return nil, err
-		}
-		n.Children[idx], err = loadNode(br)
-		if err != nil {
-			return nil, err
-		}
-	}
-	if _, err := br.Discard(1); err != nil { // Discard ")"
-		return nil, err
-	}
-	return &n, nil
-}
-
-func loadDuo(br *bufio.Reader) (*duoNode, error) {
-	n := duoNode{}
-	idxStr1, err := br.ReadBytes(':')
-	if err != nil {
-		return nil, err
-	}
-	idxStr1 = idxStr1[:len(idxStr1)-1] // chop off ":"
-	idx1, err := strconv.ParseInt(string(idxStr1), 10, 64)
-	if err != nil {
-		return nil, err
-	}
-	n.child1, err = loadNode(br)
-	if err != nil {
-		return nil, err
-	}
-	idxStr2, err := br.ReadBytes(':')
+	witness, err := t.ExtractWitness(1, false, nil)
 	if err != nil {
-		return nil, err
+		panic(err)
 	}
-	idxStr2 = idxStr2[:len(idxStr2)-1] // chop off ":"
-	idx2, err := strconv.ParseInt(string(idxStr2), 10, 64)
+	_, err = witness.WriteTo(w)
 	if err != nil {
-		return nil, err
-	}
-	n.child2, err = loadNode(br)
-	if err != nil {
-		return nil, err
+		panic(err)
 	}
-	n.mask = (uint32(1) << uint(idx1)) | (uint32(1) << uint(idx2))
-	if _, err := br.Discard(1); err != nil { // Discard ")"
-		return nil, err
-	}
-	return &n, nil
 }
 
-func loadShort(br *bufio.Reader) (*shortNode, error) {
-	n := shortNode{}
-	keyHexHex, err := br.ReadBytes(':')
-	if err != nil {
-		return nil, err
-	}
-	keyHexHex = keyHexHex[:len(keyHexHex)-1]
-	keyHex, err := hex.DecodeString(string(keyHexHex))
-	if err != nil {
-		return nil, err
-	}
-	n.Key = keyHex
-	n.Val, err = loadNode(br)
-	if err != nil {
-		return nil, err
-	}
-	if _, err := br.Discard(1); err != nil { // Discard ")"
-		return nil, err
-	}
-	return &n, nil
+type HexStdOutWriter struct{}
+
+func (*HexStdOutWriter) Write(p []byte) (n int, err error) {
+	fmt.Printf("%x", p)
+	return len(p), nil
 }
 
-func loadHash(br *bufio.Reader) (hashNode, error) {
-	hashHex, err := br.ReadBytes(')')
-	if err != nil {
-		return nil, err
-	}
-	hashHex = hashHex[:len(hashHex)-1]
-	hash, err := hex.DecodeString(string(hashHex))
-	if err != nil {
-		return nil, err
-	}
-	return hashNode(hash), nil
+func (t *Trie) PrintTrie() {
+	fmt.Printf("trie:0x")
+	t.Print(&HexStdOutWriter{})
+	fmt.Println("")
 }
 
-func loadValue(br *bufio.Reader) (valueNode, error) {
-	valHex, err := br.ReadBytes(')')
-	if err != nil {
-		return nil, err
-	}
-	valHex = valHex[:len(valHex)-1]
-	val, err := hex.DecodeString(string(valHex))
+func Load(r io.Reader) (*Trie, error) {
+	witness, err := NewWitnessFromReader(r, false)
 	if err != nil {
 		return nil, err
 	}
-	return valueNode(val), nil
-}
-
-func Load(r io.Reader) (*Trie, error) {
-	br := bufio.NewReader(r)
-	t := NewTestRLPTrie(common.Hash{})
-	var err error
-	t.root, err = loadNode(br)
-	return t, err
+	return BuildTrieFromWitness(witness, false, false)
 }
 
 func (t *Trie) PrintDiff(t2 *Trie, w io.Writer) {
diff --git a/trie/debug_test.go b/trie/debug_test.go
index 90e9234f394f99eb36b225b9d435d16770b07a7c..cb932158e7026978c0add6a5253e4717a7f6fead 100644
--- a/trie/debug_test.go
+++ b/trie/debug_test.go
@@ -73,7 +73,7 @@ func TestPrintLoad(t *testing.T) {
 		tr.Print(&b)
 		if trace {
 			fmt.Printf("Trie: %s\n", tr.root.fstring(""))
-			fmt.Printf("Buffer: %s\n", b.Bytes())
+			fmt.Printf("Buffer: 0x%x\n", b.Bytes())
 		}
 		trLoaded, err := Load(&b)
 		if err != nil {
diff --git a/trie/trie_witness.go b/trie/trie_witness.go
index 127d869e3df02131be589daedcad96b48997e621..7fd880374a7100e525c9d875042c9c62db95c64c 100644
--- a/trie/trie_witness.go
+++ b/trie/trie_witness.go
@@ -3,7 +3,11 @@ package trie
 import "errors"
 
 func (t *Trie) ExtractWitness(blockNr uint64, trace bool, rs *ResolveSet) (*Witness, error) {
-	return extractWitnessFromRootNode(t.root, blockNr, trace, rs)
+	var h HashOnly
+	if rs != nil {
+		h = rs
+	}
+	return extractWitnessFromRootNode(t.root, blockNr, trace, h)
 }
 
 func (t *Trie) ExtractWitnessForPrefix(prefix []byte, blockNr uint64, trace bool, rs *ResolveSet) (*Witness, error) {
@@ -19,12 +23,11 @@ func (t *Trie) ExtractWitnessForPrefix(prefix []byte, blockNr uint64, trace bool
 // if hashOnly param is set to a ResolveSet instance, it will make a witness for only the accounts/storages that were actually touched; other paths will be hashed.
 func extractWitnessFromRootNode(root node, blockNr uint64, trace bool, hashOnly HashOnly) (*Witness, error) {
 	builder := NewWitnessBuilder(root, blockNr, trace)
-	var limiter *MerklePathLimiter
+	var limiter *MerklePathLimiter = nil
 	if hashOnly != nil {
 		hr := newHasher(false)
 		defer returnHasherToPool(hr)
 		limiter = &MerklePathLimiter{hashOnly, hr.hash}
 	}
-
 	return builder.Build(limiter)
 }
diff --git a/trie/witness.go b/trie/witness.go
index e2f1fb2fca8eacafa6f4e400b1b120fe4ae31d99..f43897227d77bbeba764951d15c8eaab802e8b70 100644
--- a/trie/witness.go
+++ b/trie/witness.go
@@ -147,12 +147,25 @@ func (w *Witness) WriteDiff(w2 *Witness, output io.Writer) {
 		fmt.Fprintf(output, "w1 operands: %d; w2 operands: %d\n", len(w.Operators), len(w2.Operators))
 	}
 
-	for i := 0; i < len(w.Operators); i++ {
-		switch o1 := w.Operators[i].(type) {
+	length := len(w.Operators)
+	if len(w2.Operators) > length {
+		length = len(w2.Operators)
+	}
+
+	for i := 0; i < length; i++ {
+		var op WitnessOperator
+		if i < len(w.Operators) {
+			op = w.Operators[i]
+		}
+		if i >= len(w2.Operators) {
+			fmt.Fprintf(output, "unexpected o1[%d] = %T %v; o2[%d] = nil\n", i, op, op, i)
+			continue
+		}
+		switch o1 := op.(type) {
 		case *OperatorBranch:
 			o2, ok := w2.Operators[i].(*OperatorBranch)
 			if !ok {
-				fmt.Fprintf(output, "o1[%d] = %T; o2[%d] = %T\n", i, o1, i, o2)
+				fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2)
 			}
 			if o1.Mask != o2.Mask {
 				fmt.Fprintf(output, "o1[%d].Mask = %v; o2[%d].Mask = %v", i, o1.Mask, i, o2.Mask)
@@ -160,7 +173,7 @@ func (w *Witness) WriteDiff(w2 *Witness, output io.Writer) {
 		case *OperatorHash:
 			o2, ok := w2.Operators[i].(*OperatorHash)
 			if !ok {
-				fmt.Fprintf(output, "o1[%d] = %T; o2[%d] = %T\n", i, o1, i, o2)
+				fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2)
 			}
 			if !bytes.Equal(o1.Hash.Bytes(), o2.Hash.Bytes()) {
 				fmt.Fprintf(output, "o1[%d].Hash = %s; o2[%d].Hash = %s\n", i, o1.Hash.Hex(), i, o2.Hash.Hex())
@@ -168,7 +181,7 @@ func (w *Witness) WriteDiff(w2 *Witness, output io.Writer) {
 		case *OperatorCode:
 			o2, ok := w2.Operators[i].(*OperatorCode)
 			if !ok {
-				fmt.Fprintf(output, "o1[%d] = %T; o2[%d] = %T\n", i, o1, i, o2)
+				fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2)
 			}
 			if !bytes.Equal(o1.Code, o2.Code) {
 				fmt.Fprintf(output, "o1[%d].Code = %x; o2[%d].Code = %x\n", i, o1.Code, i, o2.Code)
@@ -176,12 +189,12 @@ func (w *Witness) WriteDiff(w2 *Witness, output io.Writer) {
 		case *OperatorEmptyRoot:
 			o2, ok := w2.Operators[i].(*OperatorEmptyRoot)
 			if !ok {
-				fmt.Fprintf(output, "o1[%d] = %T; o2[%d] = %T\n", i, o1, i, o2)
+				fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2)
 			}
 		case *OperatorExtension:
 			o2, ok := w2.Operators[i].(*OperatorExtension)
 			if !ok {
-				fmt.Fprintf(output, "o1[%d] = %T; o2[%d] = %T\n", i, o1, i, o2)
+				fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2)
 			}
 			if !bytes.Equal(o1.Key, o2.Key) {
 				fmt.Fprintf(output, "extension o1[%d].Key = %x; o2[%d].Key = %x\n", i, o1.Key, i, o2.Key)
@@ -189,7 +202,7 @@ func (w *Witness) WriteDiff(w2 *Witness, output io.Writer) {
 		case *OperatorLeafAccount:
 			o2, ok := w2.Operators[i].(*OperatorLeafAccount)
 			if !ok {
-				fmt.Fprintf(output, "o1[%d] = %T; o2[%d] = %T\n", i, o1, i, o2)
+				fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2)
 			}
 			if !bytes.Equal(o1.Key, o2.Key) {
 				fmt.Fprintf(output, "leafAcc o1[%d].Key = %x; o2[%d].Key = %x\n", i, o1.Key, i, o2.Key)
@@ -209,7 +222,7 @@ func (w *Witness) WriteDiff(w2 *Witness, output io.Writer) {
 		case *OperatorLeafValue:
 			o2, ok := w2.Operators[i].(*OperatorLeafValue)
 			if !ok {
-				fmt.Fprintf(output, "o1[%d] = %T; o2[%d] = %T\n", i, o1, i, o2)
+				fmt.Fprintf(output, "o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2)
 			}
 			if !bytes.Equal(o1.Key, o2.Key) {
 				fmt.Fprintf(output, "leafVal o1[%d].Key = %x; o2[%d].Key = %x\n", i, o1.Key, i, o2.Key)
@@ -219,7 +232,7 @@ func (w *Witness) WriteDiff(w2 *Witness, output io.Writer) {
 			}
 		default:
 			o2 := w2.Operators[i]
-			fmt.Fprintf(output, "unexpected o1[%d] = %T; o2[%d] = %T\n", i, o1, i, o2)
+			fmt.Fprintf(output, "unexpected o1[%d] = %T %+v; o2[%d] = %T %+v\n", i, o1, o1, i, o2, o2)
 		}
 	}
 }
diff --git a/trie/witness_builder.go b/trie/witness_builder.go
index 57060767336b643b19291ce46974789705fcf465..81a64b941595305e10a4c2f6e0a095cb9e5ec875 100644
--- a/trie/witness_builder.go
+++ b/trie/witness_builder.go
@@ -160,7 +160,7 @@ func (b *WitnessBuilder) processAccountCode(n *accountNode, hashOnly HashOnly) e
 		return nil
 	}
 
-	if n.code == nil || !hashOnly.IsCodeTouched(n.CodeHash) {
+	if n.code == nil || (hashOnly != nil && !hashOnly.IsCodeTouched(n.CodeHash)) {
 		return b.addHashOp(hashNode(n.CodeHash[:]))
 	}
 
@@ -184,7 +184,11 @@ func (b *WitnessBuilder) makeBlockWitness(
 	nd node, hex []byte, limiter *MerklePathLimiter, force bool) error {
 
 	processAccountNode := func(key []byte, storageKey []byte, n *accountNode) error {
-		if err := b.processAccountCode(n, limiter.HashOnly); err != nil {
+		var hashOnly HashOnly
+		if limiter != nil {
+			hashOnly = limiter.HashOnly
+		}
+		if err := b.processAccountCode(n, hashOnly); err != nil {
 			return err
 		}
 		if err := b.processAccountStorage(n, storageKey, limiter); err != nil {