1. 执行结果
personal.unlockAccount("0xd4c3b95bf0bbf0fd0087062125dd572114ded44f")
Unlock account 0xd4c3b95bf0bbf0fd0087062125dd572114ded44f
Passphrase:
true
2. 数据结构
type KeyStore struct {
unlocked map[common.Address]*unlocked // Currently unlocked account (decrypted private keys)
}
3.源码
- 计算时间长度
- 通过密码解密
- 解锁帐户添加至 KeyStore.unlocked
3.1. go-ethereum/internal/ethapi/api.go
func (s *PrivateAccountAPI) UnlockAccount(addr common.Address, password string, duration *uint64) (bool, error) {
const max = uint64(time.Duration(math.MaxInt64) / time.Second)
var d time.Duration //维持多长时间
if duration == nil {
d = 300 * time.Second
} else if *duration > max {
return false, errors.New("unlock duration too large")
} else {
d = time.Duration(*duration) * time.Second
}
err := fetchKeystore(s.am).TimedUnlock(accounts.Account{Address: addr}, password, d)
return err == nil, err
}
3.2. go-ethereum/accounts/keystore/keystore.go
func (ks *KeyStore) TimedUnlock(a accounts.Account, passphrase string, timeout time.Duration) error {
a, key, err := ks.getDecryptedKey(a, passphrase) //解密
if err != nil {
return err
}
ks.mu.Lock()
defer ks.mu.Unlock()
u, found := ks.unlocked[a.Address]
if found { //如果已经unlock
if u.abort == nil {
// The address was unlocked indefinitely, so unlocking
// it with a timeout would be confusing.
zeroKey(key.PrivateKey)
return nil
}
// Terminate the expire goroutine and replace it below.
close(u.abort)
}
if timeout > 0 {
u = &unlocked{Key: key, abort: make(chan struct{})}
go ks.expire(a.Address, u, timeout) //开启监听, unlock时间长度是否到达
} else {
u = &unlocked{Key: key} //没有时间长度限制
}
ks.unlocked[a.Address] = u
return nil
}