Merge branch 'develop' of https://github.com/tendermint/tendermint into develop
This commit is contained in:
commit
f7639bf105
|
@ -14,6 +14,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/tendermint/tendermint/binary"
|
"github.com/tendermint/tendermint/binary"
|
||||||
. "github.com/tendermint/tendermint/cmd/barak/types"
|
. "github.com/tendermint/tendermint/cmd/barak/types"
|
||||||
|
@ -41,12 +42,14 @@ var barak = struct {
|
||||||
nonce uint64
|
nonce uint64
|
||||||
processes map[string]*pcm.Process
|
processes map[string]*pcm.Process
|
||||||
validators []Validator
|
validators []Validator
|
||||||
|
rootDir string
|
||||||
}{
|
}{
|
||||||
mtx: sync.Mutex{},
|
mtx: sync.Mutex{},
|
||||||
pid: os.Getpid(),
|
pid: os.Getpid(),
|
||||||
nonce: 0,
|
nonce: 0,
|
||||||
processes: make(map[string]*pcm.Process),
|
processes: make(map[string]*pcm.Process),
|
||||||
validators: nil,
|
validators: nil,
|
||||||
|
rootDir: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -72,6 +75,13 @@ func main() {
|
||||||
}
|
}
|
||||||
barak.nonce = options.StartNonce
|
barak.nonce = options.StartNonce
|
||||||
barak.validators = options.Validators
|
barak.validators = options.Validators
|
||||||
|
barak.rootDir = os.Getenv("BRKROOT")
|
||||||
|
if barak.rootDir == "" {
|
||||||
|
barak.rootDir = os.Getenv("HOME") + "/.barak"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write pid to file.
|
||||||
|
AtomicWriteFile(barak.rootDir+"/pidfile", []byte(Fmt("%v", barak.pid)))
|
||||||
|
|
||||||
// Debug.
|
// Debug.
|
||||||
fmt.Printf("Options: %v\n", options)
|
fmt.Printf("Options: %v\n", options)
|
||||||
|
@ -111,7 +121,7 @@ func Run(authCommand AuthCommand) (interface{}, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
log.Info(Fmt("Run() received command %v", reflect.TypeOf(command)))
|
log.Info(Fmt("Run() received command %v:\n%v", reflect.TypeOf(command), command))
|
||||||
// Issue command
|
// Issue command
|
||||||
switch c := command.(type) {
|
switch c := command.(type) {
|
||||||
case CommandRunProcess:
|
case CommandRunProcess:
|
||||||
|
@ -174,7 +184,12 @@ func RunProcess(wait bool, label string, execPath string, args []string, input s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, create one.
|
// Otherwise, create one.
|
||||||
proc, err := pcm.Create(pcm.ProcessModeDaemon, label, execPath, args, input)
|
err := EnsureDir(barak.rootDir + "/outputs")
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to create outputs dir: %v", err)
|
||||||
|
}
|
||||||
|
outPath := Fmt("%v/outputs/%v_%v.out", barak.rootDir, label, time.Now().Format("2006_01_02_15_04_05_MST"))
|
||||||
|
proc, err := pcm.Create(pcm.ProcessModeDaemon, label, execPath, args, input, outPath)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
barak.processes[label] = proc
|
barak.processes[label] = proc
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,25 +17,31 @@ var Config = struct {
|
||||||
PrivKey acm.PrivKey
|
PrivKey acm.PrivKey
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
var (
|
|
||||||
configFlag = cli.StringFlag{
|
|
||||||
Name: "config-file",
|
|
||||||
Value: ".debora/config.json",
|
|
||||||
Usage: "config file",
|
|
||||||
}
|
|
||||||
waitFlag = cli.BoolFlag{
|
|
||||||
Name: "wait",
|
|
||||||
Usage: "whether to wait for termination",
|
|
||||||
}
|
|
||||||
inputFlag = cli.StringFlag{
|
|
||||||
Name: "input",
|
|
||||||
Value: "",
|
|
||||||
Usage: "input to the program (e.g. stdin)",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Printf("New Debora Process (PID: %d)\n", os.Getpid())
|
fmt.Printf("New Debora Process (PID: %d)\n", os.Getpid())
|
||||||
|
|
||||||
|
rootDir := os.Getenv("DEBROOT")
|
||||||
|
if rootDir == "" {
|
||||||
|
rootDir = os.Getenv("HOME") + "/.debora"
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
configFlag = cli.StringFlag{
|
||||||
|
Name: "config-file",
|
||||||
|
Value: rootDir + "/config.json",
|
||||||
|
Usage: "config file",
|
||||||
|
}
|
||||||
|
waitFlag = cli.BoolFlag{
|
||||||
|
Name: "wait",
|
||||||
|
Usage: "whether to wait for termination",
|
||||||
|
}
|
||||||
|
inputFlag = cli.StringFlag{
|
||||||
|
Name: "input",
|
||||||
|
Value: "",
|
||||||
|
Usage: "input to the program (e.g. stdin)",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
app.Name = "debora"
|
app.Name = "debora"
|
||||||
app.Usage = "summons commands to barak"
|
app.Usage = "summons commands to barak"
|
||||||
|
@ -171,9 +177,14 @@ func cliListProcesses(c *cli.Context) {
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("%v processes:\n", remote)
|
fmt.Printf("%v processes:\n", remote)
|
||||||
for _, proc := range response.Processes {
|
for _, proc := range response.Processes {
|
||||||
fmt.Printf(" \"%v\" => `%v` (%v) start:%v end:%v output:%v\n",
|
startTimeStr := Green(proc.StartTime.String())
|
||||||
proc.Label, proc.ExecPath, proc.Pid,
|
endTimeStr := proc.EndTime.String()
|
||||||
proc.StartTime, proc.EndTime, proc.OutputPath)
|
if !proc.EndTime.IsZero() {
|
||||||
|
endTimeStr = Red(endTimeStr)
|
||||||
|
}
|
||||||
|
fmt.Printf(" %v start:%v end:%v output:%v\n",
|
||||||
|
RightPadString(Fmt("\"%v\" => `%v` (%v)", proc.Label, proc.ExecPath, proc.Pid), 40),
|
||||||
|
startTimeStr, endTimeStr, proc.OutputPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ANSIReset = "\x1b[0m"
|
||||||
|
ANSIBright = "\x1b[1m"
|
||||||
|
ANSIDim = "\x1b[2m"
|
||||||
|
ANSIUnderscore = "\x1b[4m"
|
||||||
|
ANSIBlink = "\x1b[5m"
|
||||||
|
ANSIReverse = "\x1b[7m"
|
||||||
|
ANSIHidden = "\x1b[8m"
|
||||||
|
|
||||||
|
ANSIFgBlack = "\x1b[30m"
|
||||||
|
ANSIFgRed = "\x1b[31m"
|
||||||
|
ANSIFgGreen = "\x1b[32m"
|
||||||
|
ANSIFgYellow = "\x1b[33m"
|
||||||
|
ANSIFgBlue = "\x1b[34m"
|
||||||
|
ANSIFgMagenta = "\x1b[35m"
|
||||||
|
ANSIFgCyan = "\x1b[36m"
|
||||||
|
ANSIFgWhite = "\x1b[37m"
|
||||||
|
|
||||||
|
ANSIBgBlack = "\x1b[40m"
|
||||||
|
ANSIBgRed = "\x1b[41m"
|
||||||
|
ANSIBgGreen = "\x1b[42m"
|
||||||
|
ANSIBgYellow = "\x1b[43m"
|
||||||
|
ANSIBgBlue = "\x1b[44m"
|
||||||
|
ANSIBgMagenta = "\x1b[45m"
|
||||||
|
ANSIBgCyan = "\x1b[46m"
|
||||||
|
ANSIBgWhite = "\x1b[47m"
|
||||||
|
)
|
||||||
|
|
||||||
|
// color the string s with color 'color'
|
||||||
|
// unless s is already colored
|
||||||
|
func treat(s string, color string) string {
|
||||||
|
if len(s) > 2 && s[:2] == "\x1b[" {
|
||||||
|
return s
|
||||||
|
} else {
|
||||||
|
return color + s + ANSIReset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func treatAll(color string, args ...interface{}) string {
|
||||||
|
var parts []string
|
||||||
|
for _, arg := range args {
|
||||||
|
parts = append(parts, treat(fmt.Sprintf("%v", arg), color))
|
||||||
|
}
|
||||||
|
return strings.Join(parts, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Black(args ...interface{}) string {
|
||||||
|
return treatAll(ANSIFgBlack, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Red(args ...interface{}) string {
|
||||||
|
return treatAll(ANSIFgRed, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Green(args ...interface{}) string {
|
||||||
|
return treatAll(ANSIFgGreen, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Yellow(args ...interface{}) string {
|
||||||
|
return treatAll(ANSIFgYellow, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Blue(args ...interface{}) string {
|
||||||
|
return treatAll(ANSIFgBlue, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Magenta(args ...interface{}) string {
|
||||||
|
return treatAll(ANSIFgMagenta, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Cyan(args ...interface{}) string {
|
||||||
|
return treatAll(ANSIFgCyan, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func White(args ...interface{}) string {
|
||||||
|
return treatAll(ANSIFgWhite, args...)
|
||||||
|
}
|
|
@ -22,10 +22,18 @@ func (p Uint64Slice) Search(x uint64) int { return SearchUint64s(p, x) }
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
func PutUint64(dest []byte, i uint64) {
|
func PutUint64LE(dest []byte, i uint64) {
|
||||||
binary.LittleEndian.PutUint64(dest, i)
|
binary.LittleEndian.PutUint64(dest, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUint64(src []byte) uint64 {
|
func GetUint64LE(src []byte) uint64 {
|
||||||
return binary.LittleEndian.Uint64(src)
|
return binary.LittleEndian.Uint64(src)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PutUint64BE(dest []byte, i uint64) {
|
||||||
|
binary.BigEndian.PutUint64(dest, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUint64BE(src []byte) uint64 {
|
||||||
|
return binary.BigEndian.Uint64(src)
|
||||||
|
}
|
||||||
|
|
34
common/os.go
34
common/os.go
|
@ -2,6 +2,7 @@ package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
)
|
)
|
||||||
|
@ -26,3 +27,36 @@ func Exit(s string) {
|
||||||
fmt.Printf(s + "\n")
|
fmt.Printf(s + "\n")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Writes to newBytes to filePath.
|
||||||
|
// Guaranteed not to lose *both* oldBytes and newBytes,
|
||||||
|
// (assuming that the OS is perfect)
|
||||||
|
func AtomicWriteFile(filePath string, newBytes []byte) error {
|
||||||
|
// If a file already exists there, copy to filePath+".bak" (overwrite anything)
|
||||||
|
if _, err := os.Stat(filePath); !os.IsNotExist(err) {
|
||||||
|
fileBytes, err := ioutil.ReadFile(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to read file %v. %v", filePath, err)
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(filePath+".bak", fileBytes, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to write file %v. %v", filePath+".bak", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Write newBytes to filePath.
|
||||||
|
err := ioutil.WriteFile(filePath, newBytes, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to write file %v. %v", filePath, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func EnsureDir(dir string) error {
|
||||||
|
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||||
|
err := os.MkdirAll(dir, 0700)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Could not create directory %v. %v", dir, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,23 @@ package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Fmt = fmt.Sprintf
|
var Fmt = fmt.Sprintf
|
||||||
|
|
||||||
|
func RightPadString(s string, totalLength int) string {
|
||||||
|
remaining := totalLength - len(s)
|
||||||
|
if remaining > 0 {
|
||||||
|
s = s + strings.Repeat(" ", remaining)
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func LeftPadString(s string, totalLength int) string {
|
||||||
|
remaining := totalLength - len(s)
|
||||||
|
if remaining > 0 {
|
||||||
|
s = strings.Repeat(" ", remaining) + s
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
|
||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -30,9 +29,9 @@ func (w Word256) Compare(other Word256) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Uint64ToWord256(i uint64) Word256 {
|
func Uint64ToWord256(i uint64) Word256 {
|
||||||
word := Word256{}
|
buf := [8]byte{}
|
||||||
PutUint64(word[:], i)
|
PutUint64BE(buf[:], i)
|
||||||
return word
|
return LeftPadWord256(buf[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func RightPadWord256(bz []byte) (word Word256) {
|
func RightPadWord256(bz []byte) (word Word256) {
|
||||||
|
@ -46,7 +45,8 @@ func LeftPadWord256(bz []byte) (word Word256) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Uint64FromWord256(word Word256) uint64 {
|
func Uint64FromWord256(word Word256) uint64 {
|
||||||
return binary.LittleEndian.Uint64(word[:])
|
buf := word.Postfix(8)
|
||||||
|
return GetUint64BE(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
|
|
|
@ -20,7 +20,7 @@ func App() *confer.Config {
|
||||||
appMtx.Lock()
|
appMtx.Lock()
|
||||||
defer appMtx.Unlock()
|
defer appMtx.Unlock()
|
||||||
if app == nil {
|
if app == nil {
|
||||||
Init(".tendermint")
|
Init("")
|
||||||
}
|
}
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ func SetApp(a *confer.Config) {
|
||||||
var defaultConfig = `# This is a TOML config file.
|
var defaultConfig = `# This is a TOML config file.
|
||||||
# For more information, see https://github.com/toml-lang/toml
|
# For more information, see https://github.com/toml-lang/toml
|
||||||
|
|
||||||
|
Moniker = "anonymous"
|
||||||
Network = "tendermint_testnet0"
|
Network = "tendermint_testnet0"
|
||||||
ListenAddr = "0.0.0.0:8080"
|
ListenAddr = "0.0.0.0:8080"
|
||||||
# First node to connect to. Command-line overridable.
|
# First node to connect to. Command-line overridable.
|
||||||
|
@ -66,17 +67,47 @@ ListenAddr = "127.0.0.1:8081"
|
||||||
var DefaultGenesis = `{
|
var DefaultGenesis = `{
|
||||||
"Accounts": [
|
"Accounts": [
|
||||||
{
|
{
|
||||||
"Address": "29BF3A0A13001A0D23533386BE03E74923AF1179",
|
"Address": "69988763FCF806AC35D1A2F9C4885B7DD7B0599C",
|
||||||
"Amount": 2099900000000000
|
"Amount": 2099600000000000
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"Validators": [
|
"Validators": [
|
||||||
{
|
{
|
||||||
"PubKey": [1, "3A2C5C341FFC1D5F7AB518519FF8289D3BFAB82DFD6E167B926FAD72C1BF10F8"],
|
"PubKey": [1, "323A31EB01877858592AB7D593E9447110AFCD3ACF280D60C4F8E7C04FACC955"],
|
||||||
"Amount": 100000000000,
|
"Amount": 100000000000,
|
||||||
"UnbondTo": [
|
"UnbondTo": [
|
||||||
{
|
{
|
||||||
"Address": "29BF3A0A13001A0D23533386BE03E74923AF1179",
|
"Address": "69988763FCF806AC35D1A2F9C4885B7DD7B0599C",
|
||||||
|
"Amount": 100000000000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PubKey": [1, "DD2206E8F889EED3ABAAECEB2D18962D062A887346241820493FFE3B1DEF255D"],
|
||||||
|
"Amount": 100000000000,
|
||||||
|
"UnbondTo": [
|
||||||
|
{
|
||||||
|
"Address": "69988763FCF806AC35D1A2F9C4885B7DD7B0599C",
|
||||||
|
"Amount": 100000000000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PubKey": [1, "1B3256A3754FC6AB01110C166199A2F619E2D76DB3EE751E376FE404AC9FDCFF"],
|
||||||
|
"Amount": 100000000000,
|
||||||
|
"UnbondTo": [
|
||||||
|
{
|
||||||
|
"Address": "69988763FCF806AC35D1A2F9C4885B7DD7B0599C",
|
||||||
|
"Amount": 100000000000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PubKey": [1, "62CF1048BAEBB4FFFF360D5E896E3F4EC72D03D55183596931ED14995D512926"],
|
||||||
|
"Amount": 100000000000,
|
||||||
|
"UnbondTo": [
|
||||||
|
{
|
||||||
|
"Address": "69988763FCF806AC35D1A2F9C4885B7DD7B0599C",
|
||||||
"Amount": 100000000000
|
"Amount": 100000000000
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -86,6 +117,7 @@ var DefaultGenesis = `{
|
||||||
|
|
||||||
// NOTE: If you change this, maybe also change defaultConfig
|
// NOTE: If you change this, maybe also change defaultConfig
|
||||||
func initDefaults(rootDir string) {
|
func initDefaults(rootDir string) {
|
||||||
|
app.SetDefault("Moniker", "anonymous")
|
||||||
app.SetDefault("Network", "tendermint_testnet0")
|
app.SetDefault("Network", "tendermint_testnet0")
|
||||||
app.SetDefault("ListenAddr", "0.0.0.0:8080")
|
app.SetDefault("ListenAddr", "0.0.0.0:8080")
|
||||||
app.SetDefault("DB.Backend", "leveldb")
|
app.SetDefault("DB.Backend", "leveldb")
|
||||||
|
@ -104,7 +136,13 @@ func initDefaults(rootDir string) {
|
||||||
|
|
||||||
func Init(rootDir string) {
|
func Init(rootDir string) {
|
||||||
|
|
||||||
// Get RootDir
|
// Get rootdir
|
||||||
|
if rootDir == "" {
|
||||||
|
rootDir = os.Getenv("TMROOT")
|
||||||
|
}
|
||||||
|
if rootDir == "" {
|
||||||
|
rootDir = os.Getenv("HOME") + "/.tendermint"
|
||||||
|
}
|
||||||
configFile := path.Join(rootDir, "config.toml")
|
configFile := path.Join(rootDir, "config.toml")
|
||||||
genesisFile := path.Join(rootDir, "genesis.json")
|
genesisFile := path.Join(rootDir, "genesis.json")
|
||||||
|
|
||||||
|
|
|
@ -318,10 +318,10 @@ func (cs *ConsensusState) stepTransitionRoutine() {
|
||||||
// For clarity, all state transitions that happen after some timeout are here.
|
// For clarity, all state transitions that happen after some timeout are here.
|
||||||
// Schedule the next action by pushing a RoundAction{} to cs.runActionCh.
|
// Schedule the next action by pushing a RoundAction{} to cs.runActionCh.
|
||||||
scheduleNextAction := func() {
|
scheduleNextAction := func() {
|
||||||
|
rs := cs.getRoundState()
|
||||||
go func() {
|
go func() {
|
||||||
// NOTE: We can push directly to runActionCh because
|
// NOTE: We can push directly to runActionCh because
|
||||||
// we're running in a separate goroutine, which avoids deadlocks.
|
// we're running in a separate goroutine, which avoids deadlocks.
|
||||||
rs := cs.getRoundState()
|
|
||||||
round, roundStartTime, RoundDuration, _, elapsedRatio := calcRoundInfo(rs.StartTime)
|
round, roundStartTime, RoundDuration, _, elapsedRatio := calcRoundInfo(rs.StartTime)
|
||||||
log.Debug("Scheduling next action", "height", rs.Height, "round", round, "step", rs.Step, "roundStartTime", roundStartTime, "elapsedRatio", elapsedRatio)
|
log.Debug("Scheduling next action", "height", rs.Height, "round", round, "step", rs.Step, "roundStartTime", roundStartTime, "elapsedRatio", elapsedRatio)
|
||||||
switch rs.Step {
|
switch rs.Step {
|
||||||
|
@ -358,7 +358,12 @@ func (cs *ConsensusState) stepTransitionRoutine() {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduleNextAction()
|
if cs.getRoundState().Step < RoundStepCommit {
|
||||||
|
scheduleNextAction()
|
||||||
|
} else {
|
||||||
|
// Race condition with receipt of commits, maybe.
|
||||||
|
// We shouldn't have to schedule anything.
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: All ConsensusState.RunAction*() calls come from here.
|
// NOTE: All ConsensusState.RunAction*() calls come from here.
|
||||||
// Since only one routine calls them, it is safe to assume that
|
// Since only one routine calls them, it is safe to assume that
|
||||||
|
@ -533,6 +538,7 @@ func (cs *ConsensusState) updateToState(state *sm.State, contiguous bool) {
|
||||||
|
|
||||||
// After the call cs.Step becomes RoundStepNewRound.
|
// After the call cs.Step becomes RoundStepNewRound.
|
||||||
func (cs *ConsensusState) setupNewRound(round uint) {
|
func (cs *ConsensusState) setupNewRound(round uint) {
|
||||||
|
// XXX Looks like this is just not called.
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if round == 0 {
|
if round == 0 {
|
||||||
panic("setupNewRound() should never be called for round 0")
|
panic("setupNewRound() should never be called for round 0")
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package node
|
||||||
|
|
||||||
|
import (
|
||||||
|
acm "github.com/tendermint/tendermint/account"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NodeID struct {
|
||||||
|
Name string
|
||||||
|
PubKey acm.PubKey
|
||||||
|
}
|
||||||
|
|
||||||
|
type PrivNodeID struct {
|
||||||
|
NodeID
|
||||||
|
PrivKey acm.PrivKey
|
||||||
|
}
|
||||||
|
|
||||||
|
type NodeGreeting struct {
|
||||||
|
NodeID
|
||||||
|
Version string
|
||||||
|
Network string
|
||||||
|
Message string
|
||||||
|
Time time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type SignedNodeGreeting struct {
|
||||||
|
NodeGreeting
|
||||||
|
Signature acm.Signature
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pnid *PrivNodeID) SignGreeting() *SignedNodeGreeting {
|
||||||
|
//greeting := NodeGreeting{}
|
||||||
|
return nil
|
||||||
|
}
|
13
node/node.go
13
node/node.go
|
@ -45,11 +45,16 @@ func NewNode() *Node {
|
||||||
|
|
||||||
// Get PrivValidator
|
// Get PrivValidator
|
||||||
var privValidator *sm.PrivValidator
|
var privValidator *sm.PrivValidator
|
||||||
if _, err := os.Stat(config.App().GetString("PrivValidatorFile")); err == nil {
|
privValidatorFile := config.App().GetString("PrivValidatorFile")
|
||||||
privValidator = sm.LoadPrivValidator(config.App().GetString("PrivValidatorFile"))
|
if _, err := os.Stat(privValidatorFile); err == nil {
|
||||||
log.Info("Loaded PrivValidator", "file", config.App().GetString("PrivValidatorFile"), "privValidator", privValidator)
|
privValidator = sm.LoadPrivValidator(privValidatorFile)
|
||||||
|
log.Info("Loaded PrivValidator",
|
||||||
|
"file", privValidatorFile, "privValidator", privValidator)
|
||||||
} else {
|
} else {
|
||||||
log.Info("No PrivValidator found", "file", config.App().GetString("PrivValidatorFile"))
|
privValidator = sm.GenPrivValidator()
|
||||||
|
privValidator.SetFile(privValidatorFile)
|
||||||
|
privValidator.Save()
|
||||||
|
log.Info("Generated PrivValidator", "file", privValidatorFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
eventSwitch := new(events.EventSwitch)
|
eventSwitch := new(events.EventSwitch)
|
||||||
|
|
|
@ -319,14 +319,12 @@ func (a *AddrBook) saveToFile(filePath string) {
|
||||||
Addrs: addrs,
|
Addrs: addrs,
|
||||||
}
|
}
|
||||||
|
|
||||||
w, err := os.Create(filePath)
|
jsonBytes, err := json.MarshalIndent(aJSON, "", "\t")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error opening file", "file", filePath, "error", err)
|
log.Error("Failed to save AddrBook to file", "err", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer w.Close()
|
err = AtomicWriteFile(filePath, jsonBytes)
|
||||||
jsonBytes, err := json.MarshalIndent(aJSON, "", "\t")
|
|
||||||
_, err = w.Write(jsonBytes)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to save AddrBook to file", "file", filePath, "error", err)
|
log.Error("Failed to save AddrBook to file", "file", filePath, "error", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,16 +10,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeFile(prefix string) (string, *os.File) {
|
|
||||||
now := time.Now()
|
|
||||||
path := fmt.Sprintf("%v_%v.out", prefix, now.Format("2006_01_02_15_04_05_MST"))
|
|
||||||
file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return path, file
|
|
||||||
}
|
|
||||||
|
|
||||||
type Process struct {
|
type Process struct {
|
||||||
Label string
|
Label string
|
||||||
ExecPath string
|
ExecPath string
|
||||||
|
@ -40,8 +30,11 @@ const (
|
||||||
|
|
||||||
// execPath: command name
|
// execPath: command name
|
||||||
// args: args to command. (should not include name)
|
// args: args to command. (should not include name)
|
||||||
func Create(mode int, label string, execPath string, args []string, input string) (*Process, error) {
|
func Create(mode int, label string, execPath string, args []string, input string, outPath string) (*Process, error) {
|
||||||
outPath, outFile := makeFile("output_" + label)
|
outFile, err := os.OpenFile(outPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
cmd := exec.Command(execPath, args...)
|
cmd := exec.Command(execPath, args...)
|
||||||
switch mode {
|
switch mode {
|
||||||
case ProcessModeStd:
|
case ProcessModeStd:
|
||||||
|
|
|
@ -36,7 +36,7 @@ func GetStorage(address, key []byte) (*ctypes.ResponseGetStorage, error) {
|
||||||
storageRoot := account.StorageRoot
|
storageRoot := account.StorageRoot
|
||||||
storageTree := state.LoadStorage(storageRoot)
|
storageTree := state.LoadStorage(storageRoot)
|
||||||
|
|
||||||
_, value := storageTree.Get(RightPadWord256(key).Bytes())
|
_, value := storageTree.Get(LeftPadWord256(key).Bytes())
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return &ctypes.ResponseGetStorage{key, nil}, nil
|
return &ctypes.ResponseGetStorage{key, nil}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,16 +33,21 @@ func Status() (*ctypes.ResponseStatus, error) {
|
||||||
|
|
||||||
func NetInfo() (*ctypes.ResponseNetInfo, error) {
|
func NetInfo() (*ctypes.ResponseNetInfo, error) {
|
||||||
listening := p2pSwitch.IsListening()
|
listening := p2pSwitch.IsListening()
|
||||||
|
moniker := config.App().GetString("Moniker")
|
||||||
network := config.App().GetString("Network")
|
network := config.App().GetString("Network")
|
||||||
listeners := []string{}
|
listeners := []string{}
|
||||||
for _, listener := range p2pSwitch.Listeners() {
|
for _, listener := range p2pSwitch.Listeners() {
|
||||||
listeners = append(listeners, listener.String())
|
listeners = append(listeners, listener.String())
|
||||||
}
|
}
|
||||||
peers := []string{}
|
peers := []ctypes.Peer{}
|
||||||
for _, peer := range p2pSwitch.Peers().List() {
|
for _, peer := range p2pSwitch.Peers().List() {
|
||||||
peers = append(peers, peer.String())
|
peers = append(peers, ctypes.Peer{
|
||||||
|
Address: peer.Connection().RemoteAddress.String(),
|
||||||
|
IsOutbound: peer.IsOutbound(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return &ctypes.ResponseNetInfo{
|
return &ctypes.ResponseNetInfo{
|
||||||
|
Moniker: moniker,
|
||||||
Network: network,
|
Network: network,
|
||||||
Listening: listening,
|
Listening: listening,
|
||||||
Listeners: listeners,
|
Listeners: listeners,
|
||||||
|
|
|
@ -16,7 +16,7 @@ func toVMAccount(acc *account.Account) *vm.Account {
|
||||||
Balance: acc.Balance,
|
Balance: acc.Balance,
|
||||||
Code: acc.Code, // This is crazy.
|
Code: acc.Code, // This is crazy.
|
||||||
Nonce: uint64(acc.Sequence),
|
Nonce: uint64(acc.Sequence),
|
||||||
StorageRoot: RightPadWord256(acc.StorageRoot),
|
StorageRoot: LeftPadWord256(acc.StorageRoot),
|
||||||
Other: acc.PubKey,
|
Other: acc.PubKey,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ func Call(address, data []byte) (*ctypes.ResponseCall, error) {
|
||||||
txCache := state.NewTxCache(cache)
|
txCache := state.NewTxCache(cache)
|
||||||
params := vm.Params{
|
params := vm.Params{
|
||||||
BlockHeight: uint64(st.LastBlockHeight),
|
BlockHeight: uint64(st.LastBlockHeight),
|
||||||
BlockHash: RightPadWord256(st.LastBlockHash),
|
BlockHash: LeftPadWord256(st.LastBlockHash),
|
||||||
BlockTime: st.LastBlockTime.Unix(),
|
BlockTime: st.LastBlockTime.Unix(),
|
||||||
GasLimit: 10000000,
|
GasLimit: 10000000,
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ func CallCode(code, data []byte) (*ctypes.ResponseCall, error) {
|
||||||
txCache := state.NewTxCache(cache)
|
txCache := state.NewTxCache(cache)
|
||||||
params := vm.Params{
|
params := vm.Params{
|
||||||
BlockHeight: uint64(st.LastBlockHeight),
|
BlockHeight: uint64(st.LastBlockHeight),
|
||||||
BlockHash: RightPadWord256(st.LastBlockHash),
|
BlockHash: LeftPadWord256(st.LastBlockHash),
|
||||||
BlockTime: st.LastBlockTime.Unix(),
|
BlockTime: st.LastBlockTime.Unix(),
|
||||||
GasLimit: 10000000,
|
GasLimit: 10000000,
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,10 +70,16 @@ type ResponseStatus struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResponseNetInfo struct {
|
type ResponseNetInfo struct {
|
||||||
|
Moniker string
|
||||||
Network string
|
Network string
|
||||||
Listening bool
|
Listening bool
|
||||||
Listeners []string
|
Listeners []string
|
||||||
Peers []string
|
Peers []Peer
|
||||||
|
}
|
||||||
|
|
||||||
|
type Peer struct {
|
||||||
|
Address string
|
||||||
|
IsOutbound bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResponseSignTx struct {
|
type ResponseSignTx struct {
|
||||||
|
|
|
@ -225,6 +225,7 @@ type WSConnection struct {
|
||||||
id string
|
id string
|
||||||
wsConn *websocket.Conn
|
wsConn *websocket.Conn
|
||||||
writeChan chan WSResponse
|
writeChan chan WSResponse
|
||||||
|
quitChan chan struct{}
|
||||||
failedSends uint
|
failedSends uint
|
||||||
started uint32
|
started uint32
|
||||||
stopped uint32
|
stopped uint32
|
||||||
|
@ -238,6 +239,7 @@ func NewWSConnection(wsConn *websocket.Conn) *WSConnection {
|
||||||
id: wsConn.RemoteAddr().String(),
|
id: wsConn.RemoteAddr().String(),
|
||||||
wsConn: wsConn,
|
wsConn: wsConn,
|
||||||
writeChan: make(chan WSResponse, WriteChanBufferSize), // buffered. we keep track when its full
|
writeChan: make(chan WSResponse, WriteChanBufferSize), // buffered. we keep track when its full
|
||||||
|
quitChan: make(chan struct{}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,8 +258,10 @@ func (con *WSConnection) Start(evsw *events.EventSwitch) {
|
||||||
// close the connection
|
// close the connection
|
||||||
func (con *WSConnection) Stop() {
|
func (con *WSConnection) Stop() {
|
||||||
if atomic.CompareAndSwapUint32(&con.stopped, 0, 1) {
|
if atomic.CompareAndSwapUint32(&con.stopped, 0, 1) {
|
||||||
con.wsConn.Close()
|
close(con.quitChan)
|
||||||
close(con.writeChan)
|
// the write loop closes the websocket connection
|
||||||
|
// when it exits its loop, and the read loop
|
||||||
|
// closes the writeChan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,6 +281,7 @@ func (con *WSConnection) safeWrite(resp WSResponse) {
|
||||||
|
|
||||||
// read from the socket and subscribe to or unsubscribe from events
|
// read from the socket and subscribe to or unsubscribe from events
|
||||||
func (con *WSConnection) read() {
|
func (con *WSConnection) read() {
|
||||||
|
defer close(con.writeChan)
|
||||||
reaper := time.Tick(time.Second * WSConnectionReaperSeconds)
|
reaper := time.Tick(time.Second * WSConnectionReaperSeconds)
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
@ -322,32 +327,30 @@ func (con *WSConnection) read() {
|
||||||
default:
|
default:
|
||||||
con.safeWrite(WSResponse{Error: "Unknown request type: " + req.Type})
|
con.safeWrite(WSResponse{Error: "Unknown request type: " + req.Type})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// receives on a write channel and writes out on the socket
|
// receives on a write channel and writes out on the socket
|
||||||
func (con *WSConnection) write() {
|
func (con *WSConnection) write() {
|
||||||
|
defer con.wsConn.Close()
|
||||||
n, err := new(int64), new(error)
|
n, err := new(int64), new(error)
|
||||||
for {
|
for {
|
||||||
msg, more := <-con.writeChan
|
select {
|
||||||
if !more {
|
case msg := <-con.writeChan:
|
||||||
// the channel was closed, so ensure
|
buf := new(bytes.Buffer)
|
||||||
// connection is stopped and return
|
binary.WriteJSON(msg, buf, n, err)
|
||||||
con.Stop()
|
if *err != nil {
|
||||||
return
|
log.Error("Failed to marshal WSResponse to JSON", "error", err)
|
||||||
}
|
} else {
|
||||||
buf := new(bytes.Buffer)
|
if err := con.wsConn.WriteMessage(websocket.TextMessage, buf.Bytes()); err != nil {
|
||||||
binary.WriteJSON(msg, buf, n, err)
|
log.Error("Failed to write response on websocket", "error", err)
|
||||||
if *err != nil {
|
con.Stop()
|
||||||
log.Error("Failed to write JSON WSResponse", "error", err)
|
return
|
||||||
} else {
|
}
|
||||||
if err := con.wsConn.WriteMessage(websocket.TextMessage, buf.Bytes()); err != nil {
|
|
||||||
log.Error("Failed to write response on websocket", "error", err)
|
|
||||||
con.Stop()
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
case <-con.quitChan:
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -288,7 +288,7 @@ func simpleContract() ([]byte, []byte, []byte) {
|
||||||
// the is the code we need to return the contractCode when the contract is initialized
|
// the is the code we need to return the contractCode when the contract is initialized
|
||||||
lenCode := len(contractCode)
|
lenCode := len(contractCode)
|
||||||
// push code to the stack
|
// push code to the stack
|
||||||
//code := append([]byte{byte(0x60 + lenCode - 1)}, LeftPadWord256(contractCode).Bytes()...)
|
//code := append([]byte{byte(0x60 + lenCode - 1)}, RightPadWord256(contractCode).Bytes()...)
|
||||||
code := append([]byte{0x7f}, RightPadWord256(contractCode).Bytes()...)
|
code := append([]byte{0x7f}, RightPadWord256(contractCode).Bytes()...)
|
||||||
// store it in memory
|
// store it in memory
|
||||||
code = append(code, []byte{0x60, 0x0, 0x52}...)
|
code = append(code, []byte{0x60, 0x0, 0x52}...)
|
||||||
|
|
|
@ -119,8 +119,8 @@ func testGetStorage(t *testing.T, typ string) {
|
||||||
mempoolCount = 0
|
mempoolCount = 0
|
||||||
|
|
||||||
v := getStorage(t, typ, contractAddr, []byte{0x1})
|
v := getStorage(t, typ, contractAddr, []byte{0x1})
|
||||||
got := RightPadWord256(v)
|
got := LeftPadWord256(v)
|
||||||
expected := RightPadWord256([]byte{0x5})
|
expected := LeftPadWord256([]byte{0x5})
|
||||||
if got.Compare(expected) != 0 {
|
if got.Compare(expected) != 0 {
|
||||||
t.Fatalf("Wrong storage value. Got %x, expected %x", got.Bytes(), expected.Bytes())
|
t.Fatalf("Wrong storage value. Got %x, expected %x", got.Bytes(), expected.Bytes())
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ func (cache *BlockCache) GetStorage(addr Word256, key Word256) (value Word256) {
|
||||||
_, val_ := storage.Get(key.Bytes())
|
_, val_ := storage.Get(key.Bytes())
|
||||||
value = Zero256
|
value = Zero256
|
||||||
if val_ != nil {
|
if val_ != nil {
|
||||||
value = RightPadWord256(val_.([]byte))
|
value = LeftPadWord256(val_.([]byte))
|
||||||
}
|
}
|
||||||
cache.storages[Tuple256{addr, key}] = storageInfo{value, false}
|
cache.storages[Tuple256{addr, key}] = storageInfo{value, false}
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -152,7 +152,6 @@ func execBlock(s *State, block *types.Block, blockPartsHeader types.PartSetHeade
|
||||||
|
|
||||||
// Increment validator AccumPowers
|
// Increment validator AccumPowers
|
||||||
s.BondedValidators.IncrementAccum(1)
|
s.BondedValidators.IncrementAccum(1)
|
||||||
|
|
||||||
s.LastBlockHeight = block.Height
|
s.LastBlockHeight = block.Height
|
||||||
s.LastBlockHash = block.Hash()
|
s.LastBlockHash = block.Hash()
|
||||||
s.LastBlockParts = blockPartsHeader
|
s.LastBlockParts = blockPartsHeader
|
||||||
|
@ -395,7 +394,7 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
|
||||||
txCache = NewTxCache(blockCache)
|
txCache = NewTxCache(blockCache)
|
||||||
params = vm.Params{
|
params = vm.Params{
|
||||||
BlockHeight: uint64(_s.LastBlockHeight),
|
BlockHeight: uint64(_s.LastBlockHeight),
|
||||||
BlockHash: RightPadWord256(_s.LastBlockHash),
|
BlockHash: LeftPadWord256(_s.LastBlockHash),
|
||||||
BlockTime: _s.LastBlockTime.Unix(),
|
BlockTime: _s.LastBlockTime.Unix(),
|
||||||
GasLimit: 10000000,
|
GasLimit: 10000000,
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,8 +99,9 @@ func (privVal *PrivValidator) Save() {
|
||||||
|
|
||||||
func (privVal *PrivValidator) save() {
|
func (privVal *PrivValidator) save() {
|
||||||
jsonBytes := binary.JSONBytes(privVal)
|
jsonBytes := binary.JSONBytes(privVal)
|
||||||
err := ioutil.WriteFile(privVal.filename, jsonBytes, 0700)
|
err := AtomicWriteFile(privVal.filename, jsonBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// `@; BOOM!!!
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,7 +147,7 @@ func (cache *TxCache) AddLog(log *vm.Log) {
|
||||||
func NewContractAddress(caller []byte, nonce uint64) []byte {
|
func NewContractAddress(caller []byte, nonce uint64) []byte {
|
||||||
temp := make([]byte, 32+8)
|
temp := make([]byte, 32+8)
|
||||||
copy(temp, caller)
|
copy(temp, caller)
|
||||||
PutUint64(temp[32:], nonce)
|
PutUint64LE(temp[32:], nonce)
|
||||||
return sha3.Sha3(temp)[:20]
|
return sha3.Sha3(temp)[:20]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ func toVMAccount(acc *ac.Account) *vm.Account {
|
||||||
Balance: acc.Balance,
|
Balance: acc.Balance,
|
||||||
Code: acc.Code, // This is crazy.
|
Code: acc.Code, // This is crazy.
|
||||||
Nonce: uint64(acc.Sequence),
|
Nonce: uint64(acc.Sequence),
|
||||||
StorageRoot: RightPadWord256(acc.StorageRoot),
|
StorageRoot: LeftPadWord256(acc.StorageRoot),
|
||||||
Other: acc.PubKey,
|
Other: acc.PubKey,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,6 @@ func NewValidatorSet(vals []*Validator) *ValidatorSet {
|
||||||
|
|
||||||
// TODO: mind the overflow when times and votingPower shares too large.
|
// TODO: mind the overflow when times and votingPower shares too large.
|
||||||
func (valSet *ValidatorSet) IncrementAccum(times uint) {
|
func (valSet *ValidatorSet) IncrementAccum(times uint) {
|
||||||
|
|
||||||
// Add VotingPower * times to each validator and order into heap.
|
// Add VotingPower * times to each validator and order into heap.
|
||||||
validatorsHeap := NewHeap()
|
validatorsHeap := NewHeap()
|
||||||
for _, val := range valSet.Validators {
|
for _, val := range valSet.Validators {
|
||||||
|
@ -56,12 +55,12 @@ func (valSet *ValidatorSet) IncrementAccum(times uint) {
|
||||||
// Decrement the validator with most accum, times times.
|
// Decrement the validator with most accum, times times.
|
||||||
for i := uint(0); i < times; i++ {
|
for i := uint(0); i < times; i++ {
|
||||||
mostest := validatorsHeap.Peek().(*Validator)
|
mostest := validatorsHeap.Peek().(*Validator)
|
||||||
|
if i == times-1 {
|
||||||
|
valSet.proposer = mostest
|
||||||
|
}
|
||||||
mostest.Accum -= int64(valSet.TotalVotingPower())
|
mostest.Accum -= int64(valSet.TotalVotingPower())
|
||||||
validatorsHeap.Update(mostest, accumComparable(mostest.Accum))
|
validatorsHeap.Update(mostest, accumComparable(mostest.Accum))
|
||||||
}
|
}
|
||||||
|
|
||||||
// The next proposer is the next most accums remaining
|
|
||||||
valSet.proposer = validatorsHeap.Peek().(*Validator)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (valSet *ValidatorSet) Copy() *ValidatorSet {
|
func (valSet *ValidatorSet) Copy() *ValidatorSet {
|
||||||
|
@ -293,5 +292,5 @@ type accumComparable uint64
|
||||||
|
|
||||||
// We want to find the validator with the greatest accum.
|
// We want to find the validator with the greatest accum.
|
||||||
func (ac accumComparable) Less(o interface{}) bool {
|
func (ac accumComparable) Less(o interface{}) bool {
|
||||||
return uint64(ac) > uint64(o.(accumComparable))
|
return uint64(ac) < uint64(o.(accumComparable))
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
|
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -41,6 +42,15 @@ func TestCopy(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestProposerSelection(t *testing.T) {
|
||||||
|
vset := randValidatorSet(10)
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
val := vset.Proposer()
|
||||||
|
fmt.Printf("Proposer: %v\n", val)
|
||||||
|
vset.IncrementAccum(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkValidatorSetCopy(b *testing.B) {
|
func BenchmarkValidatorSetCopy(b *testing.B) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
vset := NewValidatorSet([]*Validator{})
|
vset := NewValidatorSet([]*Validator{})
|
||||||
|
@ -51,7 +61,7 @@ func BenchmarkValidatorSetCopy(b *testing.B) {
|
||||||
PubKey: privAccount.PubKey.(account.PubKeyEd25519),
|
PubKey: privAccount.PubKey.(account.PubKeyEd25519),
|
||||||
}
|
}
|
||||||
if !vset.Add(val) {
|
if !vset.Add(val) {
|
||||||
panic("Failde to add validator")
|
panic("Failed to add validator")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
package vm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
// To256
|
||||||
|
//
|
||||||
|
// "cast" the big int to a 256 big int (i.e., limit to)
|
||||||
|
var tt256 = new(big.Int).Lsh(big.NewInt(1), 256)
|
||||||
|
var tt256m1 = new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(1))
|
||||||
|
var tt255 = new(big.Int).Lsh(big.NewInt(1), 255)
|
||||||
|
|
||||||
|
func U256(x *big.Int) *big.Int {
|
||||||
|
x.And(x, tt256m1)
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func S256(x *big.Int) *big.Int {
|
||||||
|
if x.Cmp(tt255) < 0 {
|
||||||
|
return x
|
||||||
|
} else {
|
||||||
|
// We don't want to modify x, ever
|
||||||
|
return new(big.Int).Sub(x, tt256)
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,7 +39,7 @@ func ecrecoverFunc(input []byte, gas *uint64) (output []byte, err error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
hashed := sha3.Sha3(recovered[1:])
|
hashed := sha3.Sha3(recovered[1:])
|
||||||
return RightPadBytes(hashed, 32), nil
|
return LeftPadBytes(hashed, 32), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func sha256Func(input []byte, gas *uint64) (output []byte, err error) {
|
func sha256Func(input []byte, gas *uint64) (output []byte, err error) {
|
||||||
|
@ -73,7 +73,7 @@ func ripemd160Func(input []byte, gas *uint64) (output []byte, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return RightPadBytes(hasher.Sum(nil), 32), nil
|
return LeftPadBytes(hasher.Sum(nil), 32), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func identityFunc(input []byte, gas *uint64) (output []byte, err error) {
|
func identityFunc(input []byte, gas *uint64) (output []byte, err error) {
|
||||||
|
|
13
vm/stack.go
13
vm/stack.go
|
@ -51,7 +51,7 @@ func (st *Stack) PushBytes(bz []byte) {
|
||||||
if len(bz) != 32 {
|
if len(bz) != 32 {
|
||||||
panic("Invalid bytes size: expected 32")
|
panic("Invalid bytes size: expected 32")
|
||||||
}
|
}
|
||||||
st.Push(RightPadWord256(bz))
|
st.Push(LeftPadWord256(bz))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *Stack) Push64(i uint64) {
|
func (st *Stack) Push64(i uint64) {
|
||||||
|
@ -73,7 +73,8 @@ func (st *Stack) PopBytes() []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *Stack) Pop64() uint64 {
|
func (st *Stack) Pop64() uint64 {
|
||||||
return GetUint64(st.Pop().Bytes())
|
d := st.Pop()
|
||||||
|
return Uint64FromWord256(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *Stack) Len() int {
|
func (st *Stack) Len() int {
|
||||||
|
@ -105,11 +106,13 @@ func (st *Stack) Peek() Word256 {
|
||||||
return st.data[st.ptr-1]
|
return st.data[st.ptr-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *Stack) Print() {
|
func (st *Stack) Print(n int) {
|
||||||
fmt.Println("### stack ###")
|
fmt.Println("### stack ###")
|
||||||
if st.ptr > 0 {
|
if st.ptr > 0 {
|
||||||
for i, val := range st.data {
|
nn := MinInt(n, st.ptr)
|
||||||
fmt.Printf("%-3d %v\n", i, val)
|
for j, i := 0, st.ptr-1; i > st.ptr-1-nn; i-- {
|
||||||
|
fmt.Printf("%-3d %X\n", j, st.data[i])
|
||||||
|
j += 1
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("-- empty --")
|
fmt.Println("-- empty --")
|
||||||
|
|
|
@ -89,6 +89,6 @@ func createAddress(creator *Account) Word256 {
|
||||||
creator.Nonce += 1
|
creator.Nonce += 1
|
||||||
temp := make([]byte, 32+8)
|
temp := make([]byte, 32+8)
|
||||||
copy(temp, creator.Address[:])
|
copy(temp, creator.Address[:])
|
||||||
PutUint64(temp[32:], nonce)
|
PutUint64LE(temp[32:], nonce)
|
||||||
return RightPadWord256(sha3.Sha3(temp)[:20])
|
return LeftPadWord256(sha3.Sha3(temp)[:20])
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,10 +64,10 @@ func TestSubcurrency(t *testing.T) {
|
||||||
st := newAppState()
|
st := newAppState()
|
||||||
// Create accounts
|
// Create accounts
|
||||||
account1 := &Account{
|
account1 := &Account{
|
||||||
Address: RightPadWord256(makeBytes(20)),
|
Address: LeftPadWord256(makeBytes(20)),
|
||||||
}
|
}
|
||||||
account2 := &Account{
|
account2 := &Account{
|
||||||
Address: RightPadWord256(makeBytes(20)),
|
Address: LeftPadWord256(makeBytes(20)),
|
||||||
}
|
}
|
||||||
st.accounts[account1.Address.String()] = account1
|
st.accounts[account1.Address.String()] = account1
|
||||||
st.accounts[account2.Address.String()] = account2
|
st.accounts[account2.Address.String()] = account2
|
||||||
|
|
365
vm/vm.go
365
vm/vm.go
|
@ -1,6 +1,7 @@
|
||||||
package vm
|
package vm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
@ -131,207 +132,253 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
||||||
case ADD: // 0x01
|
case ADD: // 0x01
|
||||||
//x, y := stack.Pop64(), stack.Pop64()
|
|
||||||
//stack.Push64(x + y)
|
|
||||||
x, y := stack.Pop(), stack.Pop()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
xb := new(big.Int).SetBytes(flip(x[:]))
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
yb := new(big.Int).SetBytes(flip(y[:]))
|
yb := new(big.Int).SetBytes(y[:])
|
||||||
sum := new(big.Int).Add(xb, yb)
|
sum := new(big.Int).Add(xb, yb)
|
||||||
stack.Push(RightPadWord256(flip(sum.Bytes())))
|
res := LeftPadWord256(U256(sum).Bytes())
|
||||||
dbg.Printf(" %v + %v = %v\n", xb, yb, sum)
|
stack.Push(res)
|
||||||
|
dbg.Printf(" %v + %v = %v (%X)\n", xb, yb, sum, res)
|
||||||
|
|
||||||
case MUL: // 0x02
|
case MUL: // 0x02
|
||||||
//x, y := stack.Pop64(), stack.Pop64()
|
|
||||||
//stack.Push64(x * y)
|
|
||||||
x, y := stack.Pop(), stack.Pop()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
xb := new(big.Int).SetBytes(flip(x[:]))
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
yb := new(big.Int).SetBytes(flip(y[:]))
|
yb := new(big.Int).SetBytes(y[:])
|
||||||
prod := new(big.Int).Mul(xb, yb)
|
prod := new(big.Int).Mul(xb, yb)
|
||||||
stack.Push(RightPadWord256(flip(rightMostBytes(prod.Bytes(), 32))))
|
res := LeftPadWord256(U256(prod).Bytes())
|
||||||
dbg.Printf(" %v * %v = %v\n", xb, yb, prod)
|
stack.Push(res)
|
||||||
|
dbg.Printf(" %v * %v = %v (%X)\n", xb, yb, prod, res)
|
||||||
|
|
||||||
case SUB: // 0x03
|
case SUB: // 0x03
|
||||||
//x, y := stack.Pop64(), stack.Pop64()
|
|
||||||
//stack.Push64(x - y)
|
|
||||||
x, y := stack.Pop(), stack.Pop()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
xb := new(big.Int).SetBytes(flip(x[:]))
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
yb := new(big.Int).SetBytes(flip(y[:]))
|
yb := new(big.Int).SetBytes(y[:])
|
||||||
diff := new(big.Int).Sub(xb, yb)
|
diff := new(big.Int).Sub(xb, yb)
|
||||||
stack.Push(RightPadWord256(flip(diff.Bytes())))
|
res := LeftPadWord256(U256(diff).Bytes())
|
||||||
dbg.Printf(" %v - %v = %v\n", xb, yb, diff)
|
stack.Push(res)
|
||||||
|
dbg.Printf(" %v - %v = %v (%X)\n", xb, yb, diff, res)
|
||||||
|
|
||||||
case DIV: // 0x04
|
case DIV: // 0x04
|
||||||
//x, y := stack.Pop64(), stack.Pop64()
|
|
||||||
//stack.Push64(x / y)
|
|
||||||
x, y := stack.Pop(), stack.Pop()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
if y.IsZero() { // TODO
|
if y.IsZero() {
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
dbg.Printf(" %x / %x = %v (TODO)\n", x, y, 0)
|
dbg.Printf(" %x / %x = %v\n", x, y, 0)
|
||||||
} else {
|
} else {
|
||||||
xb := new(big.Int).SetBytes(flip(x[:]))
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
yb := new(big.Int).SetBytes(flip(y[:]))
|
yb := new(big.Int).SetBytes(y[:])
|
||||||
div := new(big.Int).Div(xb, yb)
|
div := new(big.Int).Div(xb, yb)
|
||||||
stack.Push(RightPadWord256(flip(div.Bytes())))
|
res := LeftPadWord256(U256(div).Bytes())
|
||||||
dbg.Printf(" %v / %v = %v\n", xb, yb, div)
|
stack.Push(res)
|
||||||
|
dbg.Printf(" %v / %v = %v (%X)\n", xb, yb, div, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
case SDIV: // 0x05
|
case SDIV: // 0x05
|
||||||
// TODO ... big?
|
x, y := stack.Pop(), stack.Pop()
|
||||||
x, y := int64(stack.Pop64()), int64(stack.Pop64())
|
if y.IsZero() {
|
||||||
if y == 0 { // TODO
|
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
dbg.Printf(" %v / %v = %v (TODO)\n", x, y, 0)
|
dbg.Printf(" %x / %x = %v\n", x, y, 0)
|
||||||
} else {
|
} else {
|
||||||
stack.Push64(uint64(x / y))
|
xb := S256(new(big.Int).SetBytes(x[:]))
|
||||||
dbg.Printf(" %v / %v = %v\n", x, y, x/y)
|
yb := S256(new(big.Int).SetBytes(y[:]))
|
||||||
|
div := new(big.Int).Div(xb, yb)
|
||||||
|
res := LeftPadWord256(U256(div).Bytes())
|
||||||
|
stack.Push(res)
|
||||||
|
dbg.Printf(" %v / %v = %v (%X)\n", xb, yb, div, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
case MOD: // 0x06
|
case MOD: // 0x06
|
||||||
//x, y := stack.Pop64(), stack.Pop64()
|
|
||||||
x, y := stack.Pop(), stack.Pop()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
if y.IsZero() { // TODO
|
if y.IsZero() {
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
dbg.Printf(" %v %% %v = %v (TODO)\n", x, y, 0)
|
dbg.Printf(" %v %% %v = %v\n", x, y, 0)
|
||||||
} else {
|
} else {
|
||||||
xb := new(big.Int).SetBytes(flip(x[:]))
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
yb := new(big.Int).SetBytes(flip(y[:]))
|
yb := new(big.Int).SetBytes(y[:])
|
||||||
mod := new(big.Int).Mod(xb, yb)
|
mod := new(big.Int).Mod(xb, yb)
|
||||||
stack.Push(RightPadWord256(flip(mod.Bytes())))
|
res := LeftPadWord256(U256(mod).Bytes())
|
||||||
dbg.Printf(" %v %% %v = %v\n", xb, yb, mod)
|
stack.Push(res)
|
||||||
|
dbg.Printf(" %v %% %v = %v (%X)\n", xb, yb, mod, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
case SMOD: // 0x07
|
case SMOD: // 0x07
|
||||||
// TODO ... big?
|
x, y := stack.Pop(), stack.Pop()
|
||||||
x, y := int64(stack.Pop64()), int64(stack.Pop64())
|
if y.IsZero() {
|
||||||
if y == 0 { // TODO
|
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
dbg.Printf(" %v %% %v = %v (TODO)\n", x, y, 0)
|
dbg.Printf(" %v %% %v = %v\n", x, y, 0)
|
||||||
} else {
|
} else {
|
||||||
stack.Push64(uint64(x % y))
|
xb := S256(new(big.Int).SetBytes(x[:]))
|
||||||
dbg.Printf(" %v %% %v = %v\n", x, y, x%y)
|
yb := S256(new(big.Int).SetBytes(y[:]))
|
||||||
|
mod := new(big.Int).Mod(xb, yb)
|
||||||
|
res := LeftPadWord256(U256(mod).Bytes())
|
||||||
|
stack.Push(res)
|
||||||
|
dbg.Printf(" %v %% %v = %v (%X)\n", xb, yb, mod, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
case ADDMOD: // 0x08
|
case ADDMOD: // 0x08
|
||||||
// TODO ... big?
|
x, y, z := stack.Pop(), stack.Pop(), stack.Pop()
|
||||||
x, y, z := stack.Pop64(), stack.Pop64(), stack.Pop64()
|
if z.IsZero() {
|
||||||
if z == 0 { // TODO
|
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
dbg.Printf(" (%v + %v) %% %v = %v (TODO)\n", x, y, z, 0)
|
dbg.Printf(" %v %% %v = %v\n", x, y, 0)
|
||||||
} else {
|
} else {
|
||||||
stack.Push64((x + y) % z)
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
dbg.Printf(" (%v + %v) %% %v = %v\n", x, y, z, (x+y)%z)
|
yb := new(big.Int).SetBytes(y[:])
|
||||||
|
zb := new(big.Int).SetBytes(z[:])
|
||||||
|
add := new(big.Int).Add(xb, yb)
|
||||||
|
mod := new(big.Int).Mod(add, zb)
|
||||||
|
res := LeftPadWord256(U256(mod).Bytes())
|
||||||
|
stack.Push(res)
|
||||||
|
dbg.Printf(" %v + %v %% %v = %v (%X)\n",
|
||||||
|
xb, yb, zb, mod, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
case MULMOD: // 0x09
|
case MULMOD: // 0x09
|
||||||
// TODO ... big?
|
x, y, z := stack.Pop(), stack.Pop(), stack.Pop()
|
||||||
x, y, z := stack.Pop64(), stack.Pop64(), stack.Pop64()
|
if z.IsZero() {
|
||||||
if z == 0 { // TODO
|
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
dbg.Printf(" (%v + %v) %% %v = %v (TODO)\n", x, y, z, 0)
|
dbg.Printf(" %v %% %v = %v\n", x, y, 0)
|
||||||
} else {
|
} else {
|
||||||
stack.Push64((x * y) % z)
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
dbg.Printf(" (%v + %v) %% %v = %v\n", x, y, z, (x*y)%z)
|
yb := new(big.Int).SetBytes(y[:])
|
||||||
|
zb := new(big.Int).SetBytes(z[:])
|
||||||
|
mul := new(big.Int).Mul(xb, yb)
|
||||||
|
mod := new(big.Int).Mod(mul, zb)
|
||||||
|
res := LeftPadWord256(U256(mod).Bytes())
|
||||||
|
stack.Push(res)
|
||||||
|
dbg.Printf(" %v * %v %% %v = %v (%X)\n",
|
||||||
|
xb, yb, zb, mod, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
case EXP: // 0x0A
|
case EXP: // 0x0A
|
||||||
//x, y := stack.Pop64(), stack.Pop64()
|
|
||||||
//stack.Push64(ExpUint64(x, y))
|
|
||||||
x, y := stack.Pop(), stack.Pop()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
xb := new(big.Int).SetBytes(flip(x[:]))
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
yb := new(big.Int).SetBytes(flip(y[:]))
|
yb := new(big.Int).SetBytes(y[:])
|
||||||
pow := new(big.Int).Exp(xb, yb, big.NewInt(0))
|
pow := new(big.Int).Exp(xb, yb, big.NewInt(0))
|
||||||
stack.Push(RightPadWord256(flip(pow.Bytes())))
|
res := LeftPadWord256(U256(pow).Bytes())
|
||||||
dbg.Printf(" %v ** %v = %v\n", xb, yb, pow)
|
stack.Push(res)
|
||||||
|
dbg.Printf(" %v ** %v = %v (%X)\n", xb, yb, pow, res)
|
||||||
|
|
||||||
case SIGNEXTEND: // 0x0B
|
case SIGNEXTEND: // 0x0B
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
back := stack.Pop()
|
||||||
res := (y << uint(x)) >> x
|
backb := new(big.Int).SetBytes(back[:])
|
||||||
stack.Push64(res)
|
if backb.Cmp(big.NewInt(31)) < 0 {
|
||||||
dbg.Printf(" (%v << %v) >> %v = %v\n", y, x, x, res)
|
bit := uint(backb.Uint64()*8 + 7)
|
||||||
|
num := stack.Pop()
|
||||||
|
numb := new(big.Int).SetBytes(num[:])
|
||||||
|
mask := new(big.Int).Lsh(big.NewInt(1), bit)
|
||||||
|
mask.Sub(mask, big.NewInt(1))
|
||||||
|
if numb.Bit(int(bit)) == 1 {
|
||||||
|
numb.Or(numb, mask.Not(mask))
|
||||||
|
} else {
|
||||||
|
numb.Add(numb, mask)
|
||||||
|
}
|
||||||
|
res := LeftPadWord256(U256(numb).Bytes())
|
||||||
|
dbg.Printf(" = %v (%X)", numb, res)
|
||||||
|
stack.Push(res)
|
||||||
|
}
|
||||||
|
|
||||||
case LT: // 0x10
|
case LT: // 0x10
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
if x < y {
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
|
yb := new(big.Int).SetBytes(y[:])
|
||||||
|
if xb.Cmp(yb) < 0 {
|
||||||
stack.Push64(1)
|
stack.Push64(1)
|
||||||
|
dbg.Printf(" %v < %v = %v\n", xb, yb, 1)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
|
dbg.Printf(" %v < %v = %v\n", xb, yb, 0)
|
||||||
}
|
}
|
||||||
dbg.Printf(" %v < %v = %v\n", x, y, x < y)
|
|
||||||
|
|
||||||
case GT: // 0x11
|
case GT: // 0x11
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
if x > y {
|
xb := new(big.Int).SetBytes(x[:])
|
||||||
|
yb := new(big.Int).SetBytes(y[:])
|
||||||
|
if xb.Cmp(yb) > 0 {
|
||||||
stack.Push64(1)
|
stack.Push64(1)
|
||||||
|
dbg.Printf(" %v > %v = %v\n", xb, yb, 1)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
|
dbg.Printf(" %v > %v = %v\n", xb, yb, 0)
|
||||||
}
|
}
|
||||||
dbg.Printf(" %v > %v = %v\n", x, y, x > y)
|
|
||||||
|
|
||||||
case SLT: // 0x12
|
case SLT: // 0x12
|
||||||
x, y := int64(stack.Pop64()), int64(stack.Pop64())
|
x, y := stack.Pop(), stack.Pop()
|
||||||
if x < y {
|
xb := S256(new(big.Int).SetBytes(x[:]))
|
||||||
|
yb := S256(new(big.Int).SetBytes(y[:]))
|
||||||
|
if xb.Cmp(yb) < 0 {
|
||||||
stack.Push64(1)
|
stack.Push64(1)
|
||||||
|
dbg.Printf(" %v < %v = %v\n", xb, yb, 1)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
|
dbg.Printf(" %v < %v = %v\n", xb, yb, 0)
|
||||||
}
|
}
|
||||||
dbg.Printf(" %v < %v = %v\n", x, y, x < y)
|
|
||||||
|
|
||||||
case SGT: // 0x13
|
case SGT: // 0x13
|
||||||
x, y := int64(stack.Pop64()), int64(stack.Pop64())
|
x, y := stack.Pop(), stack.Pop()
|
||||||
if x > y {
|
xb := S256(new(big.Int).SetBytes(x[:]))
|
||||||
|
yb := S256(new(big.Int).SetBytes(y[:]))
|
||||||
|
if xb.Cmp(yb) > 0 {
|
||||||
stack.Push64(1)
|
stack.Push64(1)
|
||||||
|
dbg.Printf(" %v > %v = %v\n", xb, yb, 1)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
|
dbg.Printf(" %v > %v = %v\n", xb, yb, 0)
|
||||||
}
|
}
|
||||||
dbg.Printf(" %v > %v = %v\n", x, y, x > y)
|
|
||||||
|
|
||||||
case EQ: // 0x14
|
case EQ: // 0x14
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
if x == y {
|
if bytes.Equal(x[:], y[:]) {
|
||||||
stack.Push64(1)
|
stack.Push64(1)
|
||||||
|
dbg.Printf(" %X == %X = %v\n", x, y, 1)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
|
dbg.Printf(" %X == %X = %v\n", x, y, 0)
|
||||||
}
|
}
|
||||||
dbg.Printf(" %v == %v = %v\n", x, y, x == y)
|
|
||||||
|
|
||||||
case ISZERO: // 0x15
|
case ISZERO: // 0x15
|
||||||
x := stack.Pop64()
|
x := stack.Pop()
|
||||||
if x == 0 {
|
if x.IsZero() {
|
||||||
stack.Push64(1)
|
stack.Push64(1)
|
||||||
|
dbg.Printf(" %v == 0 = %v\n", x, 1)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
|
dbg.Printf(" %v == 0 = %v\n", x, 0)
|
||||||
}
|
}
|
||||||
dbg.Printf(" %v == 0 = %v\n", x, x == 0)
|
|
||||||
|
|
||||||
case AND: // 0x16
|
case AND: // 0x16
|
||||||
//x, y := stack.Pop64(), stack.Pop64()
|
|
||||||
//stack.Push64(x & y)
|
|
||||||
x, y := stack.Pop(), stack.Pop()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
xb := new(big.Int).SetBytes(flip(x[:]))
|
z := [32]byte{}
|
||||||
yb := new(big.Int).SetBytes(flip(y[:]))
|
for i := 0; i < 32; i++ {
|
||||||
res := new(big.Int).And(xb, yb)
|
z[i] = x[i] & y[i]
|
||||||
stack.Push(RightPadWord256(flip(res.Bytes())))
|
}
|
||||||
dbg.Printf(" %v & %v = %v\n", xb, yb, res)
|
stack.Push(z)
|
||||||
|
dbg.Printf(" %X & %X = %X\n", x, y, z)
|
||||||
|
|
||||||
case OR: // 0x17
|
case OR: // 0x17
|
||||||
//x, y := stack.Pop64(), stack.Pop64()
|
|
||||||
//stack.Push64(x | y)
|
|
||||||
//dbg.Printf(" %v | %v = %v\n", x, y, x|y)
|
|
||||||
x, y := stack.Pop(), stack.Pop()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
xb := new(big.Int).SetBytes(flip(x[:]))
|
z := [32]byte{}
|
||||||
yb := new(big.Int).SetBytes(flip(y[:]))
|
for i := 0; i < 32; i++ {
|
||||||
res := new(big.Int).Or(xb, yb)
|
z[i] = x[i] | y[i]
|
||||||
stack.Push(RightPadWord256(flip(res.Bytes())))
|
}
|
||||||
dbg.Printf(" %v & %v = %v\n", xb, yb, res)
|
stack.Push(z)
|
||||||
|
dbg.Printf(" %X | %X = %X\n", x, y, z)
|
||||||
|
|
||||||
case XOR: // 0x18
|
case XOR: // 0x18
|
||||||
x, y := stack.Pop64(), stack.Pop64()
|
x, y := stack.Pop(), stack.Pop()
|
||||||
stack.Push64(x ^ y)
|
z := [32]byte{}
|
||||||
dbg.Printf(" %v ^ %v = %v\n", x, y, x^y)
|
for i := 0; i < 32; i++ {
|
||||||
|
z[i] = x[i] ^ y[i]
|
||||||
|
}
|
||||||
|
stack.Push(z)
|
||||||
|
dbg.Printf(" %X ^ %X = %X\n", x, y, z)
|
||||||
|
|
||||||
case NOT: // 0x19
|
case NOT: // 0x19
|
||||||
x := stack.Pop64()
|
x := stack.Pop()
|
||||||
stack.Push64(^x)
|
z := [32]byte{}
|
||||||
dbg.Printf(" !%v = %v\n", x, ^x)
|
for i := 0; i < 32; i++ {
|
||||||
|
z[i] = ^x[i]
|
||||||
|
}
|
||||||
|
stack.Push(z)
|
||||||
|
dbg.Printf(" !%X = %X\n", x, z)
|
||||||
|
|
||||||
case BYTE: // 0x1A
|
case BYTE: // 0x1A
|
||||||
idx, val := stack.Pop64(), stack.Pop()
|
idx, val := stack.Pop64(), stack.Pop()
|
||||||
|
@ -347,24 +394,24 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
return nil, firstErr(err, ErrInsufficientGas)
|
return nil, firstErr(err, ErrInsufficientGas)
|
||||||
}
|
}
|
||||||
offset, size := stack.Pop64(), stack.Pop64()
|
offset, size := stack.Pop64(), stack.Pop64()
|
||||||
data, ok := subslice(memory, offset, size, false)
|
data, ok := subslice(memory, offset, size)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
data = sha3.Sha3(data)
|
data = sha3.Sha3(data)
|
||||||
stack.PushBytes(flip(data))
|
stack.PushBytes(data)
|
||||||
dbg.Printf(" => (%v) %X\n", size, data)
|
dbg.Printf(" => (%v) %X\n", size, data)
|
||||||
|
|
||||||
case ADDRESS: // 0x30
|
case ADDRESS: // 0x30
|
||||||
stack.Push(flipWord(callee.Address))
|
stack.Push(callee.Address)
|
||||||
dbg.Printf(" => %X\n", flipWord(callee.Address))
|
dbg.Printf(" => %X\n", callee.Address)
|
||||||
|
|
||||||
case BALANCE: // 0x31
|
case BALANCE: // 0x31
|
||||||
addr := stack.Pop()
|
addr := stack.Pop()
|
||||||
if ok = useGas(gas, GasGetAccount); !ok {
|
if ok = useGas(gas, GasGetAccount); !ok {
|
||||||
return nil, firstErr(err, ErrInsufficientGas)
|
return nil, firstErr(err, ErrInsufficientGas)
|
||||||
}
|
}
|
||||||
acc := vm.appState.GetAccount(flipWord(addr)) // TODO ensure that 20byte lengths are supported.
|
acc := vm.appState.GetAccount(addr)
|
||||||
if acc == nil {
|
if acc == nil {
|
||||||
return nil, firstErr(err, ErrUnknownAddress)
|
return nil, firstErr(err, ErrUnknownAddress)
|
||||||
}
|
}
|
||||||
|
@ -373,12 +420,12 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
dbg.Printf(" => %v (%X)\n", balance, addr)
|
dbg.Printf(" => %v (%X)\n", balance, addr)
|
||||||
|
|
||||||
case ORIGIN: // 0x32
|
case ORIGIN: // 0x32
|
||||||
stack.Push(flipWord(vm.origin))
|
stack.Push(vm.origin)
|
||||||
dbg.Printf(" => %X\n", flipWord(vm.origin))
|
dbg.Printf(" => %X\n", vm.origin)
|
||||||
|
|
||||||
case CALLER: // 0x33
|
case CALLER: // 0x33
|
||||||
stack.Push(flipWord(caller.Address))
|
stack.Push(caller.Address)
|
||||||
dbg.Printf(" => %X\n", flipWord(caller.Address))
|
dbg.Printf(" => %X\n", caller.Address)
|
||||||
|
|
||||||
case CALLVALUE: // 0x34
|
case CALLVALUE: // 0x34
|
||||||
stack.Push64(value)
|
stack.Push64(value)
|
||||||
|
@ -386,12 +433,13 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
|
|
||||||
case CALLDATALOAD: // 0x35
|
case CALLDATALOAD: // 0x35
|
||||||
offset := stack.Pop64()
|
offset := stack.Pop64()
|
||||||
data, ok := subslice(input, offset, 32, true)
|
data, ok := subslice(input, offset, 32)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrInputOutOfBounds)
|
return nil, firstErr(err, ErrInputOutOfBounds)
|
||||||
}
|
}
|
||||||
stack.Push(RightPadWord256(data))
|
res := LeftPadWord256(data)
|
||||||
dbg.Printf(" => 0x%X\n", RightPadWord256(data))
|
stack.Push(res)
|
||||||
|
dbg.Printf(" => 0x%X\n", res)
|
||||||
|
|
||||||
case CALLDATASIZE: // 0x36
|
case CALLDATASIZE: // 0x36
|
||||||
stack.Push64(uint64(len(input)))
|
stack.Push64(uint64(len(input)))
|
||||||
|
@ -401,11 +449,11 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
memOff := stack.Pop64()
|
memOff := stack.Pop64()
|
||||||
inputOff := stack.Pop64()
|
inputOff := stack.Pop64()
|
||||||
length := stack.Pop64()
|
length := stack.Pop64()
|
||||||
data, ok := subslice(input, inputOff, length, false)
|
data, ok := subslice(input, inputOff, length)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrInputOutOfBounds)
|
return nil, firstErr(err, ErrInputOutOfBounds)
|
||||||
}
|
}
|
||||||
dest, ok := subslice(memory, memOff, length, false)
|
dest, ok := subslice(memory, memOff, length)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
|
@ -421,11 +469,11 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
memOff := stack.Pop64()
|
memOff := stack.Pop64()
|
||||||
codeOff := stack.Pop64()
|
codeOff := stack.Pop64()
|
||||||
length := stack.Pop64()
|
length := stack.Pop64()
|
||||||
data, ok := subslice(code, codeOff, length, false)
|
data, ok := subslice(code, codeOff, length)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrCodeOutOfBounds)
|
return nil, firstErr(err, ErrCodeOutOfBounds)
|
||||||
}
|
}
|
||||||
dest, ok := subslice(memory, memOff, length, false)
|
dest, ok := subslice(memory, memOff, length)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
|
@ -441,7 +489,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
if ok = useGas(gas, GasGetAccount); !ok {
|
if ok = useGas(gas, GasGetAccount); !ok {
|
||||||
return nil, firstErr(err, ErrInsufficientGas)
|
return nil, firstErr(err, ErrInsufficientGas)
|
||||||
}
|
}
|
||||||
acc := vm.appState.GetAccount(flipWord(addr))
|
acc := vm.appState.GetAccount(addr)
|
||||||
if acc == nil {
|
if acc == nil {
|
||||||
return nil, firstErr(err, ErrUnknownAddress)
|
return nil, firstErr(err, ErrUnknownAddress)
|
||||||
}
|
}
|
||||||
|
@ -455,7 +503,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
if ok = useGas(gas, GasGetAccount); !ok {
|
if ok = useGas(gas, GasGetAccount); !ok {
|
||||||
return nil, firstErr(err, ErrInsufficientGas)
|
return nil, firstErr(err, ErrInsufficientGas)
|
||||||
}
|
}
|
||||||
acc := vm.appState.GetAccount(flipWord(addr))
|
acc := vm.appState.GetAccount(addr)
|
||||||
if acc == nil {
|
if acc == nil {
|
||||||
return nil, firstErr(err, ErrUnknownAddress)
|
return nil, firstErr(err, ErrUnknownAddress)
|
||||||
}
|
}
|
||||||
|
@ -463,11 +511,11 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
memOff := stack.Pop64()
|
memOff := stack.Pop64()
|
||||||
codeOff := stack.Pop64()
|
codeOff := stack.Pop64()
|
||||||
length := stack.Pop64()
|
length := stack.Pop64()
|
||||||
data, ok := subslice(code, codeOff, length, false)
|
data, ok := subslice(code, codeOff, length)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrCodeOutOfBounds)
|
return nil, firstErr(err, ErrCodeOutOfBounds)
|
||||||
}
|
}
|
||||||
dest, ok := subslice(memory, memOff, length, false)
|
dest, ok := subslice(memory, memOff, length)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
|
@ -502,20 +550,20 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
|
|
||||||
case MLOAD: // 0x51
|
case MLOAD: // 0x51
|
||||||
offset := stack.Pop64()
|
offset := stack.Pop64()
|
||||||
data, ok := subslice(memory, offset, 32, true)
|
data, ok := subslice(memory, offset, 32)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
stack.Push(RightPadWord256(data))
|
stack.Push(LeftPadWord256(data))
|
||||||
dbg.Printf(" => 0x%X\n", data)
|
dbg.Printf(" => 0x%X\n", data)
|
||||||
|
|
||||||
case MSTORE: // 0x52
|
case MSTORE: // 0x52
|
||||||
offset, data := stack.Pop64(), stack.Pop()
|
offset, data := stack.Pop64(), stack.Pop()
|
||||||
dest, ok := subslice(memory, offset, 32, false)
|
dest, ok := subslice(memory, offset, 32)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
copy(dest, flip(data[:]))
|
copy(dest, data[:])
|
||||||
dbg.Printf(" => 0x%X\n", data)
|
dbg.Printf(" => 0x%X\n", data)
|
||||||
|
|
||||||
case MSTORE8: // 0x53
|
case MSTORE8: // 0x53
|
||||||
|
@ -543,8 +591,8 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case JUMPI: // 0x57
|
case JUMPI: // 0x57
|
||||||
pos, cond := stack.Pop64(), stack.Pop64()
|
pos, cond := stack.Pop64(), stack.Pop()
|
||||||
if cond >= 1 {
|
if !cond.IsZero() {
|
||||||
err = jump(code, pos, &pc)
|
err = jump(code, pos, &pc)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -566,14 +614,15 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
|
|
||||||
case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
|
case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
|
||||||
a := uint64(op - PUSH1 + 1)
|
a := uint64(op - PUSH1 + 1)
|
||||||
codeSegment, ok := subslice(code, pc+1, a, true)
|
codeSegment, ok := subslice(code, pc+1, a)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrCodeOutOfBounds)
|
return nil, firstErr(err, ErrCodeOutOfBounds)
|
||||||
}
|
}
|
||||||
res := RightPadWord256(codeSegment)
|
res := LeftPadWord256(codeSegment)
|
||||||
stack.Push(res)
|
stack.Push(res)
|
||||||
pc += a
|
pc += a
|
||||||
dbg.Printf(" => 0x%X\n", res)
|
dbg.Printf(" => 0x%X\n", res)
|
||||||
|
stack.Print(10)
|
||||||
|
|
||||||
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
|
case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
|
||||||
n := int(op - DUP1 + 1)
|
n := int(op - DUP1 + 1)
|
||||||
|
@ -583,7 +632,8 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
|
case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
|
||||||
n := int(op - SWAP1 + 2)
|
n := int(op - SWAP1 + 2)
|
||||||
stack.Swap(n)
|
stack.Swap(n)
|
||||||
dbg.Printf(" => [%d]\n", n)
|
dbg.Printf(" => [%d] %X\n", n, stack.Peek())
|
||||||
|
stack.Print(10)
|
||||||
|
|
||||||
case LOG0, LOG1, LOG2, LOG3, LOG4:
|
case LOG0, LOG1, LOG2, LOG3, LOG4:
|
||||||
n := int(op - LOG0)
|
n := int(op - LOG0)
|
||||||
|
@ -592,7 +642,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
topics[i] = stack.Pop()
|
topics[i] = stack.Pop()
|
||||||
}
|
}
|
||||||
data, ok := subslice(memory, offset, size, false)
|
data, ok := subslice(memory, offset, size)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
|
@ -608,7 +658,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
case CREATE: // 0xF0
|
case CREATE: // 0xF0
|
||||||
contractValue := stack.Pop64()
|
contractValue := stack.Pop64()
|
||||||
offset, size := stack.Pop64(), stack.Pop64()
|
offset, size := stack.Pop64(), stack.Pop64()
|
||||||
input, ok := subslice(memory, offset, size, false)
|
input, ok := subslice(memory, offset, size)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
|
@ -627,7 +677,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
} else {
|
} else {
|
||||||
newAccount.Code = ret // Set the code
|
newAccount.Code = ret // Set the code
|
||||||
stack.Push(flipWord(newAccount.Address))
|
stack.Push(newAccount.Address)
|
||||||
}
|
}
|
||||||
|
|
||||||
case CALL, CALLCODE: // 0xF1, 0xF2
|
case CALL, CALLCODE: // 0xF1, 0xF2
|
||||||
|
@ -638,7 +688,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
dbg.Printf(" => %X\n", addr)
|
dbg.Printf(" => %X\n", addr)
|
||||||
|
|
||||||
// Get the arguments from the memory
|
// Get the arguments from the memory
|
||||||
args, ok := subslice(memory, inOffset, inSize, false)
|
args, ok := subslice(memory, inOffset, inSize)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
|
@ -662,7 +712,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
if ok = useGas(gas, GasGetAccount); !ok {
|
if ok = useGas(gas, GasGetAccount); !ok {
|
||||||
return nil, firstErr(err, ErrInsufficientGas)
|
return nil, firstErr(err, ErrInsufficientGas)
|
||||||
}
|
}
|
||||||
acc := vm.appState.GetAccount(flipWord(addr))
|
acc := vm.appState.GetAccount(addr)
|
||||||
if acc == nil {
|
if acc == nil {
|
||||||
return nil, firstErr(err, ErrUnknownAddress)
|
return nil, firstErr(err, ErrUnknownAddress)
|
||||||
}
|
}
|
||||||
|
@ -678,7 +728,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
stack.Push(Zero256)
|
stack.Push(Zero256)
|
||||||
} else {
|
} else {
|
||||||
stack.Push(One256)
|
stack.Push(One256)
|
||||||
dest, ok := subslice(memory, retOffset, retSize, false)
|
dest, ok := subslice(memory, retOffset, retSize)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
|
@ -692,7 +742,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
|
|
||||||
case RETURN: // 0xF3
|
case RETURN: // 0xF3
|
||||||
offset, size := stack.Pop64(), stack.Pop64()
|
offset, size := stack.Pop64(), stack.Pop64()
|
||||||
ret, ok := subslice(memory, offset, size, false)
|
ret, ok := subslice(memory, offset, size)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
|
@ -705,7 +755,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
return nil, firstErr(err, ErrInsufficientGas)
|
return nil, firstErr(err, ErrInsufficientGas)
|
||||||
}
|
}
|
||||||
// TODO if the receiver is , then make it the fee.
|
// TODO if the receiver is , then make it the fee.
|
||||||
receiver := vm.appState.GetAccount(flipWord(addr))
|
receiver := vm.appState.GetAccount(addr)
|
||||||
if receiver == nil {
|
if receiver == nil {
|
||||||
return nil, firstErr(err, ErrUnknownAddress)
|
return nil, firstErr(err, ErrUnknownAddress)
|
||||||
}
|
}
|
||||||
|
@ -726,7 +776,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value uint64, ga
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func subslice(data []byte, offset, length uint64, flip_ bool) (ret []byte, ok bool) {
|
func subslice(data []byte, offset, length uint64) (ret []byte, ok bool) {
|
||||||
size := uint64(len(data))
|
size := uint64(len(data))
|
||||||
if size < offset {
|
if size < offset {
|
||||||
return nil, false
|
return nil, false
|
||||||
|
@ -737,9 +787,6 @@ func subslice(data []byte, offset, length uint64, flip_ bool) (ret []byte, ok bo
|
||||||
ret, ok = data[offset:offset+length], true
|
ret, ok = data[offset:offset+length], true
|
||||||
}
|
}
|
||||||
|
|
||||||
if flip_ {
|
|
||||||
ret = flip(ret)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -794,27 +841,3 @@ func transfer(from, to *Account, amount uint64) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func flip(in []byte) []byte {
|
|
||||||
l2 := len(in) / 2
|
|
||||||
flipped := make([]byte, len(in))
|
|
||||||
// copy the middle bit (if its even it will get overwritten)
|
|
||||||
if len(in) != 0 {
|
|
||||||
flipped[l2] = in[l2]
|
|
||||||
}
|
|
||||||
for i := 0; i < l2; i++ {
|
|
||||||
flipped[i] = in[len(in)-1-i]
|
|
||||||
flipped[len(in)-1-i] = in[i]
|
|
||||||
}
|
|
||||||
return flipped
|
|
||||||
}
|
|
||||||
|
|
||||||
func flipWord(in Word256) Word256 {
|
|
||||||
word := Word256{}
|
|
||||||
// copy the middle bit (if its even it will get overwritten)
|
|
||||||
for i := 0; i < 16; i++ {
|
|
||||||
word[i] = in[len(in)-1-i]
|
|
||||||
word[len(in)-1-i] = in[i]
|
|
||||||
}
|
|
||||||
return word
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue