diff options
Diffstat (limited to 'ethutil')
-rw-r--r-- | ethutil/db.go | 1 | ||||
-rw-r--r-- | ethutil/parsing.go | 102 | ||||
-rw-r--r-- | ethutil/parsing_test.go | 4 | ||||
-rw-r--r-- | ethutil/trie.go | 85 | ||||
-rw-r--r-- | ethutil/trie_test.go | 24 |
5 files changed, 163 insertions, 53 deletions
diff --git a/ethutil/db.go b/ethutil/db.go index 3681c4b05..b11d5d726 100644 --- a/ethutil/db.go +++ b/ethutil/db.go @@ -4,6 +4,7 @@ package ethutil type Database interface { Put(key []byte, value []byte) Get(key []byte) ([]byte, error) + Delete(key []byte) error LastKnownTD() []byte Close() Print() diff --git a/ethutil/parsing.go b/ethutil/parsing.go index b43dac064..553bb9717 100644 --- a/ethutil/parsing.go +++ b/ethutil/parsing.go @@ -7,57 +7,57 @@ import ( // Op codes var OpCodes = map[string]byte{ - "STOP": 0, - "ADD": 1, - "MUL": 2, - "SUB": 3, - "DIV": 4, - "SDIV": 5, - "MOD": 6, - "SMOD": 7, - "EXP": 8, - "NEG": 9, - "LT": 10, - "LE": 11, - "GT": 12, - "GE": 13, - "EQ": 14, - "NOT": 15, - "MYADDRESS": 16, - "TXSENDER": 17, - "TXVALUE": 18, - "TXFEE": 19, - "TXDATAN": 20, - "TXDATA": 21, - "BLK_PREVHASH": 22, - "BLK_COINBASE": 23, - "BLK_TIMESTAMP": 24, - "BLK_NUMBER": 25, - "BLK_DIFFICULTY": 26, - "BASEFEE": 27, - "SHA256": 32, - "RIPEMD160": 33, - "ECMUL": 34, - "ECADD": 35, - "ECSIGN": 36, - "ECRECOVER": 37, - "ECVALID": 38, - "SHA3": 39, - "PUSH": 48, - "POP": 49, - "DUP": 50, - "SWAP": 51, - "MLOAD": 52, - "MSTORE": 53, - "SLOAD": 54, - "SSTORE": 55, - "JMP": 56, - "JMPI": 57, - "IND": 58, - "EXTRO": 59, - "BALANCE": 60, - "MKTX": 61, - "SUICIDE": 62, + "STOP": 0x00, + "ADD": 0x01, + "MUL": 0x02, + "SUB": 0x03, + "DIV": 0x04, + "SDIV": 0x05, + "MOD": 0x06, + "SMOD": 0x07, + "EXP": 0x08, + "NEG": 0x09, + "LT": 0x0a, + "LE": 0x0b, + "GT": 0x0c, + "GE": 0x0d, + "EQ": 0x0e, + "NOT": 0x0f, + "MYADDRESS": 0x10, + "TXSENDER": 0x11, + "TXVALUE": 0x12, + "TXDATAN": 0x13, + "TXDATA": 0x14, + "BLK_PREVHASH": 0x15, + "BLK_COINBASE": 0x16, + "BLK_TIMESTAMP": 0x17, + "BLK_NUMBER": 0x18, + "BLK_DIFFICULTY": 0x19, + "BLK_NONCE": 0x1a, + "BASEFEE": 0x1b, + "SHA256": 0x20, + "RIPEMD160": 0x21, + "ECMUL": 0x22, + "ECADD": 0x23, + "ECSIGN": 0x24, + "ECRECOVER": 0x25, + "ECVALID": 0x26, + "SHA3": 0x27, + "PUSH": 0x30, + "POP": 0x31, + "DUP": 0x32, + "SWAP": 0x33, + "MLOAD": 0x34, + "MSTORE": 0x35, + "SLOAD": 0x36, + "SSTORE": 0x37, + "JMP": 0x38, + "JMPI": 0x39, + "IND": 0x3a, + "EXTRO": 0x3b, + "BALANCE": 0x3c, + "MKTX": 0x3d, + "SUICIDE": 0x3f, } func IsOpCode(s string) bool { diff --git a/ethutil/parsing_test.go b/ethutil/parsing_test.go index 69a5e9016..6b59777e6 100644 --- a/ethutil/parsing_test.go +++ b/ethutil/parsing_test.go @@ -1,5 +1,6 @@ package ethutil +/* import ( "math" "testing" @@ -19,14 +20,13 @@ func TestCompile(t *testing.T) { } func TestValidInstr(t *testing.T) { - /* op, args, err := Instr("68163") if err != nil { t.Error("Error decoding instruction") } - */ } func TestInvalidInstr(t *testing.T) { } +*/ diff --git a/ethutil/trie.go b/ethutil/trie.go index 322f77647..83527d364 100644 --- a/ethutil/trie.go +++ b/ethutil/trie.go @@ -70,6 +70,12 @@ func (cache *Cache) Get(key []byte) *Value { return value } +func (cache *Cache) Delete(key []byte) { + delete(cache.nodes, string(key)) + + cache.db.Delete(key) +} + func (cache *Cache) Commit() { // Don't try to commit if it isn't dirty if !cache.IsDirty { @@ -413,3 +419,82 @@ func (t *Trie) Copy() *Trie { return trie } + +type TrieIterator struct { + trie *Trie + key string + value string + + shas [][]byte + values []string +} + +func (t *Trie) NewIterator() *TrieIterator { + return &TrieIterator{trie: t} +} + +// Some time in the near future this will need refactoring :-) +// XXX Note to self, IsSlice == inline node. Str == sha3 to node +func (it *TrieIterator) workNode(currentNode *Value) { + if currentNode.Len() == 2 { + k := CompactDecode(currentNode.Get(0).Str()) + + if currentNode.Get(1).IsSlice() { + it.workNode(currentNode.Get(1)) + } else { + if k[len(k)-1] == 16 { + it.values = append(it.values, currentNode.Get(1).Str()) + } else { + it.shas = append(it.shas, currentNode.Get(1).Bytes()) + it.getNode(currentNode.Get(1).Bytes()) + } + } + } else { + for i := 0; i < currentNode.Len(); i++ { + if i == 16 && currentNode.Get(i).Len() != 0 { + it.values = append(it.values, currentNode.Get(i).Str()) + } else { + if currentNode.Get(i).IsSlice() { + it.workNode(currentNode.Get(i)) + } else { + val := currentNode.Get(i).Str() + if val != "" { + it.shas = append(it.shas, currentNode.Get(1).Bytes()) + it.getNode([]byte(val)) + } + } + } + } + } +} + +func (it *TrieIterator) getNode(node []byte) { + currentNode := it.trie.cache.Get(node) + it.workNode(currentNode) +} + +func (it *TrieIterator) Collect() [][]byte { + if it.trie.Root == "" { + return nil + } + + it.getNode(NewValue(it.trie.Root).Bytes()) + + return it.shas +} + +func (it *TrieIterator) Purge() int { + shas := it.Collect() + for _, sha := range shas { + it.trie.cache.Delete(sha) + } + return len(it.values) +} + +func (it *TrieIterator) Key() string { + return "" +} + +func (it *TrieIterator) Value() string { + return "" +} diff --git a/ethutil/trie_test.go b/ethutil/trie_test.go index 9d2c8e19f..c3a8f224d 100644 --- a/ethutil/trie_test.go +++ b/ethutil/trie_test.go @@ -1,6 +1,7 @@ package ethutil import ( + "fmt" "reflect" "testing" ) @@ -21,6 +22,10 @@ func (db *MemDatabase) Put(key []byte, value []byte) { func (db *MemDatabase) Get(key []byte) ([]byte, error) { return db.db[string(key)], nil } +func (db *MemDatabase) Delete(key []byte) error { + delete(db.db, string(key)) + return nil +} func (db *MemDatabase) Print() {} func (db *MemDatabase) Close() {} func (db *MemDatabase) LastKnownTD() []byte { return nil } @@ -148,3 +153,22 @@ func TestTrieDeleteWithValue(t *testing.T) { } } + +func TestTrieIterator(t *testing.T) { + _, trie := New() + trie.Update("c", LONG_WORD) + trie.Update("ca", LONG_WORD) + trie.Update("cat", LONG_WORD) + + it := trie.NewIterator() + fmt.Println("purging") + fmt.Println("len =", it.Purge()) + /* + for it.Next() { + k := it.Key() + v := it.Value() + + fmt.Println(k, v) + } + */ +} |