// Converts string to simple numeric format std::string strToNumeric(std::string inp) { std::string o = "0"; if (inp == "") { o = ""; } else if ((inp[0] == '"' && inp[inp.length()-1] == '"') || (inp[0] == '\'' && inp[inp.length()-1] == '\'')) { for (unsigned i = 1; i < inp.length() - 1; i++) { o = decimalAdd(decimalMul(o,"256"), unsignedToDecimal((unsigned char)inp[i])); } } else if (inp.substr(0,2) == "0x") { for (unsigned i = 2; i < inp.length(); i++) { int dig = std::string("0123456789abcdef").find(inp[i]); if (dig < 0) return ""; o = decimalAdd(decimalMul(o,"16"), unsignedToDecimal(dig)); } } else { bool isPureNum = true; for (unsigned i = 0; i < inp.length(); i++) { isPureNum = isPureNum && inp[i] >= '0' && inp[i] <= '9'; } o = isPureNum ? inp : ""; } return o; }
//Subtract the two strings representing decimal values std::string decimalSub(const std::string &a, const std::string &b) { if (b == "0") return a; if (b == a) return "0"; std::string c = prependZeros(b, a.length() - b.length()); for (unsigned i = 0; i < c.length(); i++) c[i] = '0' + ('9' - c[i]); std::string o = decimalAdd(decimalAdd(a, c).substr(1), "1"); return removeRedundantLeadingZeros(o); }
//Subtract the two strings representing decimal values std::string decimalSub(std::string a, std::string b) { if (b == "0") return a; if (b == a) return "0"; while (b.length() < a.length()) b = "0" + b; std::string c = b; for (unsigned i = 0; i < c.length(); i++) c[i] = '0' + ('9' - c[i]); std::string o = decimalAdd(decimalAdd(a, c).substr(1), "1"); while (o.size() > 1 && o[0] == '0') o = o.substr(1); return o; }
//Divide the two strings representing decimal values std::string decimalDiv(std::string a, std::string b) { std::string c = b; if (decimalGt(c, a)) return "0"; int zeroes = -1; while (decimalGt(a, c, true)) { zeroes += 1; c = c + "0"; } c = c.substr(0, c.size() - 1); std::string quot = "0"; while (decimalGt(a, c, true)) { a = decimalSub(a, c); quot = decimalAdd(quot, "1"); } for (int i = 0; i < zeroes; i++) quot += "0"; return decimalAdd(quot, decimalDiv(a, b)); }
//Multiply two strings representing decimal values std::string decimalMul(std::string a, std::string b) { std::string o = "0"; for (unsigned i = 0; i < b.length(); i++) { std::string n = decimalDigitMul(a, b[i] - '0'); if (n != "0") { for (unsigned j = i + 1; j < b.length(); j++) n += "0"; } o = decimalAdd(o, n); } return o; }
// Converts binary transaction data into a list of integer values std::vector<std::string> decodeDatalist(std::string ser) { std::vector<std::string> out; for (unsigned i = 0; i < ser.length(); i+= 32) { std::string o = "0"; for (unsigned j = i; j < i + 32; j++) { int vj = (int)(unsigned char)ser[j]; o = decimalAdd(decimalMul(o, "256"), unsignedToDecimal(vj)); } out.push_back(o); } return out; }
//Helper function for decimalMul std::string decimalDigitMul(std::string a, int dig) { if (dig == 0) return "0"; else return decimalAdd(a, decimalDigitMul(a, dig - 1)); }
//Helper function for decimalMul static std::string decimalDigitMul(const std::string &a, int dig) { if (dig == 0) return "0"; else return decimalAdd(a, decimalDigitMul(a, dig - 1)); }
// Populate an svObj with the arguments needed to determine // the storage position of a node svObj getStorageVars(svObj pre, Node node, std::string prefix, int index) { Metadata m = node.metadata; if (!pre.globalOffset.size()) pre.globalOffset = "0"; std::vector<Node> h; std::vector<std::string> coefficients; // Array accesses or atoms if (node.val == "access" || node.type == TOKEN) { std::string tot = "1"; h = listfyStorageAccess(node); coefficients.push_back("1"); for (unsigned i = h.size() - 1; i >= 1; i--) { // Array sizes must be constant or at least arithmetically // evaluable at compile time if (!isPureArithmetic(h[i])) err("Array size must be fixed value", m); // Create a list of the coefficient associated with each // array index coefficients.push_back(decimalMul(coefficients.back(), h[i].val)); } } // Tuples else { int startc; // Handle the (fun <fun_astnode> args...) case if (node.val == "fun") { startc = 1; h = listfyStorageAccess(node.args[0]); } // Handle the (<fun_name> args...) case, which // the serpent parser produces when the function // is a simple name and not a complex astnode else { startc = 0; h = listfyStorageAccess(token(node.val, m)); } svObj sub = pre; sub.globalOffset = "0"; // Evaluate tuple elements recursively for (unsigned i = startc; i < node.args.size(); i++) { sub = getStorageVars(sub, node.args[i], prefix+h[0].val.substr(2)+".", i-startc); } coefficients.push_back(sub.globalOffset); for (unsigned i = h.size() - 1; i >= 1; i--) { // Array sizes must be constant or at least arithmetically // evaluable at compile time if (!isPureArithmetic(h[i])) err("Array size must be fixed value", m); // Create a list of the coefficient associated with each // array index coefficients.push_back(decimalMul(coefficients.back(), h[i].val)); } pre.offsets = sub.offsets; pre.coefficients = sub.coefficients; pre.nonfinal = sub.nonfinal; pre.nonfinal[prefix+h[0].val.substr(2)] = true; } pre.coefficients[prefix+h[0].val.substr(2)] = coefficients; pre.offsets[prefix+h[0].val.substr(2)] = pre.globalOffset; pre.indices[prefix+h[0].val.substr(2)] = index; if (decimalGt(tt176, coefficients.back())) pre.globalOffset = decimalAdd(pre.globalOffset, coefficients.back()); return pre; }