func traverseLink(addr []byte, name, key string, state *monkstate.State, dir int) ([]byte, []byte) { bigBase := big.NewInt(0) obj := state.GetStateObject(addr) base := VariName(name) // key should be trailing 20 bytes if l := len(key); l > 20 { key = key[l-20:] } // get slot for this keyed element of linked list keyBytes := monkutil.PackTxDataArgs2(key) keyBytesShift := append(keyBytes, []byte{1, 0, 0}...)[3:] slotBig := bigBase.Add(monkutil.BigD(base), monkutil.BigD(keyBytesShift)) // next locator is this slot plus 2 // prev locator is this slot plus 1 slotNextLoc := bigBase.Add(slotBig, big.NewInt(int64(dir))) slotNext := obj.GetStorage(slotNextLoc) if slotNext.IsNil() { slotNextLoc = monkutil.BigD(append(base[:len(base)-1], byte(StdVarSize+1))) slotNext = obj.GetStorage(slotNextLoc) } keyB := slotNext.Bytes() keyB = keyB[9:29] // value is right at slot v := obj.GetStorage(slotNext.BigInt()) return keyB, v.Bytes() }
func getLinkedListHead(obj *monkstate.StateObject, base []byte) ([]byte, []byte) { headLocLoc := append(base[:len(base)-1], byte(StdVarSize+1)) headLoc := obj.GetStorage(monkutil.BigD(headLocLoc)) headKey := headLoc.Bytes()[9:29] head := obj.GetStorage(headLoc.BigInt()) return headKey, head.Bytes() }
// Return an element from a linked list func GetLinkedListElement(addr []byte, name, key string, state *monkstate.State) []byte { bigBase := big.NewInt(0) obj := state.GetStateObject(addr) base := VariName(name) // key should be trailing 20 bytes if l := len(key); l > 20 { key = key[l-20:] } // get slot for this keyed element of linked list keyBytes := monkutil.PackTxDataArgs2(key) keyBytesShift := append(keyBytes, []byte{1, 0, 0}...)[3:] slotBig := bigBase.Add(monkutil.BigD(base), monkutil.BigD(keyBytesShift)) // value is right at slot v := obj.GetStorage(slotBig) return v.Bytes() }
// key must come as hex!!!!!! // Return an element from keyed array type func GetKeyedArrayElement(addr []byte, name, key string, index int, state *monkstate.State) []byte { bigBase := big.NewInt(0) bigBase2 := big.NewInt(0) obj := state.GetStateObject(addr) base := VariName(name) // how big are the elements stored in this array: sizeLocator := make([]byte, len(base)) copy(sizeLocator, base) sizeLocator = append(sizeLocator[:31], byte(StdVarSize+1)) elementSizeBytes := (obj.GetStorage(monkutil.BigD(sizeLocator))).Bytes() elementSize := monkutil.BigD(elementSizeBytes).Uint64() // key should be trailing 20 bytes if len(key) >= 2 && key[:2] == "0x" { key = key[2:] } if l := len(key); l > 40 { key = key[l-40:] } // what slot does the array start at: keyBytes := monkutil.PackTxDataArgs2("0x" + key) keyBytesShift := append(keyBytes[3:], []byte{1, 0, 0}...) slotBig := bigBase.Add(monkutil.BigD(base), monkutil.BigD(keyBytesShift)) //numElements := obj.GetStorage(slotBig) // which slot (row), and where in that slot (col) is the element we want: entriesPerRow := int64(256 / elementSize) rowN := int64(index) / entriesPerRow colN := int64(index) % entriesPerRow row := bigBase.Add(big.NewInt(1), bigBase.Add(slotBig, big.NewInt(rowN))).Bytes() rowStorage := (obj.GetStorage(monkutil.BigD(row))).Bytes() rowStorageBig := monkutil.BigD(rowStorage) elSizeBig := monkutil.BigD(elementSizeBytes) // row storage gives us a big number, from which we need to pull // an element of size elementsize. // so divide it by 2^(colN*elSize) and take modulo 2^elsize // divide row storage by 2^(colN*elSize) colBig := bigBase.Exp(big.NewInt(2), bigBase.Mul(elSizeBig, big.NewInt(colN)), nil) r := bigBase.Div(rowStorageBig, colBig) w := bigBase2.Exp(big.NewInt(2), elSizeBig, nil) v := bigBase.Mod(r, w) return v.Bytes() }
func GetLinkedList(addr []byte, name string, state *monkstate.State) *ring.Ring { bigBase := big.NewInt(0) obj := state.GetStateObject(addr) base := VariName(name) n := getLinkedListLength(obj, base) nextLocLoc := monkutil.BigD(append(base[:len(base)-1], byte(StdVarSize+1))) nextLoc := obj.GetStorage(nextLocLoc).BigInt() r := ring.New(n) for i := 0; i < n; i++ { r.Value = obj.GetStorage(nextLoc) r = r.Next() nextLocLoc = bigBase.Add(nextLoc, big.NewInt(2)) nextLoc = obj.GetStorage(nextLocLoc).BigInt() } return r }
// Single Type Variable. // (+ @@variname 1) func GetSingle(addr []byte, name string, state *monkstate.State) []byte { obj := state.GetStateObject(addr) base := VariName(name) base[31] = byte(StdVarSize + 1) return (obj.GetStorage(monkutil.BigD(base))).Bytes() }
func getLinkedListLength(obj *monkstate.StateObject, base []byte) int { nEleLoc := append(base[:len(base)-1], byte(StdVarSize+3)) nEl := obj.GetStorage(monkutil.BigD(nEleLoc)) return int(nEl.Uint()) }